{"record":{"id":"776f90c0cad192ca","repo":"apereo/cas","slug":"could-not-authenticate-account-for-username","errorCode":null,"errorMessage":"Could not authenticate account for ${username}","messagePattern":"Could not authenticate account for (.+?)","errorType":"exception","errorClass":"FailedLoginException","httpStatus":401,"severity":"error","filePath":"support/cas-server-support-rest-authentication/src/main/java/org/apereo/cas/adaptors/rest/RestAuthenticationHandler.java","lineNumber":94,"sourceCode":"        final String originalPassword) throws Throwable {\n\n        var response = (HttpResponse) null;\n        try {\n            val exec = HttpExecutionRequest\n                .builder()\n                .basicAuthUsername(credential.getUsername())\n                .basicAuthPassword(credential.toPassword())\n                .method(HttpMethod.valueOf(properties.getMethod().toUpperCase(Locale.ENGLISH)))\n                .url(SpringExpressionLanguageValueResolver.getInstance().resolve(properties.getUri()))\n                .httpClient(httpClient)\n                .build()\n                .withoutRetry();\n            response = HttpUtils.execute(exec);\n            val status = HttpStatus.resolve(Objects.requireNonNull(response).getCode());\n            return switch (Objects.requireNonNull(status)) {\n                case OK -> buildPrincipalFromResponse(credential, response);\n                case FORBIDDEN -> throw new AccountDisabledException(\"Could not authenticate forbidden account for \" + credential.getUsername());\n                case UNAUTHORIZED -> throw new FailedLoginException(\"Could not authenticate account for \" + credential.getUsername());\n                case NOT_FOUND -> throw new AccountNotFoundException(\"Could not locate account for \" + credential.getUsername());\n                case LOCKED -> throw new AccountLockedException(\"Could not authenticate locked account for \" + credential.getUsername());\n                case PRECONDITION_FAILED -> throw new AccountExpiredException(\"Could not authenticate expired account for \" + credential.getUsername());\n                case PRECONDITION_REQUIRED -> throw new AccountPasswordMustChangeException(\"Account password must change for \" + credential.getUsername());\n                default -> throw new FailedLoginException(\"Rest endpoint returned an unknown status code \" + status + \" for \" + credential.getUsername());\n            };\n        } finally {\n            HttpUtils.close(response);\n        }\n    }\n\n    protected AuthenticationHandlerExecutionResult buildPrincipalFromResponse(\n        final UsernamePasswordCredential credential,\n        final HttpResponse response) throws Throwable {\n        try {\n            try (val content = ((HttpEntityContainer) response).getEntity().getContent()) {\n                val result = IOUtils.toString(content, StandardCharsets.UTF_8);\n                LOGGER.debug(\"REST authentication response received: [{}]\", result);","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-rest-authentication/src/main/java/org/apereo/cas/adaptors/rest/RestAuthenticationHandler.java#L76-L112","documentation":"RestAuthenticationHandler throws FailedLoginException when the remote REST authentication endpoint replies HTTP 401 UNAUTHORIZED. This means the credentials were rejected as invalid — the standard 'bad username or password' outcome for REST authentication.","triggerScenarios":"authenticateUsernamePasswordInternal sends the encoded credentials to the REST endpoint; it responds 401 and the switch maps UNAUTHORIZED -> FailedLoginException.","commonSituations":"User typed a wrong password; client and server disagree on password encoding (e.g. the endpoint expects raw but CAS sends encoded); credentials for the endpoint's own basic-auth are wrong so 401 reflects the endpoint, not the user.","solutions":["Confirm the user's username/password are correct","Check cas.authn.rest.password-encoder settings match what the endpoint expects (plain vs encoded)","If the endpoint itself requires basic auth, verify the configured basicAuthUsername/basicAuthPassword are valid","Inspect endpoint logs to see whether 401 came from user validation or endpoint authentication"],"exampleFix":"// before\nPOST /auth  ->  401 Unauthorized (wrong password)\n// after\nPOST /auth  ->  200 OK (correct credentials)","handlingStrategy":"try-catch","validationCode":"// Validate credentials format client-side before the call\nif (username == null || username.isBlank() || password == null || password.isEmpty()) {\n    throw new IllegalArgumentException(\"Username and password required\");\n}","typeGuard":"boolean isUnauthorized(HttpResponse r) { return r != null && r.getCode() == 401; }","tryCatchPattern":"try {\n    return restHandler.authenticate(credential);\n} catch (FailedLoginException e) {\n    LOGGER.debug(\"Bad credentials for REST auth: {}\", e.getMessage());\n    throw e; // let CAS throttling/warning machinery handle it\n}","preventionTips":["Match password-encoding config (cas.authn.rest.password-encoder) with the endpoint's expectation","Verify any configured basic-auth credentials for the endpoint itself are current","Test with a known-good credential after endpoint changes","Check endpoint logs to distinguish user-vs-endpoint 401s"],"tags":["authentication","rest","http-401","bad-credentials"],"backgroundTag":"authentication-required","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"}