spring-projects/spring-security · error · BadCredentialsException
The presented RememberMeAuthenticationToken does not contain
Error message
The presented RememberMeAuthenticationToken does not contain the expected key
What it means
RememberMeAuthenticationProvider.authenticate() compares the key hash of the incoming RememberMeAuthenticationToken with its configured key. On mismatch it throws BadCredentialsException 'The presented RememberMeAuthenticationToken does not contain the expected key'. The shared key validates that the token was issued by the matching remember-me services.
Source
Thrown at core/src/main/java/org/springframework/security/authentication/RememberMeAuthenticationProvider.java:59
private String key;
public RememberMeAuthenticationProvider(String key) {
Assert.hasLength(key, "key must have a length");
this.key = key;
}
@Override
public void afterPropertiesSet() {
Assert.notNull(this.messages, "A message source must be set");
}
@Override
public @Nullable Authentication authenticate(Authentication authentication) throws AuthenticationException {
if (!supports(authentication.getClass())) {
return null;
}
if (this.key.hashCode() != ((RememberMeAuthenticationToken) authentication).getKeyHash()) {
throw new BadCredentialsException(this.messages.getMessage("RememberMeAuthenticationProvider.incorrectKey",
"The presented RememberMeAuthenticationToken does not contain the expected key"));
}
return authentication;
}
public String getKey() {
return this.key;
}
@Override
public void setMessageSource(MessageSource messageSource) {
this.messages = new MessageSourceAccessor(messageSource);
}
@Override
public boolean supports(Class<?> authentication) {
return (RememberMeAuthenticationToken.class.isAssignableFrom(authentication));
}View on GitHub (pinned to 96852e8860)
Solutions
- Configure the identical key on RememberMeServices and RememberMeAuthenticationProvider
- If the key was rotated, have users log in again / invalidate old remember-me cookies
- Ensure consistent key across all nodes in a cluster
- In multi-filter-chain setups, make sure each chain's provider matches its own services' key
Example fix
// before
TokenBasedRememberMeServices services = new TokenBasedRememberMeServices("keyOne", uds);
new RememberMeAuthenticationProvider("keyTwo");
// after
String key = "keyOne";
TokenBasedRememberMeServices services = new TokenBasedRememberMeServices(key, uds);
new RememberMeAuthenticationProvider(key); Defensive patterns
Strategy: validation
Validate before calling
RememberMeAuthenticationProvider provider = new RememberMeAuthenticationProvider(key); TokenBasedRememberMeServices services = new TokenBasedRememberMeServices(key, uds); assert key != null && !key.isBlank();
Type guard
boolean hasValidKey(RememberMeAuthenticationToken t, String key) { return key != null && key.hashCode() == t.getKeyHash(); } Try / catch
try { return provider.authenticate(auth); } catch (BadCredentialsException e) { log.warn("Remember-me token key mismatch, forcing re-login"); return null; } Prevention
- Share one key constant between RememberMeServices and RememberMeAuthenticationProvider
- Rotate keys deliberately and invalidate old cookies
- Verify keys match in multi-chain and multi-node deployments
When it happens
Trigger: A RememberMeAuthenticationToken created with key A reaches a RememberMeAuthenticationProvider configured with key B — typically RememberMeServices and the provider keys differ.
Common situations: TokenBasedRememberMeServices key differs from provider key; key changed after tokens were persisted in cookies/sessions; multiple security filter chains with different remember-me keys; cluster nodes with different key config.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Can not set rememberMeCookieName and custom rememberMeServic
- The presented AnonymousAuthenticationToken does not contain
- Cookie token was not Base64 encoded; value was '<cookieValue
- Series Id '<series>' already exists!
- Token for series '<series>' does not exist
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/560e706c8c725fae.
Report an issue: GitHub.