apereo/cas · error · FailedLoginException

[e.getMessage()]

Error message

[e.getMessage()]

What it means

The handler wraps the whole authentication attempt in catch (Throwable) and rethrows FailedLoginException(e.getMessage()). Any database-level failure (SQL syntax error, connection failure, driver missing, NPE) surfaces as this generic failed-login message with the original message text.

Solutions

  1. Read the logged stack trace via LoggingUtils output to identify the root cause.
  2. Test the datasource connectivity and run the generated SQL directly in the DB.
  3. Validate cas.authn.jdbc.search[] properties (sql, table, fields) and the JDBC driver dependency.
  4. Replace generic handling by checking DB health and configuration before enabling this handler.

Example fix

// before: sql missing FROM table
cas.authn.jdbc.search[0].sql=SELECT COUNT(*) FROM WHERE username=? AND password=?
// after
cas.authn.jdbc.search[0].sql=SELECT COUNT(*) FROM users WHERE username=? AND password=?
Defensive patterns

Strategy: try-catch

Validate before calling

// health-check the datasource before attempting auth
jdbcTemplate.queryForObject("SELECT 1", Integer.class);

Try / catch

try { result = handler.authenticate(credential); }
catch (FailedLoginException e) {
  Throwable root = ExceptionUtils.getRootCause(e);
  log.error("Auth failed: {}", root == null ? e.getMessage() : root.getMessage());
}

Prevention

When it happens

Trigger: Any Throwable escaping queryForObject: DataAccessException from a broken SQL string, DataSource connectivity problems, NullPointerException on misconfigured properties, ClassCastException on unexpected count types.

Common situations: Typo in cas.authn.jdbc.search[].sql; DB down or network blocked; JDBC driver not on classpath; jdbcTemplate/datasource bean misconfiguration.

Understand the failure class

Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.

Related errors


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

Appendix: source

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

    protected AuthenticationHandlerExecutionResult authenticateUsernamePasswordInternal(
        final UsernamePasswordCredential credential, final String originalPassword) throws Throwable {
        val sql = "SELECT COUNT('x') FROM ".concat(properties.getTableUsers())
            .concat(" WHERE ")
            .concat(properties.getFieldUser())
            .concat(" = ? AND ")
            .concat(properties.getFieldPassword()).concat("= ?");
        val username = credential.getUsername();
        try {
            LOGGER.debug("Executing SQL query [{}]", sql);
            val count = getJdbcTemplate().queryForObject(sql, Integer.class, username, credential.toPassword());
            if (count == null || count == 0) {
                throw new FailedLoginException(username + " not found with SQL query.");
            }
            val principal = principalFactory.createPrincipal(username);
            return createHandlerResult(credential, principal, new ArrayList<>());
        } catch (final Throwable e) {
            LoggingUtils.error(LOGGER, e);
            throw new FailedLoginException(e.getMessage());
        }
    }
}

View on GitHub (pinned to e7288fc434)