Vertonur Sunimi (Migrated from SEC-2427) said:

Prerequisite: Browser with authenticated rememberme cookie stored.

Reproduction steps: 1. The browser open a page to trigger auto login. 2. Request received by server and processed right before code tokenRepository.updateToken(newToken.getSeries(), newToken.getTokenValue(), newToken.getDate()); of PersistentTokenBasedRememberMeServices and the executing thread paused. 3. End user refresh the page and a second request is sent to the server 4. The second request is recieved and processed through the Spring Security filters and returned a new cookie to the browser and the token( token-A) in the db is updated either. 5. The first request resumed and run code updateToken thus the db is updated with the new generated token (token-B). As the request has been canceled by the browser so token-B will never reach the browser with code addCookie(newToken, request, response); 6. Session of the end user time out and pages are requested again, browser send request s with token-A 7. !presentedToken.equals(token.getTokenValue()) of PersistentTokenBasedRememberMeServices is checked thus caused CookieTheftException be thrown and all tokens related to the end user in db are deleted.

SO concurrency control is needed for rememberme filter.

Comment From: spring-projects-issues

Cameron Dalton said:

I don't think "concurrency control" in the remember me filter will solve this. Thread execution in the first request might wait before it even gets to the remember me filter, the second request gets all the way through the remember me filter, and then the first request wakes up and proceeds all the way through the filter.

A common additional use case that will produces this behavior (think I can still call it the same bug):

The user opens a page which triggers a remember-me auto login

The response does not make it back to the client for any reason. For example:

Before the response comes back to the client (say on a page that takes a couple seconds to load) the user clicks Stop in the browser

Before the response comes back to the client, the user closes the browser

Some network issue prevents the response from making it back to the client (I experienced this with a 502 Proxy Error)

The user opens that page again

Since the previous response never made it back to the client, the new remember me cookie (with the updated token value) was not recorded by the browser. Thus when the user visits the page again, the browser submits the old cookie, triggering the CookieTheftException.

Comment From: weaselmetal

Ok, this is an old issue. But I do believe the remember me functionality should not break with simultaneous requests. Which is actually the case.

If a client sends two simultaneous requests against the server, both with an expired session Id and with a valid remember me token, then the remember me functionality is broken. One of the two requests will create a new token and remove the old one. The request being handled second causes a CookieTheftException, removing all tokens, also the one which was just created. Follow up requests which would use the newer token end up with a 401 response.

The problems are: - Clearly, in that case no cookie theft happened. Informing the user that their cookie was stolen would be fatal for the user trust. So one cannot bubble that up to the user. As outlined by Cameron Dalton, there are also other scenarios, where spring would throw a CookieTheftException, even though the cookie wasn't stolen. Another reason not to claim that the cookie was stolen. - Well, remember me doesn't work at all when the client runs into the described scenario.

Things that spring cannot / should not assume: - That one client never makes simultaneous requests, but all requests are strictly sequential. - That a client always checks if the session is still valid before making any simultaneous requests.

So, while I don't want to make suggestions how this should be solved, I think it needs to be solved.

One thing I am not sure about is: is it really necessary, to delete all tokens for the user, when one outdated (or invalidated / removed) token is presented to the server? If an attacker was able to steal one token from one device, why would one assume that other tokens were probably stolen too? I'm no expert, but at least the aforementioned assumption seems a bit contrived.

Hope to hear back from you spring guys!

Comment From: mindhaq

The approach here might be a valid solution.

~https://articles.javatalks.ru/articles/25~

updated link at archive.org:

https://web.archive.org/web/20210411164636/https://articles.javatalks.ru/articles/25

Comment From: SaeedZhiany

The approach here might be a valid solution.

https://articles.javatalks.ru/articles/25

@mindhaq the link is broken. can you please update it?