spring-security-kerberos icon indicating copy to clipboard operation
spring-security-kerberos copied to clipboard

NotSerializableException on JaasSubjectHolder

Open ogoedhart opened this issue 1 year ago • 4 comments

Summary With version 2.0.0 a serialization exception is introduced.

Explanation The org.springframework.security.kerberos.authentication.KerberosServiceRequestToken extends the AbstractAuthenticationToken which implements Authentication (extends Serializable).

The KerberosServiceRequestToken holds an org.springframework.security.kerberos.authentication.JaasSubjectHolder which is not Serializable (and the field is not transient). And therefore (in our case) spring-session-jdbc throws a NotSerializableException while trying to serialize the object.

Spring session jdbc tries to store the SecurityContextImpl which extends Serializable (refer to SecurityContextImpl docs)

The SecurityContextImpl holds a org.springframework.security.core.Authentication object (in our case the KerberosServiceRequestToken.

Suggestion The field private JaasSubjectHolder jaasSubjectHolder on KerberosServiceRequestToken should be transient or the Object JaasSubjectHolder should extends Serializable. I'm not sure about the actual solution and implication on the rest.

ogoedhart avatar Jun 07 '23 09:06 ogoedhart

Have the exact same problem with Spring Boot 3.1.1/Security;6.1.1/Kerberos:2.0.0

Martj89 avatar Aug 25 '23 08:08 Martj89

Same problem here:

Describe the bug spring-security-kerberos-core, 2.0.0 introduced org.springframework.security.kerberos.authentication.JaasSubjectHolder.

This object wasn't in spring-security-kerberos-core, 1.0.1-RELEASE version, which used other object:

  • Class org.springframework.security.kerberos.authentication.KerberosAuthenticationProvider was not using JaasSubjectHolder.

Since 2.0.0, KerberosAuthenticationProvider started using JaasSubjectHolder.

Therefore, if Spring Security session management stores object into session, it has to be Serializable. Especially, if session is backed by Redis, for example.

To Reproduce Use: .sessionManagement(management -> management .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED))

  • store session in Redis.

Expected behavior No exception.

Sample No sample provided, quite obvious reasoning.

Stacktrace

org.springframework.data.redis.serializer.SerializationException: Cannot serialize
        at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.serialize(JdkSerializationRedisSerializer.java:96)
        at org.springframework.data.redis.core.AbstractOperations.rawHashValue(AbstractOperations.java:186)
        at org.springframework.data.redis.core.DefaultHashOperations.putAll(DefaultHashOperations.java:161)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:568)
        at org.springframework.data.redis.core.BoundOperationsProxyFactory$BoundOperationsMethodInterceptor.doInvoke(BoundOperationsProxyFactory.java:183)
        at org.springframework.data.redis.core.BoundOperationsProxyFactory$BoundOperationsMethodInterceptor.invoke(BoundOperationsProxyFactory.java:153)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
        at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:72)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:244)
        at jdk.proxy3/jdk.proxy3.$Proxy186.putAll(Unknown Source)
        at org.springframework.session.data.redis.RedisIndexedSessionRepository$RedisSession.saveDelta(RedisIndexedSessionRepository.java:852)
        at org.springframework.session.data.redis.RedisIndexedSessionRepository$RedisSession.save(RedisIndexedSessionRepository.java:840)
        at org.springframework.session.data.redis.RedisIndexedSessionRepository.save(RedisIndexedSessionRepository.java:478)
        at org.springframework.session.data.redis.RedisIndexedSessionRepository.save(RedisIndexedSessionRepository.java:258)
        at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.commitSession(SessionRepositoryFilter.java:228)
        at org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:146)
        at org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:82)
        at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:352)
        at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:268)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
        at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:642)
        at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:410)
        at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:340)
        at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:277)
        at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:358)
        at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:222)
        at org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:304)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:149)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:341)
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:391)
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:894)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1740)
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
        at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
        at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer
        at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:64)
        at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:33)
        at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.serialize(JdkSerializationRedisSerializer.java:94)
        ... 47 common frames omitted
Caused by: java.io.NotSerializableException: org.springframework.security.kerberos.authentication.JaasSubjectHolder
        at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1187)
        at java.base/java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1572)
        at java.base/java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1529)
        at java.base/java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1438)
        at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1181)
        at java.base/java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1572)
        at java.base/java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1529)
        at java.base/java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1438)
        at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1181)
        at java.base/java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:350)
        at org.springframework.core.serializer.DefaultSerializer.serialize(DefaultSerializer.java:46)
        at org.springframework.core.serializer.Serializer.serializeToByteArray(Serializer.java:56)
        at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:60)
        ... 49 common frames omitted

rstribrn avatar Aug 28 '23 18:08 rstribrn

I've created a pull request with fix proposal. Hopefully it will work in all scenarios (I tried comparing all changes between 1.0.1-RELEASE and 2.0.0, and added also serialVersionUID to another class where it was missing).

rstribrn avatar Aug 28 '23 18:08 rstribrn

BTW:

Until its merged, this is working for me:

		<dependency>
			<groupId>org.springframework.security.kerberos</groupId>
			<artifactId>spring-security-kerberos-client</artifactId>
			<version>2.0.0</version>
		</dependency>
		<!-- Hold on 1.0.1-RELEASE, version 2.0.0 waits for:
		     - https://github.com/spring-projects/spring-security-kerberos/issues/178
		-->
		<dependency>
			<groupId>org.springframework.security.kerberos</groupId>
			<artifactId>spring-security-kerberos-core</artifactId>
			<version>1.0.1.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.security.kerberos</groupId>
			<artifactId>spring-security-kerberos-web</artifactId>
			<version>2.0.0</version>
		</dependency>

rstribrn avatar Aug 28 '23 18:08 rstribrn