{"record":{"id":"5c6ebb201d1ff106","repo":"apereo/cas","slug":"account-has-been-disabled","errorCode":null,"errorMessage":"Account has been disabled","messagePattern":"Account has been disabled","errorType":"exception","errorClass":"AccountDisabledException","httpStatus":null,"severity":"warning","filePath":"support/cas-server-support-jdbc-authentication/src/main/java/org/apereo/cas/jdbc/QueryAndEncodeDatabaseAuthenticationHandler.java","lineNumber":69,"sourceCode":"        final UsernamePasswordCredential transformedCredential, final String originalPassword) throws Throwable {\n        val username = transformedCredential.getUsername();\n        try {\n            val sqlQueryResults = performSqlQuery(username);\n            val digestedPassword = databasePasswordEncoder.encode(transformedCredential.toPassword(), sqlQueryResults);\n\n            if (!sqlQueryResults.get(properties.getPasswordFieldName()).equals(digestedPassword)) {\n                throw new FailedLoginException(\"Password does not match value on record.\");\n            }\n            if (StringUtils.isNotBlank(properties.getExpiredFieldName()) && sqlQueryResults.containsKey(properties.getExpiredFieldName())) {\n                val dbExpired = sqlQueryResults.get(properties.getExpiredFieldName()).toString();\n                if (BooleanUtils.toBoolean(dbExpired) || \"1\".equals(dbExpired)) {\n                    throw new AccountPasswordMustChangeException(\"Password has expired\");\n                }\n            }\n            if (StringUtils.isNotBlank(properties.getDisabledFieldName()) && sqlQueryResults.containsKey(properties.getDisabledFieldName())) {\n                val dbDisabled = sqlQueryResults.get(properties.getDisabledFieldName()).toString();\n                if (BooleanUtils.toBoolean(dbDisabled) || \"1\".equals(dbDisabled)) {\n                    throw new AccountDisabledException(\"Account has been disabled\");\n                }\n            }\n            val attributes = collectPrincipalAttributes(sqlQueryResults);\n            val principal = principalFactory.createPrincipal(username, attributes);\n            return createHandlerResult(transformedCredential, principal, new ArrayList<>());\n        } catch (final IncorrectResultSizeDataAccessException e) {\n            if (e.getActualSize() == 0) {\n                throw new AccountNotFoundException(username + \" not found with SQL query\");\n            }\n            throw new FailedLoginException(\"Multiple records found for \" + username);\n        } catch (final DataAccessException e) {\n            throw new PreventedException(e);\n        }\n    }\n\n    protected Map<String, Object> performSqlQuery(final String username) {\n        return getJdbcTemplate().queryForMap(properties.getSql(), username);\n    }","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-jdbc-authentication/src/main/java/org/apereo/cas/jdbc/QueryAndEncodeDatabaseAuthenticationHandler.java#L51-L87","documentation":"The handler throws AccountDisabledException('Account has been disabled') when the row returned by the SQL query has a truthy value in the column named by properties.getDisabledFieldName(). Authentication stops even though the password was correct, because the account record is administratively disabled.","triggerScenarios":"Query result contains the disabled-field column whose value is BooleanUtils.toBoolean(...) true or the string \"1\".","commonSituations":"Admin deactivated the account (locked, leave of absence, terminated), HR/identity sync set the flag, disabledFieldName accidentally mapped to a column that is 1 for all users.","solutions":["Re-enable the account in the source database (set flag to 0/false)","Verify disabledFieldName maps to the correct schema column","Check upstream provisioning/identity sync that may have disabled the user","If the flag is stale, correct it in the user-management system of record"],"exampleFix":"// before: points at 'locked' tinyint that is always 1\n// cas.authn.jdbc.encode[0].fieldDisabled=locked\n// after\n// cas.authn.jdbc.encode[0].fieldDisabled=account_disabled","handlingStrategy":"try-catch","validationCode":"boolean disabled = jdbc.queryForObject(\"SELECT account_disabled FROM users WHERE username=?\", Boolean.class, user);\nif (disabled) return accountDisabledPage(user);","typeGuard":null,"tryCatchPattern":"try {\n    authResult = handler.authenticate(credential);\n} catch (AccountDisabledException e) {\n    // valid credentials but deactivated account\n    return showAccountDisabledNotice(user);\n}","preventionTips":["Verify fieldDisabled/fieldDisabled maps to a real account-status column, not a co-opted flag","Keep the disable/enable lifecycle in one system of record","Notify admins when accounts get disabled by sync jobs","Return a distinct user-facing message for disabled vs wrong password"],"tags":["jdbc","account-status","account-disabled"],"backgroundTag":"account-disabled","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"}