{"record":{"id":"ffcd73fc931c844e","repo":"apereo/cas","slug":"accountdisabledexception","errorCode":null,"errorMessage":"AccountDisabledException","messagePattern":"AccountDisabledException","errorType":"exception","errorClass":"AccountDisabledException","httpStatus":null,"severity":"error","filePath":"support/cas-server-support-redis-authentication/src/main/java/org/apereo/cas/redis/RedisAuthenticationHandler.java","lineNumber":44,"sourceCode":"                                      final CasRedisTemplate redisTemplate) {\n        super(name, principalFactory, order);\n        this.redisTemplate = redisTemplate;\n    }\n\n    @Override\n    protected AuthenticationHandlerExecutionResult authenticateUsernamePasswordInternal(\n        final UsernamePasswordCredential credential,\n        final String originalPassword) throws Throwable {\n        val account = (RedisUserAccount) redisTemplate.opsForValue().get(credential.getUsername());\n        if (account == null) {\n            throw new AccountNotFoundException();\n        }\n        if (!getPasswordEncoder().matches(originalPassword, account.getPassword())) {\n            LOGGER.warn(\"Account password on record for [{}] does not match the given/encoded password\", credential.getId());\n            throw new FailedLoginException();\n        }\n        switch (account.getStatus()) {\n            case DISABLED -> throw new AccountDisabledException();\n            case EXPIRED -> throw new AccountExpiredException();\n            case LOCKED -> throw new AccountLockedException();\n            case MUST_CHANGE_PASSWORD -> throw new AccountPasswordMustChangeException();\n            case OK -> LOGGER.debug(\"Account status is OK\");\n        }\n        val principal = principalFactory.createPrincipal(account.getUsername(), account.getAttributes());\n        return createHandlerResult(credential, principal, new ArrayList<>());\n    }\n}\n","sourceCodeStart":26,"sourceCodeEnd":54,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-redis-authentication/src/main/java/org/apereo/cas/redis/RedisAuthenticationHandler.java#L26-L54","documentation":"When the Redis account's Status is DISABLED, the handler throws AccountDisabledException immediately after successful password verification. The credentials were correct but the account is administratively disabled.","triggerScenarios":"RedisUserAccount.getStatus() == Status.DISABLED on the matched account after a successful password check.","commonSituations":"Admin disabled the user in the source-of-truth and the status was synced to Redis; stale status left in Redis after re-enabling the user in the upstream system; provisioning writes DISABLED by default for new users pending approval.","solutions":["Set the account status to OK in Redis (or fix upstream and re-sync)","Check the provisioning/sync job that populates status and re-run it after re-enabling the user","Confirm your user-approval workflow flips the status before login is expected to succeed"],"exampleFix":"// before\naccount.setStatus(Status.DISABLED);\nredisTemplate.opsForValue().set(username, account);\n// after\naccount.setStatus(Status.OK);\nredisTemplate.opsForValue().set(username, account);","handlingStrategy":"validation","validationCode":"RedisUserAccount acct = (RedisUserAccount) redisTemplate.opsForValue().get(username);\nif (acct != null && acct.getStatus() == Status.DISABLED) {\n    // short-circuit: show 'account disabled' instead of attempting auth\n}","typeGuard":"boolean isUsableAccount(RedisUserAccount a) { return a != null && a.getStatus() == Status.OK; }","tryCatchPattern":"try {\n    authHandler.authenticate(credential);\n} catch (AccountDisabledException e) {\n    // account-disabled messaging / support link\n}","preventionTips":["Keep status in Redis in sync with the upstream IdP/HR source","Re-run sync jobs promptly after enable/disable changes","Default new-user status to OK only after approval"],"tags":["redis","account-disabled","authentication","cas"],"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"}