apereo/cas · warning

No custom principal attribute was provided by the client

Error message

No custom principal attribute was provided by the client [{}]. Using the default id [{}]

What it means

BaseDelegatedClientAuthenticationHandler.determinePrincipalIdFrom logs this warning when the pac4j client reports a custom principal attribute type (principalAttribute set on the client/profile), yet the client did not actually supply that attribute, so CAS falls back to the profile's default identifier. Authentication still succeeds; only the principal-id source differs from the requested one.

Solutions

  1. Configure the provider to release the expected attribute (scopes/claims/attribute-release policy).
  2. Fix the client's principal attribute name so it matches an attribute present in the profile.
  3. Accept the default id and silence the warning by removing the client principal-attribute configuration if the default typed id is acceptable.

Example fix

// before (client config requesting an attribute the IdP never sends)
client.setPrincipalAttribute("sub"); // sub not in profile
// after
client.setPrincipalAttribute("email"); // email present in profile
Defensive patterns

Strategy: validation

Validate before calling

if (StringUtils.isNotBlank(clientPrincipalAttribute) && !profile.containsAttribute(clientPrincipalAttribute)) {
    // request the attribute via provider scopes or correct the name
}

Prevention

When it happens

Trigger: The pac4j client's principal attribute is configured (client's principalAttribute non-blank) but the returned profile lacks the attribute value (the else branch when firstAttribute/attribute is absent), during determinePrincipalIdFrom called via extractedCredential in delegated client authentication.

Common situations: Provider not releasing the configured client principal attribute; misconfigured client-level principal attribute name; providers returning thin profiles (e.g. implicit flow with minimal claims).

Related errors


AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08). Data as JSON: /api/errors/c814f1fc02daee6f. 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:122

    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) {
            id = profile.getTypedId();
            LOGGER.debug("Authentication indicates usage of typed profile id [{}]", id);
        }

View on GitHub (pinned to e7288fc434)