{"record":{"id":"ab793cd50a0ab65f","repo":"apereo/cas","slug":"could-not-authenticate-account-for","errorCode":null,"errorMessage":"Could not authenticate account for ","messagePattern":"Could not authenticate account for ","errorType":"exception","errorClass":"FailedLoginException","httpStatus":null,"severity":"error","filePath":"support/cas-server-support-syncope-authentication/src/main/java/org/apereo/cas/syncope/SyncopeAuthenticationHandler.java","lineNumber":75,"sourceCode":"        val result = authenticateSyncopeUser(credential);\n        if (result.isPresent()) {\n            val user = result.get();\n            LOGGER.debug(\"Received Syncope user object as [{}]\", user);\n            if (user.has(\"suspended\") && user.get(\"suspended\").asBoolean()) {\n                throw new AccountDisabledException(\n                    \"Could not authenticate forbidden account for \" + credential.getUsername());\n            }\n            if (user.has(\"mustChangePassword\") && user.get(\"mustChangePassword\").asBoolean()) {\n                throw new AccountPasswordMustChangeException(\n                    \"Account password must change for \" + credential.getUsername());\n            }\n            val principalAttributes = SyncopeUtils.convertFromUserEntity(user, properties.getAttributeMappings());\n            val name = properties.getAttributeMappings().getOrDefault(\"domain\", \"syncopeDomain\");\n            principalAttributes.put(name, CollectionUtils.wrapList(syncopeDomain));\n            val principal = principalFactory.createPrincipal(user.get(\"username\").asString(), principalAttributes);\n            return createHandlerResult(credential, principal, new ArrayList<>());\n        }\n        throw new FailedLoginException(\"Could not authenticate account for \" + credential.getUsername());\n    }\n\n    protected Optional<JsonNode> authenticateSyncopeUser(final UsernamePasswordCredential credential) {\n        HttpResponse response = null;\n        try {\n            val syncopeRestUrl = Strings.CI.appendIfMissing(\n                SpringExpressionLanguageValueResolver.getInstance().resolve(properties.getUrl()),\n                \"/rest/users/self\");\n            val exec = HttpExecutionRequest.builder()\n                .method(HttpMethod.GET)\n                .url(syncopeRestUrl)\n                .basicAuthUsername(credential.getUsername())\n                .basicAuthPassword(credential.toPassword())\n                .headers(CollectionUtils.wrap(SyncopeUtils.SYNCOPE_HEADER_DOMAIN, syncopeDomain))\n                .maximumRetryAttempts(properties.getMaxRetryAttempts())\n                .build();\n            response = HttpUtils.execute(exec);\n            if (response != null) {","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-syncope-authentication/src/main/java/org/apereo/cas/syncope/SyncopeAuthenticationHandler.java#L57-L93","documentation":"SyncopeAuthenticationHandler.authenticateUsernamePasswordInternal throws FailedLoginException when authenticateSyncopeUser returns an empty Optional, i.e. Syncope did not authenticate the supplied username/password (bad credentials, unknown user, or an upstream call that yielded no user). CAS translates that into a generic FailedLoginException for the standard authentication flow.","triggerScenarios":"POST to Syncope's REST authentication endpoint for the configured domain returns no user (401/404, wrong credentials, or non-matching realm) so authenticateSyncopeUser yields Optional.empty.","commonSituations":"Wrong password or username typo; user exists in a different Syncope domain/realm than cas.authn.syncope.domain; misconfigured syncopeRestUrl or admin credentials for the authentication REST call; Syncope access-token/admin user lacking rights in the target realm.","solutions":["Verify the username/password are correct and the user is in the configured Syncope domain (cas.authn.syncope.domain)","Check cas.authn.syncope.url, basic-authn-username/password used to call Syncope, and network reachability from CAS to Syncope","Confirm the user's realm in Syncope is one the configured admin account may access","Enable debug logging on Syncope side to see why the auth REST call returns empty","If this persists without user error, inspect Syncope access tokens / core REST config"],"exampleFix":"// before\ncas.authn.syncope.url=http://localhost:8080/syncope\ncas.authn.syncope.domain=Two\n// after\ncas.authn.syncope.url=http://syncope:8080/syncope\ncas.authn.syncope.domain=Two\ncas.authn.syncope.basic-authn-username=admin\ncas.authn.syncope.basic-authn-password=secret","handlingStrategy":"retry","validationCode":"// before CAS login, check reachability\ntry (var resp = HttpClient.newHttpClient().send(\n    HttpRequest.newBuilder(URI.create(syncopeUrl + \"/rest/users?FIQLString=username==\" + u)).header(\"Authorization\", basic).build(),\n    BodyHandlers.ofString())) {\n    if (resp.statusCode() != 200) throw new IllegalStateException(\"Syncope unreachable: \" + resp.statusCode());\n}","typeGuard":null,"tryCatchPattern":"try {\n    return authenticationManager.authenticate(transaction);\n} catch (FailedLoginException e) {\n    LOGGER.warn(\"Syncope login failed for user\", e);\n    throw new BadCredentialsException(\"invalid.username.or.password\");\n} catch (Exception e) {\n    // network / 5xx — consider retry or degraded mode\n}","preventionTips":["Double-check cas.authn.syncope.url and domain against Syncope deployment","Use a dedicated Syncope admin account with only the needed realm rights","Add health-check monitoring of Syncope from the CAS host","Log (without secrets) the Syncope REST response status on failure for triage","Don't leak detailed failure reasons to end users; show generic bad-credentials message"],"tags":["syncope","failed-login","bad-credentials","authentication","cas"],"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"}