apereo/cas · warning
When the password field is left undefined, CAS will skip…
Error message
When the password field is left undefined, CAS will skip comparing database and user passwords for equality , (especially if the query results do not contain the password field),and will instead only rely on a successful query execution with returned results in order to verify credentials
What it means
This constructor-time WARN in QueryDatabaseAuthenticationHandler fires when QueryJdbcAuthenticationProperties.fieldPassword is blank. Without a password field, CAS cannot compare the submitted password against a database column; authentication succeeds merely because the query returned at least one row, effectively turning the handler into a username-existence check. CAS warns because this silently weakens credential verification.
Solutions
- Set cas.authn.jdbc.query[].fieldPassword to the alias of the password column returned by the sql statement so CAS can compare hashes/passwords
- Ensure the sql SELECT actually includes the password field referenced by fieldPassword
- Configure the matching passwordEncoder/passwordPolicyConfiguration so stored hashes compare correctly
- If existence-only auth is truly intended, accept/audit the risk and document it; consider a stronger mechanism
Example fix
// before cas.authn.jdbc.query[0].sql=SELECT username FROM users WHERE username=? // after cas.authn.jdbc.query[0].sql=SELECT username, password FROM users WHERE username=? cas.authn.jdbc.query[0].fieldPassword=password
Defensive patterns
Strategy: validation
Validate before calling
if (casProperties.getAuthn().getJdbc().getQuery().stream().anyMatch(q -> q.getFieldPassword().isBlank())) { throw new IllegalStateException("query jdbc authn requires fieldPassword"); } Prevention
- Always set fieldPassword when configuring query JDBC authentication
- Verify the SQL selects the password column aliased to fieldPassword
- Configure passwordEncoder to match stored hash format
- Treat existence-only auth as a security exception requiring explicit approval
When it happens
Trigger: Configuring cas.authn.jdbc.query[] without setting fieldPassword while still expecting password comparison; fieldPassword typo'd or named differently from the SELECT alias; deliberately using the handler as an existence check but forgetting the warning is expected.
Common situations: Copy-pasted query config from an example lacking fieldPassword; SELECT that omits the password column so fieldPassword was removed to stop errors; deployments intending bind-style or existence-based auth who did not realize the security implication.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- [e.getMessage()]
- Password does not match value on record.
- Password does not match value on record.
- Password has expired
- [username] not found with SQL query.
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/4d0cd39396952624.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-jdbc-authentication/src/main/java/org/apereo/cas/jdbc/QueryDatabaseAuthenticationHandler.java:44
* password provided by the user. If they match, then authentication succeeds.
* Default password translator is plaintext translator.
*
* @author Scott Battaglia
* @author Dmitriy Kopylenko
* @author Marvin S. Addison
* @since 3.0.0
*/
@Slf4j
@Monitorable
public class QueryDatabaseAuthenticationHandler extends AbstractJdbcUsernamePasswordAuthenticationHandler<QueryJdbcAuthenticationProperties> {
public QueryDatabaseAuthenticationHandler(final QueryJdbcAuthenticationProperties properties,
final PrincipalFactory principalFactory,
final DataSource dataSource) {
super(properties, principalFactory, dataSource);
if (StringUtils.isBlank(properties.getFieldPassword())) {
LOGGER.warn("When the password field is left undefined, CAS will skip comparing database and user passwords for equality "
+ ", (especially if the query results do not contain the password field),"
+ "and will instead only rely on a successful query execution with returned results in order to verify credentials");
}
}
@Override
protected AuthenticationHandlerExecutionResult authenticateUsernamePasswordInternal(
final UsernamePasswordCredential credential, final String originalPassword) throws Throwable {
val username = credential.getUsername();
val password = credential.toPassword();
try {
val dbFields = query(credential);
if (dbFields.containsKey(properties.getFieldPassword())) {
val dbPassword = (String) dbFields.get(properties.getFieldPassword());
val originalPasswordMatchFails = StringUtils.isNotBlank(originalPassword) && !matches(originalPassword, dbPassword);
val originalPasswordEquals = StringUtils.isBlank(originalPassword) && !Strings.CI.equals(password, dbPassword);
if (originalPasswordMatchFails || originalPasswordEquals) {View on GitHub (pinned to e7288fc434)