apereo/cas · error · FailedLoginException

Failed to authenticate user

Error message

Failed to authenticate user

What it means

StoredProcedureAuthenticationHandler calls the configured stored procedure with username/password and expects a 'status' output that is truthy. If the result map is empty or status evaluates false, FailedLoginException 'Failed to authenticate user' is thrown.

Solutions

  1. Inspect the debug log 'Procedure results are [...]' and confirm the actual key name; fix the procedure or the extraction to match it.
  2. Update the stored procedure to return status=1 on success.
  3. Verify procedureName matches the actual stored procedure and the user has EXECUTE permission.
  4. Confirm the function call parameters (username, password) match the procedure signature.

Example fix

// before: procedure outputs @status_value
// after: name the output parameter 'status' in the procedure
CREATE PROCEDURE auth_user(IN username VARCHAR, IN password VARCHAR, OUT status INT)
BEGIN SELECT COUNT(*) INTO status FROM users WHERE ...; END;
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify the procedure exists and is executable
jdbcTemplate.execute("CALL auth_user('probe','probe',@status)");
Integer status = jdbcTemplate.queryForObject("SELECT @status", Integer.class);

Type guard

Object status = results.get("status");
if (status == null || !BooleanUtils.toBoolean(status.toString())) { throw new FailedLoginException(); }

Try / catch

try { result = handler.authenticate(credential); }
catch (FailedLoginException e) { log.warn("Stored procedure auth returned failure: {}", e.getMessage()); }

Prevention

When it happens

Trigger: SimpleJdbcCall.execute returns empty results, or the results map lacks a 'status' key, or status is '0'/'false' after BooleanUtils.toBoolean.

Common situations: Procedure returns keys with different case or naming (e.g. STATUS, return_status) so results.get("status") is null; procedure returns no result set on failure; procedure always returns 0 because of internal logic/schema drift.

Understand the failure class

Related errors


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

Appendix: source

Thrown at support/cas-server-support-jdbc-authentication/src/main/java/org/apereo/cas/jdbc/StoredProcedureAuthenticationHandler.java:40

public class StoredProcedureAuthenticationHandler extends AbstractJdbcUsernamePasswordAuthenticationHandler<ProcedureJdbcAuthenticationProperties> {

    public StoredProcedureAuthenticationHandler(
        final ProcedureJdbcAuthenticationProperties properties,
        final PrincipalFactory principalFactory, final DataSource dataSource) {
        super(properties, principalFactory, dataSource);
    }

    @Override
    protected AuthenticationHandlerExecutionResult authenticateUsernamePasswordInternal(
        final UsernamePasswordCredential credential, final String originalPassword) throws Throwable {
        val username = credential.getUsername();
        val password = credential.toPassword();

        val jdbcCall = new SimpleJdbcCall(jdbcTemplate).withProcedureName(properties.getProcedureName());
        val results = jdbcCall.execute(Map.of("username", username, "password", password));
        LOGGER.debug("Procedure results are [{}]", results);
        if (results.isEmpty() || !BooleanUtils.toBoolean(results.get("status").toString())) {
            throw new FailedLoginException("Failed to authenticate user");
        }
        val principal = principalFactory.createPrincipal(username, CollectionUtils.toMultiValuedMap(results));
        return createHandlerResult(credential, principal, new ArrayList<>());
    }
}

View on GitHub (pinned to e7288fc434)