apereo/cas · error · FailedLoginException

Unable to authenticate

Error message

Unable to authenticate ${credential.getId()}

What it means

Fallback failure in AcceptUsersAuthenticationHandler: after the password check, if no password-policy strategy applies (strategy null or username blank), the handler cannot build a handler result and throws FailedLoginException('Unable to authenticate ' + credential.getId()). It marks any remaining/unexpected path as an authentication failure.

Solutions

  1. Ensure the credential carries a non-blank username before reaching the handler
  2. Configure a password policy handling strategy (or accept the default) so a handler result can be built
  3. If this fires despite a valid username/password, debug getPasswordPolicyHandlingStrategy() wiring

Example fix

// before
UsernamePasswordCredential c = new UsernamePasswordCredential(); c.setPassword(p); // username blank
// after
c.setUsername(username); // ensure username is set before authentication
Defensive patterns

Strategy: validation

Validate before calling

// before authentication
if (credential.getUsername() == null || credential.getUsername().isBlank()) {
    throw new IllegalArgumentException("Username must not be blank");
}

Try / catch

try {
    handlerResult = acceptUsersHandler.authenticate(credential, service);
} catch (FailedLoginException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Unable to authenticate")) {
        LOGGER.error("Handler could not build a result; check password policy strategy configuration");
    }
}

Prevention

When it happens

Trigger: authenticateUsernamePasswordInternal reaches the final throw because getPasswordPolicyHandlingStrategy() returned null or the username was blank, even though the password comparison passed — an edge path triggered by a blank username or missing policy strategy.

Common situations: Custom configurations where the password policy handling strategy bean is absent; credentials submitted with blank usernames that somehow reached the handler.

Understand the failure class

Related errors


AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08). Data as JSON: /api/errors/ba4d3d4445f921cb. Report an issue: GitHub.

Appendix: source

Thrown at core/cas-server-core-authentication-api/src/main/java/org/apereo/cas/authentication/AcceptUsersAuthenticationHandler.java:79

            throw new FailedLoginException("No user can be accepted because none is defined");
        }
        val username = credential.getUsername();
        val cachedPassword = this.users.get(username);
        if (cachedPassword == null) {
            LOGGER.debug("[{}] was not found in the map.", username);
            throw new AccountNotFoundException(username + " not found in backing map.");
        }
        if (!Strings.CS.equals(credential.toPassword(), cachedPassword)) {
            throw new FailedLoginException();
        }
        val strategy = getPasswordPolicyHandlingStrategy();
        if (strategy != null && StringUtils.isNotBlank(username)) {
            LOGGER.debug("Attempting to examine and handle password policy via [{}]", strategy.getClass().getSimpleName());
            val principal = this.principalFactory.createPrincipal(username);
            val messageList = strategy.handle(principal, getPasswordPolicyConfiguration());
            return createHandlerResult(credential, principal, messageList);
        }
        throw new FailedLoginException("Unable to authenticate " + credential.getId());
    }
}

View on GitHub (pinned to e7288fc434)