Skip to content

Endless loop with Spring Security and Spring Session if you make cookie path more generic #3947

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

Closed
mschipperheyn opened this issue Jun 27, 2016 · 12 comments
Assignees

Comments

@mschipperheyn
Copy link

mschipperheyn commented Jun 27, 2016

So, I'm running into this endless loop scenario when I try to access a protected resource.

I use Spring Security 4.1, Spring Session 1.2.1-BUILD-SNAPSHOT, and Spring Framework 4.1.9.

My configuration uses RememberMe functionality based on cookies.

The reason seems to be that I have two JSESSIONID (I renamed them to JSESSIONID) cookies on my computer. An old cookie and a new cookie. The old cookie has a path of /myContextPath/ and one has a path of /.

I changed the way cookies were written to support some spring websocket functionality if I remember correctly. My CookieSerializer used to have a cookie path setting of null (writing to /contextPath/) and now writes to "/".

Spring Session CookieHttpSessionStrategy reads the two cookies, but chooses the old one by default (with /contextPath/) (method: CookieHttpSessionStrategy.getSessionIds) and ignores the other one. I assume because it is more specific.

It determines that the session is invalid and then goes on to create a new one, which generates the new cookie and writes the cookie with a path of "/". It then goes into the same loop and retrieves the old one when it should be retrieving the new one

Should this be considered a mis configuration on my part? It seems like this could happen in a real world scenario quite easily (without realizing).

By the way, my filter sequence seems wrong (don't know why). Maybe this impacts. I'm not sure.

SessionRepositoryFilter
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
LogoutFilter
UsernamePasswordAuthenticationFilter
ConcurrentSessionFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
RememberMeAuthenticationFilter
@mschipperheyn
Copy link
Author

mschipperheyn commented Jun 27, 2016

I believe that the reason I changed the cookie serializer setting is that, if I recall correctly, Spring Session added a closing slash to the cookiepath if you use a contextPath and Spring Security didn't and I ran into some issues with accessing cookies on my phone app because of it.

This I needed in turn because I needed to add the cookie values to the request header in opening the websocket to get a working session.

@rwinch
Copy link
Member

rwinch commented Jun 27, 2016

@mschipperheyn Thanks for the report.

This sounds a lot like spring-projects/spring-session#275 Have you checked to ensure that you are only getting a single JSESSIONID cookie in the requests? You might try clearing your cookies.

@rwinch rwinch added the status: waiting-for-feedback We need additional information before we can continue label Jun 27, 2016
@mschipperheyn
Copy link
Author

It does look very similar to the report you indicate.

I did check and I am getting two JSESSIONID cookies. As far as I understand it, I get them for the reason indicated above: I changed the contextPath when I write the cookie from a more specific (/contextPath/) to a less specific ("/"). Given that most production environment will not be on a contextpath, I guess it may be considered an edge case.

However, the potential for an endless loop triggered by a client cookie is a little scary.

Also, I can easily remove my cookies, and that's what I did to fix this, but my end users obviously wouldn't even know. What's worse, if I removed my cookies before the error occurred, I wouldn't realize.

@rwinch
Copy link
Member

rwinch commented Jun 27, 2016

@mschipperheyn Thanks for the response.

If you remove the cookies and then use your application normally, does it work or is it broken? Often times I see this problem coming from a scenario where it would only happen in development (i.e. you started with Tomcat session and then started using Spring Session later).

If it is broken, can you provide an example because I'm afraid I cannot reproduce it so long as the cookie is written to a consistent path that does not overlap with another application.

I agree this limitation is not ideal. We plan to fix this in the next milestone.

@mschipperheyn
Copy link
Author

When I remove the cookie, it works.

@rwinch
Copy link
Member

rwinch commented Jun 27, 2016

I think you are getting into this scenario due to the fact that something else is creating the other cookie. For example, your application with a different setting, a different application, etc.

I'm closing this as a duplicate of spring-projects/spring-session#275 If you find out that this is not correct, please reopen

@rwinch rwinch closed this as completed Jun 27, 2016
@rwinch rwinch removed the status: waiting-for-feedback We need additional information before we can continue label Jun 27, 2016
@rwinch rwinch self-assigned this Jun 27, 2016
@mschipperheyn
Copy link
Author

I did start with a Tomcat session and then I implemented Spring Session and just reused the JSESSIONID key as a session parameter. Of course, since I'm not deploying my application clean (this is an upgrade), it is not limited to a development scenario.

Given my changes to the cookie serializer (writing against a different path) I expect this could happen to all users if it were deployed to production.

@mschipperheyn
Copy link
Author

I'll wait for the next milestone and reproduce my scenario. Reproducing should I think just be a matter of setting CookiePath to null, logging in. Set CookiePath to "/", restart and try to login again.

@rwinch
Copy link
Member

rwinch commented Jun 27, 2016

So long as the path and domain of the cookie are all the same as the existing cookie you should be fine. Alternatively, you can name the cookie something other than your existing cookie name and then it won't be an issue either.

@mschipperheyn
Copy link
Author

Ah ok, different Cookie name makes sense

@rwinch
Copy link
Member

rwinch commented Jun 27, 2016

If you really need a workaround you can customize the CookieSerializer to read the cookie value only if it matches the id pattern (i.e. looks like a UUID) before returning the value. See https://github.com/spring-projects/spring-session/blob/master/spring-session/src/main/java/org/springframework/session/web/http/DefaultCookieSerializer.java#L58

Tomcat by default creates a cookie without a - in it. However, Spring Session does. so it can find the correct cookie value that way.

@mschipperheyn
Copy link
Author

good idea

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants