spring-projects/spring-security · info · RememberMeAuthenticationException
Remember-me login has expired
Error message
Remember-me login has expired
What it means
processAutoLoginCookie validates the stored token's date against the configured token validity period. If token.getDate() + tokenValiditySeconds*1000 is earlier than the current time the remember-me login has expired and a RememberMeAuthenticationException is thrown, rejecting the cookie even though the series/token values match.
Source
Thrown at web/src/main/java/org/springframework/security/web/authentication/rememberme/PersistentTokenBasedRememberMeServices.java:119
}
String presentedSeries = cookieTokens[0];
String presentedToken = cookieTokens[1];
PersistentRememberMeToken token = this.tokenRepository.getTokenForSeries(presentedSeries);
if (token == null) {
// No series match, so we can't authenticate using this cookie
throw new RememberMeAuthenticationException("No persistent token found for series id: " + presentedSeries);
}
// We have a match for this user/series combination
if (!presentedToken.equals(token.getTokenValue())) {
// Token doesn't match series value. Delete all logins for this user and throw
// an exception to warn them.
this.tokenRepository.removeUserTokens(token.getUsername());
throw new CookieTheftException(this.messages.getMessage(
"PersistentTokenBasedRememberMeServices.cookieStolen",
"Invalid remember-me token (Series/token) mismatch. Implies previous cookie theft attack."));
}
if (token.getDate().getTime() + getTokenValiditySeconds() * 1000L < System.currentTimeMillis()) {
throw new RememberMeAuthenticationException("Remember-me login has expired");
}
// Token also matches, so login is valid. Update the token value, keeping the
// *same* series number.
this.logger.debug(LogMessage.format("Refreshing persistent login token for user '%s', series '%s'",
token.getUsername(), token.getSeries()));
PersistentRememberMeToken newToken = new PersistentRememberMeToken(token.getUsername(), token.getSeries(),
generateTokenData(), new Date());
try {
this.tokenRepository.updateToken(newToken.getSeries(), newToken.getTokenValue(), newToken.getDate());
addCookie(newToken, request, response);
}
catch (Exception ex) {
this.logger.error("Failed to update token: ", ex);
throw new RememberMeAuthenticationException("Autologin failed due to data access problem");
}
return getUserDetailsService().loadUserByUsername(token.getUsername());
}
View on GitHub (pinned to 96852e8860)
Solutions
- Have the user log in again; the exception correctly forces re-authentication and issues a fresh cookie.
- Increase tokenValiditySeconds (http.rememberMe().tokenValiditySeconds(...)) if a longer lifetime is acceptable for your security posture.
- Keep the validity setting stable across deploys, or expect existing cookies to expire when you shorten it.
- Synchronize server clocks (NTP) to avoid clock-skew-induced early expiry.
Example fix
// before http.rememberMe().tokenValiditySeconds(3600); // 1h: users expire constantly // after http.rememberMe().tokenValiditySeconds(1209600); // 14 days (framework default)
Defensive patterns
Strategy: try-catch
Validate before calling
PersistentRememberMeToken t = repo.getTokenForSeries(series);
if (t != null && t.getDate().getTime() + validitySeconds * 1000L < System.currentTimeMillis()) {
// expired: skip remember-me, go to login page
} Try / catch
try {
Authentication a = rememberMeServices.autoLogin(request, response);
} catch (RememberMeAuthenticationException e) {
// expired cookie: proceed unauthenticated to the login page
} Prevention
- Set tokenValiditySeconds appropriate for your users' return cadence
- Keep validity settings stable across deployments
- Synchronize server clocks with NTP
- Clear expired series periodically so expiry manifests consistently
When it happens
Trigger: Presenting a structurally valid series/token pair whose last-used timestamp is older than getTokenValiditySeconds() (default 14 days) — e.g. the user returns after a long absence, or tokenValiditySeconds was shortened below the age of stored tokens.
Common situations: Users away longer than the validity window; deployments that reduced tokenValiditySeconds, instantly invalidating existing cookies; servers with clock skew (clock moved back/forward) prematurely expiring or extending tokens; expired series kept by a cleanup job that removed them server-side before the cookie aged out (leading to 617 instead).
Related errors
- No persistent token found for series id: <presentedSeries>
- Can not set rememberMeCookieName and custom rememberMeServic
- Could not create a default ServerMaximumSessionsExceededHand
- A ReactiveSessionRegistry is needed for concurrent session m
- The presented RememberMeAuthenticationToken does not contain
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/9563796d0c068375.
Report an issue: GitHub.