{"record":{"id":"c131638ecf6e17a1","repo":"apereo/cas","slug":"principal-attribute","errorCode":null,"errorMessage":"Principal attribute [","messagePattern":"Principal attribute \\[","errorType":"validation","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"support/cas-server-support-aup-jdbc/src/main/java/org/apereo/cas/aup/JdbcAcceptableUsagePolicyRepository.java","lineNumber":104,"sourceCode":"     * @return the acceptable usage policy column name\n     */\n    protected String getAcceptableUsagePolicyColumnName(final JdbcAcceptableUsagePolicyProperties jdbc) {\n        return StringUtils.defaultIfBlank(jdbc.getAupColumn(), aupProperties.getCore().getAupAttributeName()).trim();\n    }\n\n    /**\n     * Extracts principal ID from a principal attribute or the provided credentials.\n     *\n     * @param principal the principal\n     * @return the principal ID to update the AUP setting in the database for\n     */\n    protected String determinePrincipalId(final Principal principal) {\n        if (StringUtils.isBlank(aupProperties.getJdbc().getPrincipalIdAttribute())) {\n            return principal.getId();\n        }\n        val pIdAttribName = aupProperties.getJdbc().getPrincipalIdAttribute();\n        if (!principal.getAttributes().containsKey(pIdAttribName)) {\n            throw new IllegalStateException(\"Principal attribute [\" + pIdAttribName + \"] cannot be found\");\n        }\n        val pIdAttributeValue = principal.getAttributes().get(pIdAttribName);\n        val pIdAttributeValues = CollectionUtils.toCollection(pIdAttributeValue);\n        var principalId = StringUtils.EMPTY;\n        if (!pIdAttributeValues.isEmpty()) {\n            principalId = pIdAttributeValues.iterator().next().toString().trim();\n        }\n        if (pIdAttributeValues.size() > 1) {\n            LOGGER.warn(\"Principal attribute [{}] was found, but its value [{}] is multi-valued. \"\n                        + \"Proceeding with the first element [{}]\", pIdAttribName, pIdAttributeValue, principalId);\n        }\n        if (principalId.isEmpty()) {\n            throw new IllegalStateException(\"Principal attribute [\" + pIdAttribName + \"] was found, but it is either empty\"\n                                            + \" or multi-valued with an empty element\");\n        }\n        return principalId;\n    }\n}","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-aup-jdbc/src/main/java/org/apereo/cas/aup/JdbcAcceptableUsagePolicyRepository.java#L86-L122","documentation":"Thrown by JdbcAcceptableUsagePolicyRepository.determinePrincipalId when the configured cas.acceptable-usage-policy.jdbc.principal-id-column/attribute name does not exist among the authenticated principal's attributes. CAS uses this attribute to look up the AUP record keyed by an alternate principal identifier, so a missing attribute makes the mapping impossible. It surfaces as IllegalStateException from determinePrincipalId, invoked via principalId during AUP policy checks.","triggerScenarios":"cas.acceptable-usage-policy.jdbc.principal-id-attribute is set to a name (e.g. 'employeeId') that is absent from principal.getAttributes() at the time the AUP repository resolves the principal id — typically after login when the attribute was never released into the principal.","commonSituations":"Typo in the attribute name in cas.properties; the attribute resolution strategy (source attribute release policy, LDAP/attribute repository config) does not actually fetch or release that attribute; casing mismatch between configured name and the attribute produced by the principal factory.","solutions":["Verify the attribute name in cas.acceptable-usage-policy.jdbc.principal-id-attribute exactly matches an attribute the principal actually carries (check the attribute name and casing).","Ensure the attribute is fetched and released: adjust the authentication/attribute repository source or service release policy so it appears on the principal before AUP evaluation.","If the CAS principal id itself is the right key, remove/unset the principal-id-attribute so determinePrincipalId falls back to principal.getId().","Log the full principal attribute map (or check the audit/inspektr logs) to see which attributes are actually available at AUP evaluation time."],"exampleFix":"// before (application.properties)\ncas.acceptable-usage-policy.jdbc.principal-id-attribute=employeeid\n\n// after (attribute actually present on the principal)\ncas.acceptable-usage-policy.jdbc.principal-id-attribute=employeeId","handlingStrategy":"validation","validationCode":"// before enabling AUP-JDBC, confirm the attribute reaches the principal\nif (!principal.getAttributes().containsKey(configuredPrincipalIdAttribute)) {\n    throw new IllegalStateException(\"AUP principal-id attribute missing: \" + configuredPrincipalIdAttribute);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Assert the attribute exists on the principal in a startup/integration test before deploying the AUP-JDBC config.","Keep attribute names exactly as produced by the principal factory; avoid case drift between config and source.","If unsure, omit principal-id-attribute and rely on the default principal.getId()."],"tags":["aup","jdbc","principal-attributes","cas"],"backgroundTag":"missing-required-config-field","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"}