{"record":{"id":"4d0cd39396952624","repo":"apereo/cas","slug":"when-the-password-field-is-left-undefined-cas-wil","errorCode":null,"errorMessage":"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","messagePattern":"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","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"support/cas-server-support-jdbc-authentication/src/main/java/org/apereo/cas/jdbc/QueryDatabaseAuthenticationHandler.java","lineNumber":44,"sourceCode":" * password provided by the user. If they match, then authentication succeeds.\n * Default password translator is plaintext translator.\n *\n * @author Scott Battaglia\n * @author Dmitriy Kopylenko\n * @author Marvin S. Addison\n * @since 3.0.0\n */\n@Slf4j\n@Monitorable\npublic class QueryDatabaseAuthenticationHandler extends AbstractJdbcUsernamePasswordAuthenticationHandler<QueryJdbcAuthenticationProperties> {\n\n    public QueryDatabaseAuthenticationHandler(final QueryJdbcAuthenticationProperties properties,\n\n                                              final PrincipalFactory principalFactory,\n                                              final DataSource dataSource) {\n        super(properties, principalFactory, dataSource);\n        if (StringUtils.isBlank(properties.getFieldPassword())) {\n            LOGGER.warn(\"When the password field is left undefined, CAS will skip comparing database and user passwords for equality \"\n                + \", (especially if the query results do not contain the password field),\"\n                + \"and will instead only rely on a successful query execution with returned results in order to verify credentials\");\n        }\n    }\n\n    @Override\n    protected AuthenticationHandlerExecutionResult authenticateUsernamePasswordInternal(\n        final UsernamePasswordCredential credential, final String originalPassword) throws Throwable {\n        val username = credential.getUsername();\n        val password = credential.toPassword();\n        try {\n            val dbFields = query(credential);\n            if (dbFields.containsKey(properties.getFieldPassword())) {\n                val dbPassword = (String) dbFields.get(properties.getFieldPassword());\n\n                val originalPasswordMatchFails = StringUtils.isNotBlank(originalPassword) && !matches(originalPassword, dbPassword);\n                val originalPasswordEquals = StringUtils.isBlank(originalPassword) && !Strings.CI.equals(password, dbPassword);\n                if (originalPasswordMatchFails || originalPasswordEquals) {","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-jdbc-authentication/src/main/java/org/apereo/cas/jdbc/QueryDatabaseAuthenticationHandler.java#L26-L62","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\ncas.authn.jdbc.query[0].sql=SELECT username FROM users WHERE username=?\n// after\ncas.authn.jdbc.query[0].sql=SELECT username, password FROM users WHERE username=?\ncas.authn.jdbc.query[0].fieldPassword=password","handlingStrategy":"validation","validationCode":"if (casProperties.getAuthn().getJdbc().getQuery().stream().anyMatch(q -> q.getFieldPassword().isBlank())) { throw new IllegalStateException(\"query jdbc authn requires fieldPassword\"); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["jdbc","authentication","weak-auth","config"],"backgroundTag":"missing-required-config-field","analyzedSha":"e7288fc434b4f4505b8452e1a57e8fb3111bb863","analyzedAt":"2026-09-08T15:39:16.015Z","contentChangedAt":"2026-09-08T15:39:16.015Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}