spring-attic / spring-security-oauth

Support for adding OAuth1(a) and OAuth2 features (consumer and provider) for Spring web applications.
http://github.com/spring-projects/spring-security-oauth
Apache License 2.0
4.69k stars 4.05k forks source link

Get NotSerializableException from JdbcTokenStore on login / version 2.3.7 #1782

Closed anhefti closed 4 years ago

anhefti commented 4 years ago

Hi, we have a Spring Boot application with an REST API that uses OAuth2 authentication. The application also uses JDBCTokenstore to store access- and refresh-tokens in a database.

This was working fine until we get the update to spring-security-oauth 2.3.7.RELEASE. Since then we always get a java.io.NotSerializableException exception on login.

After some research I came across the changes within SerializationUtils class. It seems that this is now far more restrictive on deserializing. Only classes form java.lang, java.util and spring.security are allowed. Since we use our own implementations of UserDetails and GrantedAuthority this is causing an error now on deserialization within SerializationUtils. See exception for more details.

My Question; is this bad practice, to have own implementations of UserDetails and GrantedAuthority and because only the spring implementations will work in the future, we will have to refactor our application to work with them. Or is there another way to solve this issue. Some kind of interception for example?

Our workaround so far is, to stick with the version 3.2.6. But for the future we need a better solution.

Thanks, Andreas Hefti

Exception:

java.lang.IllegalArgumentException: java.io.NotSerializableException: Not allowed to deserialize ch.ethz.seb.sebserver.webservice.servicelayer.authorization.impl.SEBServerUser seb-server | at org.springframework.security.oauth2.common.util.SerializationUtils.deserialize(SerializationUtils.java:66) seb-server | at org.springframework.security.oauth2.provider.token.store.JdbcTokenStore.deserializeAuthentication(JdbcTokenStore.java:405) seb-server | at org.springframework.security.oauth2.provider.token.store.JdbcTokenStore$3.mapRow(JdbcTokenStore.java:198) seb-server | at org.springframework.security.oauth2.provider.token.store.JdbcTokenStore$3.mapRow(JdbcTokenStore.java:196) seb-server | at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:94) seb-server | at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:61) seb-server | at org.springframework.jdbc.core.JdbcTemplate$1.doInPreparedStatement(JdbcTemplate.java:679) seb-server | at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:617) seb-server | at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:669) seb-server | at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:700) seb-server | at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:712) seb-server | at org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:790) seb-server | at org.springframework.security.oauth2.provider.token.store.JdbcTokenStore.readAuthentication(JdbcTokenStore.java:195) seb-server | at org.springframework.security.oauth2.provider.token.store.JdbcTokenStore.readAuthentication(JdbcTokenStore.java:188) seb-server | at ch.ethz.seb.sebserver.webservice.weblayer.oauth.CachableJdbcTokenStore.readAuthentication(CachableJdbcTokenStore.java:63) seb-server | at ch.ethz.seb.sebserver.webservice.weblayer.oauth.CachableJdbcTokenStore$$FastClassBySpringCGLIB$$379b4ff8.invoke(<generated>) seb-server | at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) seb-server | at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:746) seb-server | at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) seb-server | at org.springframework.cache.interceptor.CacheInterceptor.lambda$invoke$0(CacheInterceptor.java:53) seb-server | at org.springframework.cache.interceptor.CacheAspectSupport.invokeOperation(CacheAspectSupport.java:365) seb-server | at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:420) seb-server | at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:345) seb-server | at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:61) seb-server | at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) seb-server | at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) seb-server | at ch.ethz.seb.sebserver.webservice.weblayer.oauth.CachableJdbcTokenStore$$EnhancerBySpringCGLIB$$60149504.readAuthentication(<generated>) seb-server | at org.springframework.security.oauth2.provider.token.DefaultTokenServices.loadAuthentication(DefaultTokenServices.java:238) seb-server | at org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationManager.authenticate(OAuth2AuthenticationManager.java:83) seb-server | at org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter.doFilter(OAuth2AuthenticationProcessingFilter.java:150) seb-server | at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) seb-server | at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:66) seb-server | at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) seb-server | at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) seb-server | at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) seb-server | at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) seb-server | at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) seb-server | at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) seb-server | at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) seb-server | at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) seb-server | at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) seb-server | at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357) seb-server | at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270) seb-server | at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) seb-server | at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) seb-server | at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) seb-server | at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) seb-server | at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) seb-server | at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) seb-server | at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92) seb-server | at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) seb-server | at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) seb-server | at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) seb-server | at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93) seb-server | at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) seb-server | at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) seb-server | at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) seb-server | at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:154) seb-server | at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:122) seb-server | at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:107) seb-server | at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) seb-server | at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) seb-server | at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) seb-server | at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) seb-server | at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) seb-server | at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) seb-server | at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) seb-server | at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199) seb-server | at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) seb-server | at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490) seb-server | at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) seb-server | at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) seb-server | at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) seb-server | at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) seb-server | at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408) seb-server | at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) seb-server | at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:770) seb-server | at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415) seb-server | at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) seb-server | at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) seb-server | at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) seb-server | at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) seb-server | at java.base/java.lang.Thread.run(Unknown Source) seb-server | Caused by: java.io.NotSerializableException: Not allowed to deserialize ch.ethz.seb.sebserver.webservice.servicelayer.authorization.impl.SEBServerUser seb-server | at org.springframework.security.oauth2.common.util.SerializationUtils$SaferObjectInputStream.resolveClass(SerializationUtils.java:125) seb-server | at java.base/java.io.ObjectInputStream.readNonProxyDesc(Unknown Source) seb-server | at java.base/java.io.ObjectInputStream.readClassDesc(Unknown Source) seb-server | at java.base/java.io.ObjectInputStream.readOrdinaryObject(Unknown Source) seb-server | at java.base/java.io.ObjectInputStream.readObject0(Unknown Source) seb-server | at java.base/java.io.ObjectInputStream.defaultReadFields(Unknown Source) seb-server | at java.base/java.io.ObjectInputStream.readSerialData(Unknown Source) seb-server | at java.base/java.io.ObjectInputStream.readOrdinaryObject(Unknown Source) seb-server | at java.base/java.io.ObjectInputStream.readObject0(Unknown Source) seb-server | at java.base/java.io.ObjectInputStream.defaultReadFields(Unknown Source) seb-server | at java.base/java.io.ObjectInputStream.readSerialData(Unknown Source) seb-server | at java.base/java.io.ObjectInputStream.readOrdinaryObject(Unknown Source) seb-server | at java.base/java.io.ObjectInputStream.readObject0(Unknown Source) seb-server | at java.base/java.io.ObjectInputStream.readObject(Unknown Source) seb-server | at org.springframework.security.oauth2.common.util.SerializationUtils.deserialize(SerializationUtils.java:62) seb-server | ... 82 common frames omitted

Noxaro commented 4 years ago

I've the same problem for the RedisTokenStore. The SerializationUtils have a ALLOWED_CLASS List with classes which can be serialized / deserialized. Looks like this Whitelist is the problem...

jgrandja commented 4 years ago

@anhefti @Noxaro Please see #1785