apereo/cas · warning

Authentication cannot find attribute

Error message

Authentication cannot find attribute [{}] to use as principal id

What it means

BaseDelegatedClientAuthenticationHandler.determinePrincipalIdFrom warns when a per-client principal attribute (client config principal-attribute name) was configured, but the authenticated pac4j user profile does not contain that attribute, so the attribute cannot be used as the principal id. CAS continues with the profile's default identifier.

Solutions

  1. Request/release the attribute from the provider (add the scope/claim, e.g. cas.authn.pac4j.oidc[0].scope=openid profile email, or configure SAML attribute release).
  2. Correct the configured principal attribute name to one actually present in the provider profile.
  3. Remove the principal-attribute setting so CAS falls back to the default profile id intentionally.

Example fix

// before
cas.authn.pac4j.oidc[0].principal-attribute-id=userPrincipalName
// after (attribute the IdP actually releases)
cas.authn.pac4j.oidc[0].principal-attribute-id=email
Defensive patterns

Strategy: validation

Validate before calling

// after authentication, before using the attribute
if (StringUtils.isNotBlank(principalAttribute) && !profile.containsAttribute(principalAttribute)) {
    logger.warn("Provider did not release [{}]; falling back to default id", principalAttribute);
}

Prevention

When it happens

Trigger: Delegated client configuration (cas.authn.pac4j.<client>.principal-attribute-id / client principalAttribute) names an attribute, profile.containsAttribute(...) is false after provider authentication, i.e. the provider did not release that attribute.

Common situations: OIDC/OAuth providers not asked for or not returning the configured attribute (missing scope/claim mapping); attribute renamed on the provider side; typo in configured attribute name; SAML providers not releasing the attribute.

Understand the failure class

Related errors


AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08). Data as JSON: /api/errors/42c0e8130410f152. Report an issue: GitHub.

Appendix: source

Thrown at support/cas-server-support-pac4j-core-clients/src/main/java/org/apereo/cas/support/pac4j/authentication/handler/support/BaseDelegatedClientAuthenticationHandler.java:119

                                                          final Service service) throws Throwable {
    }

    protected String determinePrincipalIdFrom(final UserProfile profile, final BaseClient client) {
        var id = profile.getId();
        val properties = client != null ? client.getCustomProperties() : new HashMap<>();
        if (client != null && properties.containsKey(ClientCustomPropertyConstants.CLIENT_CUSTOM_PROPERTY_PRINCIPAL_ATTRIBUTE_ID)) {
            val attrObject = properties.get(ClientCustomPropertyConstants.CLIENT_CUSTOM_PROPERTY_PRINCIPAL_ATTRIBUTE_ID);
            if (attrObject != null) {
                val principalAttribute = attrObject.toString();
                if (profile.containsAttribute(principalAttribute)) {
                    val firstAttribute = CollectionUtils.firstElement(profile.getAttribute(principalAttribute));
                    if (firstAttribute.isPresent()) {
                        id = firstAttribute.get().toString();
                        id = typePrincipalId(id, profile);
                    }
                    LOGGER.debug("Authentication indicates usage of client principal attribute [{}] for the identifier [{}]", principalAttribute, id);
                } else {
                    LOGGER.warn("Authentication cannot find attribute [{}] to use as principal id", principalAttribute);
                }
            } else {
                LOGGER.warn("No custom principal attribute was provided by the client [{}]. Using the default id [{}]", client, id);
            }
        } else if (StringUtils.isNotBlank(principalAttributeId)) {
            if (profile.containsAttribute(principalAttributeId)) {
                val firstAttribute = CollectionUtils.firstElement(profile.getAttribute(principalAttributeId));
                if (firstAttribute.isPresent()) {
                    id = firstAttribute.get().toString();
                    id = typePrincipalId(id, profile);
                }
            } else {
                LOGGER.warn("CAS cannot use [{}] as the principal attribute id, since the profile attributes do not contain the attribute. "
                    + "Either adjust the CAS configuration to use a different attribute, or contact the authentication provider noted by [{}] "
                    + "to release the expected attribute to CAS", principalAttributeId, profile.getAttributes());
            }
            LOGGER.debug("Authentication indicates usage of attribute [{}] for the identifier [{}]", principalAttributeId, id);
        } else if (isTypedIdUsed) {

View on GitHub (pinned to e7288fc434)