Search code examples
spring-cloudspring-security-oauth2spring-session

Trouble saving session when mixing spring-security-gemfire and spring-security-oauth2


Background: I have a web app that utilizes AngularJS, spring-mvc, and spring-rest for delivering the UI. I have a requirement to load balance using an Elastic LB and it is not using sticky sessions; requests are round robin. I implemented session replication using spring-session with gemfire for session storage. This works well.

I need to integrate with an OAuth2 auth server (and eventually multiple OAuth2 servers) purely for authentication and the passing of userInfo. I attempted to use the spring cloud oauth2 @EnableOAuth2Sso on the web-app and hit some session serialization issues. The mere addition of the oauth2ClientContext to the session seemed to cause ClassCastException problems during session saving.

I attempted to pull down the following samples and they worked well out of the box, Particularly the UI and the Authserver.
https://github.com/spring-guides/tut-spring-security-and-angular-js

However, when I added spring session into the mix, trying to serialize to a gemfire server, I encountered the exact same issue.

Here is the stacktrace highlight:

java.lang.ClassCastException: cannot assign instance of org.springframework.beans.factory.support.StaticListableBeanFactory to field org.springframework.aop.scope.DefaultScopedObject.beanFactory of type org.springframework.beans.factory.config.ConfigurableBeanFactory in instance of org.springframework.aop.scope.DefaultScopedObject

Below is abbreviated stacktrace:

ERROR o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception

org.springframework.dao.DataAccessResourceFailureException: remote server on machine(gemfire:21800:loner):57660:9d1f3438:gemfire: : While performing a remote put; nested exception is com.gemstone.gemfire.cache.client.ServerOperationException: remote server on machine(gemfire:21800:loner):57660:9d1f3438:gemfire: : While performing a remote put
    at org.springframework.data.gemfire.GemfireCacheUtils.convertGemfireAccessException(GemfireCacheUtils.java:238) ~[spring-data-gemfire-1.7.4.RELEASE.jar:1.7.4.RELEASE]
    at org.springframework.data.gemfire.GemfireAccessor.convertGemFireAccessException(GemfireAccessor.java:91) ~[spring-data-gemfire-1.7.4.RELEASE.jar:1.7.4.RELEASE]
    at org.springframework.data.gemfire.GemfireTemplate.put(GemfireTemplate.java:190) ~[spring-data-gemfire-1.7.4.RELEASE.jar:1.7.4.RELEASE]
    at org.springframework.session.data.gemfire.GemFireOperationsSessionRepository.save(GemFireOperationsSessionRepository.java:147) ~[spring-session-1.2.1.RELEASE.jar:na]
    at org.springframework.session.data.gemfire.GemFireOperationsSessionRepository.save(GemFireOperationsSessionRepository.java:35) ~[spring-session-1.2.1.RELEASE.jar:na]
    at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.commitSession(SessionRepositoryFilter.java:244) ~[spring-session-1.2.1.RELEASE.jar:na]
    at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.access$100(SessionRepositoryFilter.java:214) ~[spring-session-1.2.1.RELEASE.jar:na]
    at org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:167) ~[spring-session-1.2.1.RELEASE.jar:na]
    at org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:80) ~[spring-session-1.2.1.RELEASE.jar:na]
    ... tomcat filter chain and spring filter stuff
Caused by: com.gemstone.gemfire.cache.client.ServerOperationException: remote server on machine(gemfire:21800:loner):57660:9d1f3438:gemfire: : While performing a remote put
    ... gemfire internal stuff
    at org.springframework.data.gemfire.GemfireTemplate.put(GemfireTemplate.java:187) ~[spring-data-gemfire-1.7.4.RELEASE.jar:1.7.4.RELEASE]
    ... 31 common frames omitted
Caused by: java.lang.ClassCastException: cannot assign instance of org.springframework.beans.factory.support.StaticListableBeanFactory to field org.springframework.aop.scope.DefaultScopedObject.beanFactory of type org.springframework.beans.factory.config.ConfigurableBeanFactory in instance of org.springframework.aop.scope.DefaultScopedObject
    at java.io.ObjectStreamClass$FieldReflector.setObjFieldValues(ObjectStreamClass.java:2133) ~[na:1.7.0_80]
    at java.io.ObjectStreamClass.setObjFieldValues(ObjectStreamClass.java:1305) ~[na:1.7.0_80]
    ... java.io stuff
    at org.springframework.aop.framework.AdvisedSupport.readObject(AdvisedSupport.java:557) ~[spring-aop-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at sun.reflect.GeneratedMethodAccessor224.invoke(Unknown Source) ~[na:na]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.7.0_80]
    at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.7.0_80]
    at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1058) ~[na:1.7.0_80]
    ... java.io stuff
    at com.gemstone.gemfire.internal.InternalDataSerializer.basicReadObject(InternalDataSerializer.java:2966) ~[gemfire-8.1.0.jar:na]
    at com.gemstone.gemfire.DataSerializer.readObject(DataSerializer.java:3210) ~[gemfire-8.1.0.jar:na]
    at org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository$GemFireSessionAttributes.readObject(AbstractGemFireOperationsSessionRepository.java:800) ~[spring-session-1.2.1.RELEASE.jar:na]
    at org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository$GemFireSessionAttributes.fromDelta(AbstractGemFireOperationsSessionRepository.java:834) ~[spring-session-1.2.1.RELEASE.jar:na]
    at org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository$GemFireSession.fromDelta(AbstractGemFireOperationsSessionRepository.java:589) ~[spring-session-1.2.1.RELEASE.jar:na]
    at com.gemstone.gemfire.internal.cache.EntryEventImpl.processDeltaBytes(EntryEventImpl.java:1345) ~[gemfire-8.1.0.jar:na]
    ... gemfire internal stuff
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.7.0_80]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.7.0_80]
    at com.gemstone.gemfire.internal.cache.tier.sockets.AcceptorImpl$1$1.run(AcceptorImpl.java:577) ~[gemfire-8.1.0.jar:na]
    ... 1 common frames omitted

I found the following, https://jira.spring.io/browse/SPR-14117, which encouraged me to update some of the jars to the newest versions, hoping the spring boot versions were simply behind, however it didn't seem to help.

Version info:

spring-cloud-starter-parent: Brixton.SR4 spring-cloud-security: 1.1.2.RELEASE spring-core: 4.3.2.RELEASE spring-security-oauth2: 2.0.10.RELEASE spring-session: 1.2.1.RELEASE

I've considered a few options: rewiring the OAuth2 framework to no longer use ScopedProxyMode.INTERFACES (seems daunting), use Redis vs. Gemfire, write the entire client from scratch (I've done it before... wasn't fun).

FWIW I've already added the RequestContextFilter as recommended here: OAuth2ClientContext (spring-security-oauth2) not persisted in Redis when using spring-session and spring-cloud-security

Does anyone have any guidance?


Solution

  • I don't know if this speaks to your problem directly but I had/have a similar problem and I think I have all the same versions as you. Seems that there are so many Spring projects and they all try to keep up with each other so sometimes there seem to be compatibility issues. I found the steps outlined here by Rob Winch fixed my issue -https://github.com/spring-projects/spring-session/issues/395