apereo/cas · error
Account password on record for
Error message
Account password on record for [{}] does not match the given/encoded password What it means
RedisAuthenticationHandler fetches the RedisUserAccount by username and compares the submitted password via the configured password encoder. When the encoder's matches() fails, it logs this warning and throws FailedLoginException — the credentials presented do not match the stored (encoded) password.
Solutions
- Verify the user's password is correct; test with the known-good credentials for the Redis-backed account.
- Ensure the stored account.getPassword() value was encoded with the same algorithm as cas.authn.passwordEncoder (or the handler's encoder bean).
- Re-import/update the account record in Redis with the correct hash for the current encoder.
- Check for whitespace/encoding issues (trailing newline) in the credential or stored value.
Example fix
// before — stored plaintext but encoder is BCrypt
redisTemplate.opsForValue().set("alice", new RedisUserAccount("alice", "plainpw", Status.OK));
// after — store the encoded form
redisTemplate.opsForValue().set("alice", new RedisUserAccount("alice", new BCryptPasswordEncoder().encode("correctpw"), Status.OK)); Defensive patterns
Strategy: try-catch
Try / catch
try {
authHandler.authenticate(credential);
} catch (FailedLoginException | AccountNotFoundException e) {
// surface 'invalid credentials' to the user; do not retry automatically
} Prevention
- Write Redis accounts using the same PasswordEncoder CAS is configured with
- Never store plaintext passwords in Redis
- Version/namespace Redis keys when changing encoding schemes and re-import users
- Trim credentials and stored values of stray whitespace
When it happens
Trigger: authenticateUsernamePasswordInternal receives a UsernamePasswordCredential whose raw password does not match account.getPassword() under the configured PasswordEncoder (e.g. BCrypt hash mismatch).
Common situations: Account records written with a different encoding algorithm than the handler's configured encoder; user typo/caps-lock; stale Redis data after a password change elsewhere; encoder misconfiguration (plain vs bcrypt).
Related errors
- AccountNotFoundException
- FailedLoginException
- AccountDisabledException
- AccountExpiredException
- AccountLockedException
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/57d5e3e917901fd4.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-redis-authentication/src/main/java/org/apereo/cas/redis/RedisAuthenticationHandler.java:40
private final CasRedisTemplate redisTemplate;
public RedisAuthenticationHandler(final String name,
final PrincipalFactory principalFactory, final Integer order,
final CasRedisTemplate redisTemplate) {
super(name, principalFactory, order);
this.redisTemplate = redisTemplate;
}
@Override
protected AuthenticationHandlerExecutionResult authenticateUsernamePasswordInternal(
final UsernamePasswordCredential credential,
final String originalPassword) throws Throwable {
val account = (RedisUserAccount) redisTemplate.opsForValue().get(credential.getUsername());
if (account == null) {
throw new AccountNotFoundException();
}
if (!getPasswordEncoder().matches(originalPassword, account.getPassword())) {
LOGGER.warn("Account password on record for [{}] does not match the given/encoded password", credential.getId());
throw new FailedLoginException();
}
switch (account.getStatus()) {
case DISABLED -> throw new AccountDisabledException();
case EXPIRED -> throw new AccountExpiredException();
case LOCKED -> throw new AccountLockedException();
case MUST_CHANGE_PASSWORD -> throw new AccountPasswordMustChangeException();
case OK -> LOGGER.debug("Account status is OK");
}
val principal = principalFactory.createPrincipal(account.getUsername(), account.getAttributes());
return createHandlerResult(credential, principal, new ArrayList<>());
}
}
View on GitHub (pinned to e7288fc434)