apereo/cas · error · FailedLoginException
[e.getMessage()]
Error message
[e.getMessage()]
What it means
BindModeSearchDatabaseAuthenticationHandler authenticates by opening a JDBC connection with the username/password as bind credentials. Any Throwable while establishing or using the connection (bad credentials, unreachable DB, driver issues) is converted into FailedLoginException whose message is the original exception's message.
Solutions
- Read the embedded message to identify the root cause (auth failure vs connectivity)
- Confirm the username/password are valid database credentials directly via a DB client
- Check datasource URL/host/port/network reachability and that the JDBC driver is on the classpath
- If the DB lacks native password-auth connections, switch to SearchModeSearchDatabaseAuthenticationHandler (query mode) with a service account
Example fix
// before (bind mode, DB without bind auth) cas.authn.jdbc.bind[0].url=jdbc:mysql://db:3306/users // after (search mode with service account) cas.authn.jdbc.query[0].sql=SELECT * FROM users WHERE username=? cas.authn.jdbc.query[0].user=root
Defensive patterns
Strategy: try-catch
Validate before calling
// precheck connectivity before auth attempt
try (var c = dataSource.getConnection()) { /* datasource reachable */ } Try / catch
try {
return handler.authenticate(credential);
} catch (FailedLoginException e) {
// inspect e.getMessage(): auth failure vs connectivity; alert on connectivity messages
} Prevention
- Validate JDBC URL/host/firewall and driver availability at startup
- Test DB credentials with a direct client before blaming the app
- Prefer search/query mode with a service account when the DB lacks bind-style auth
When it happens
Trigger: authenticateUsernamePasswordInternal fails at getDataSource().getConnection(username, password) — e.g. database rejects the bind, host/port unreachable, driver class missing — and the caught Throwable's message becomes the thrown error text.
Common situations: Wrong password (DB-level auth failure reported verbatim); database down or wrong JDBC URL/host/firewall rules; missing JDBC driver on classpath; using bind mode against a DB (like some MySQL setups) that doesn't support username/password connection auth as expected.
Understand the failure class
Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.
Related errors
- Password does not match value on record.
- Password does not match value on record.
- Password has expired
- [username] not found with SQL query.
- [e.getMessage()]
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/886e75514cb6c57c.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-jdbc-authentication/src/main/java/org/apereo/cas/jdbc/BindModeSearchDatabaseAuthenticationHandler.java:44
public class BindModeSearchDatabaseAuthenticationHandler extends AbstractJdbcUsernamePasswordAuthenticationHandler<BindJdbcAuthenticationProperties> {
public BindModeSearchDatabaseAuthenticationHandler(
final BindJdbcAuthenticationProperties 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();
try (val connection = getDataSource().getConnection(username, password)) {
LOGGER.trace("Established connection to schema [{}]", connection.getSchema());
val principal = principalFactory.createPrincipal(username);
return createHandlerResult(credential, principal, new ArrayList<>());
} catch (final Throwable e) {
throw new FailedLoginException(e.getMessage());
}
}
}
View on GitHub (pinned to e7288fc434)