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

  1. Verify the user's password is correct; test with the known-good credentials for the Redis-backed account.
  2. Ensure the stored account.getPassword() value was encoded with the same algorithm as cas.authn.passwordEncoder (or the handler's encoder bean).
  3. Re-import/update the account record in Redis with the correct hash for the current encoder.
  4. 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

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


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)