spring-projects / spring-projects/spring-security
SEC-2985: PersistentTokenBasedRememberMeServices generates many tokens for one user
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 9.6k
- Forks
- 6.3k
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 52
Description
Sergey Klimenko (Migrated from SEC-2985) said:
Hi team,
Scanning my database I found a lot of persisted tokens for the same user. Digging this problem I found that the PersistentTokenBasedRememberMeServices doesn't remove previous tokens in the following cases.
Let's suppose that we have a user that was authorized by username/login first time. In this case the onLoginSuccess method will be invoked and new token will be created and stored in PersistentTokenRepository.
After that in a few days, for example, the same user will by authorized by RememberMeAuthenticationFilter (we had valid token) and as result the processAutoLoginCookie method will be invoked and new token data will be generated and cookie and DB will be updated.
Now suppose that for any action full authentication is required. In this case the user will be forwarded to authorization form and as result onLoginSuccess method will be invoked. As result new token will be generated and stored in DB but please keep in mind that we already have valid token already in DB.
At this moment I see two solutions:
We can remove previous token from DB and store new one;
If we already have token it must be updated instead of creating new one.
I would preffer #2 so my code is:
@Override
protected void onLoginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication) {
String username = successfulAuthentication.getName();
this.logger.debug("Creating new persistent login for user " + username);
try {
PersistentRememberMeToken token;
final String rememberMeCookie = extractRememberMeCookie(request);
if (rememberMeCookie != null) {
final String[] strings = decodeCookie(rememberMeCookie);
token = this.tokenRepository.getTokenForSeries(strings[0]);
if (token != null) {
token = new PersistentRememberMeToken(token.getUsername(), token.getSeries(), generateTokenData(), new Date());
tokenRepository.updateToken(token.getSeries(), token.getTokenValue(), token.getDate());
} else {
token = new PersistentRememberMeToken(username, this.generateSeriesData(), this.generateTokenData(), new Date());
this.tokenRepository.createNewToken(token);
}
} else {
token = new PersistentRememberMeToken(username, this.generateSeriesData(), this.generateTokenData(), new Date());
this.tokenRepository.createNewToken(token);
}
this.addCookie(token, request, response);
} catch (Exception var7) {
this.logger.error("Failed to save persistent token ", var7);
}
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by locating PersistentTokenBasedRememberMeServices and its onLoginSuccess method, then inspect the token repository methods used by the existing remember-me flow. Update the login path so an existing cookie series is refreshed rather than creating another persisted token, and verify that repeated authentication does not create duplicate persisted tokens.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- authentication, security
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 58/100