-
Notifications
You must be signed in to change notification settings - Fork 706
GenericScope.setSerializationId can cause serialization issues #93
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I'm not 100 percent sure I follow (and the steps to reproduce are a little unclear, since the GitHub repo is from a tutorial with dozens of apps). Is it broken when you put an object that is in |
@dsyer Sorry for being unclear.
I updated the description. The issue is demonstrated by starting oauth2/resource oauth2/ui and oauth2/authserver/ (these are the apps that were modified in the branches that were mentioned)
No. The application is broken because Spring Security OAuth uses Session Scope objects which means they are placed in session. Since the RefreshScope is changing the serialization id it breaks serialization deserialization of the session scope beans. This can be seen if you try to use Spring Session & Spring Security OAuth across multiple applications when Spring Cloud is used in one application. It can also be seen if you restart a Spring Cloud application that stores session scope bean using Spring Session since the id changes between restarts. I should add that this isn't just Spring Session as it is generically JDK serialization/deserialization of the session scope objects when the serializationId is changed. |
OK, I see. It's been a problem lurking there for a long time. Only when you start to share beans across jvms does it come to the surface (or rather between application contexts). I'm not sure what the solution should be because the intention was good (to find an ID that is not too unique so they can share beans), but contradicts some other requirements (namely to have a uniquely addressable context ID for discovery and message passing). I think the issue that you are seeing is caused by multiple components all trying to set the application context ID, and of course not agreeing on the best value. I need to refresh my knowledge a bit about how that ID gets used. In principle though, I don't know why for this OAuth2 use case it should matter - the bits that you need in the session are only strings and primitives, so they should serialize nicely. |
The sample app broken because it is passing cookies downstream from the gateway to the resource server, and it shouldn't need to do that because the authentication is via the OAuth2 token in this sample. The resource server fails when it tries to hydrate a session from redis that it doesn't need to know about. It works for me with Brixton snapshots because the gateway isn't passing the cookie downstream any more. It also works as is if you remove the redis and spring session dependencies from the resource server (they aren't needed anyway, so that's perfectly acceptable in this case). As far as the general issue goes with On that last point, it is worth noting that Spring only uses the serialization ID for scoped proxies (which also means anything in We could also ask the question of Spring Core, if it might be possible to use scoped proxies that are somehow marked as serializable "naturally" (i.e. without needing the |
@dsyer Thanks for the response.
You stop running the code that causes the issue, but that isn't the goal. The goal is to be able to authenticated to the ui using OAuth and then authenticate to the resource applications using Spring Session. If you look at the oauth-session it demonstrates the overall goal with the necessary workarounds in place. I should point out that this is a general problem with serialization/deserialization of the
This is quite interesting. I have been able to reproduce the problem with a single application as well. While the bean names can produce the same result the results are not deterministic. This is true in part because classpath scanning is not deterministic. This means the order in which the beans are resolved is not deterministic. I created a branch, gh-93-serialization-session-scope-beans, that demonstrates the problem in an isolated test named SerializeSessionScopeBeanTests.
This could certainly help in the Spring Security OAuth case. However, if users are serializing the |
Ah, I think we are at cross purposes though. The 2 apps that you are trying to share a session between are not ever expected to have the same serialization ID (they are different). So you don't have to go to any great lengths to trick them into breaking when you share a session. The point is that by construction they don't need to share a session, so the experiment is somewhat uninformative. |
@dsyer I think there are two problems at hand here. The first is that the The second issue is that I think that Spring Security OAuth should serialize
The applications still need to share session, it is just done by serializing/deserializing the JWT token instead. If you think about a session in a generic sense it is exchanging one set of credentials (i.e. username/password, JWT token, SAML assertion, etc) for another (session id). If a user is wanting to exchange a JWT token for a session id, then they should be allowed to do so. PS: The sample I chose just happened to be a good starting point to illustrate that users may want to exchange a JWT token for a session id. More generally, users may want to serialize |
GenericScope.setSerializationId can cause serialization issues as illustrated in spring-projects/spring-session#395
The failure happens when trying to serialize Session Scoped beans because
DefaultListableBeanFactory.serializationId
has a different value from when the serialization takes place and when the deserialization takes place.In Spring Cloud, the GenericScope.setSerializationId sets the serialization id. This means both
RefreshScope
andThreadScope
(which inherit fromGenericScope
) are impacted by this.The default value is a UUID calculated from the bytes of the Spring Bean names. Unfortunately the calculation of the resulting id does not appear to be constant. When the same application is restarted, the UUID is still different than the previous id.
Ultimately, this can cause the following stacktrace:
Demo
You can find an example for reproducing this in rwinch/tut-spring-security-and-angular-js. Use the following instructions:
Use the following branches
Workaround
This can be worked around by creating a
RefreshScope
bean definition. For example:The text was updated successfully, but these errors were encountered: