{"record":{"id":"1cbb3963c25d641a","repo":"apereo/cas","slug":"principal-id-attribute-is-not-found-for-principal","errorCode":null,"errorMessage":"Principal id attribute is not found for [principalAttr]","messagePattern":"Principal id attribute is not found for \\[principalAttr\\]","errorType":"exception","errorClass":"LoginException","httpStatus":null,"severity":"error","filePath":"support/cas-server-support-ldap-core/src/main/java/org/apereo/cas/authentication/LdapAuthenticationHandler.java","lineNumber":208,"sourceCode":"     * @param ldapEntry the ldap entry\n     * @return the ldap principal identifier\n     * @throws LoginException in case the principal id cannot be determined.\n     */\n    protected String getLdapPrincipalIdentifier(final String username, final LdapEntry ldapEntry) throws LoginException {\n        if (StringUtils.isNotBlank(this.principalIdAttribute)) {\n            val principalAttr = ldapEntry.getAttribute(this.principalIdAttribute);\n            if (principalAttr == null || principalAttr.size() == 0) {\n                if (this.allowMissingPrincipalAttributeValue) {\n                    LOGGER.warn(\"The principal id attribute [{}] is not found. CAS cannot construct the final authenticated principal \"\n                            + \"if it's unable to locate the attribute that is designated as the principal id. \"\n                            + \"Attributes available on the LDAP entry are [{}]. Since principal id attribute is not available, CAS will \"\n                            + \"fall back to construct the principal based on the provided user id: [{}]\",\n                        this.principalIdAttribute, ldapEntry.getAttributes(), username);\n                    return username;\n                }\n                LOGGER.error(\"The principal id attribute [{}] is not found. CAS is configured to disallow missing principal attributes\",\n                    this.principalIdAttribute);\n                throw new LoginException(\"Principal id attribute is not found for \" + principalAttr);\n            }\n            val value = principalAttr.getStringValue();\n            if (principalAttr.size() > 1) {\n                if (!this.allowMultiplePrincipalAttributeValues) {\n                    throw new LoginException(\"Multiple principal values are not allowed: \" + principalAttr);\n                }\n                LOGGER.warn(\"Found multiple values for principal id attribute: [{}]. Using first value=[{}].\", principalAttr, value);\n            }\n            LOGGER.debug(\"Retrieved principal id attribute [{}]\", value);\n            return value;\n        }\n        LOGGER.debug(\"Principal id attribute is not defined. Using the default provided user id [{}]\", username);\n        return username;\n    }\n\n    private AuthenticationResponse getLdapAuthenticationResponse(final UsernamePasswordCredential upc) throws PreventedException {\n        try {\n            LOGGER.debug(\"Attempting LDAP authentication for [{}]. Authenticator pre-configured attributes are [{}], \"","sourceCodeStart":190,"sourceCodeEnd":226,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-ldap-core/src/main/java/org/apereo/cas/authentication/LdapAuthenticationHandler.java#L190-L226","documentation":"During principal construction, getLdapPrincipalIdentifier reads the configured principalIdAttribute from the LDAP entry. When the attribute is missing and CAS is configured to disallow missing principal id attributes (allowMissingPrincipalAttributeValues=false), it throws LoginException 'Principal id attribute is not found'.","triggerScenarios":"cas.authn.ldap[].principal-id-attribute names an attribute absent from the authenticated entry (or empty), and allow-missing-principal-attribute-values is false, so the code cannot fall back to the username.","commonSituations":"Attribute not returned by the directory (not in returned-attributes list, wrong case, or simply not populated for the user); typo in principal-id-attribute name; after migration where the attribute (e.g. sAMAccountName vs uid) differs.","solutions":["Set principal-id-attribute to an attribute actually present on the entry (verify with ldapsearch).","Enable allow-missing-principal-attribute-values=true so CAS falls back to the provided user id.","Add the attribute to returned-attributes / ensure the ACL allows reading it.","Fix casing/typo of the attribute name in the configuration."],"exampleFix":"// before\ncas.authn.ldap[0].principal-id-attribute=employeeId\ncas.authn.ldap[0].allow-missing-principal-attribute-values=false\n// after\ncas.authn.ldap[0].principal-id-attribute=sAMAccountName\ncas.authn.ldap[0].allow-missing-principal-attribute-values=true","handlingStrategy":"validation","validationCode":"// ensure the attribute is present before configuring it as principal id\nSearchResult sr = connectionFactory.search(\n  new SearchRequest(baseDn, userFilter, \"sAMAccountName\"));\nLdapEntry entry = sr.getResult().getEntry();\nif (!entry.getAttributes().containsKey(principalIdAttribute)) {\n  throw new IllegalStateException(\"Attribute missing: \" + principalIdAttribute);\n}","typeGuard":null,"tryCatchPattern":"try { result = handler.authenticate(credential); }\ncatch (LoginException e) { if (e.getMessage().startsWith(\"Principal id attribute\")) { fixPrincipalIdConfig(); } }","preventionTips":["ldapsearch a sample user to confirm the principal-id attribute exists and is returned.","Set allow-missing-principal-attribute-values=true for resilience.","Include the attribute in returned-attributes and confirm ACLs permit reading it."],"tags":["ldap","principal","configuration"],"backgroundTag":"attribute-not-found","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"}