apereo/cas · warning

SAML2 attribute query profile is not enabled

Error message

SAML2 attribute query profile is not enabled

What it means

The SAML2 SOAP Attribute Query profile endpoint was hit while the profile is disabled in CAS properties. The controller logs a warning and responds with HTTP 501 Not Implemented instead of processing the AttributeQuery, by design as a feature switch.

Solutions

  1. Set cas.authn.saml-idp.core.attribute-query-profile-enabled=true in CAS properties
  2. Ensure the configuration change is applied to the running deployment (reload/refresh)
  3. If the profile is not needed, have the SP stop sending AttributeQuery requests to this endpoint

Example fix

// before (application.properties)
# (property absent, default false)
// after
cas.authn.saml-idp.core.attribute-query-profile-enabled=true
Defensive patterns

Strategy: validation

Validate before calling

// Check the feature flag before sending an AttributeQuery
boolean enabled = casProperties.getAuthn().getSamlIdp().getCore().isAttributeQueryProfileEnabled();
if (!enabled) {
    // endpoint will return 501; enable the property first
}

Try / catch

try {
    sendAttributeQuery(soapRequest);
} catch (HttpException e) {
    if (e.getStatusCode() == 501) {
        LOGGER.error("Attribute Query profile disabled on IdP; enable "
            + "cas.authn.saml-idp.core.attribute-query-profile-enabled");
    }
}

Prevention

When it happens

Trigger: A POST to ENDPOINT_SAML2_SOAP_ATTRIBUTE_QUERY where cas.authn.saml-idp.core.attribute-query-profile-enabled is false; handlePostRequest checks isAttributeQueryProfileEnabled() and short-circuits.

Common situations: SP sends SOAP AttributeQuery requests but the IdP was deployed with the profile left at its disabled default; config property missing from deployment; ops unaware the feature must be explicitly enabled.

Related errors


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

Appendix: source

Thrown at support/cas-server-support-saml-idp-web/src/main/java/org/apereo/cas/support/saml/web/idp/profile/query/SamlIdPSaml2AttributeQueryProfileHandlerController.java:61

public class SamlIdPSaml2AttributeQueryProfileHandlerController extends AbstractSamlIdPProfileHandlerController {
    public SamlIdPSaml2AttributeQueryProfileHandlerController(final SamlProfileHandlerConfigurationContext context) {
        super(context);
    }

    /**
     * Handle post request.
     *
     * @param response the response
     * @param request  the request
     * @throws Exception the exception
     */
    @PostMapping(path = SamlIdPConstants.ENDPOINT_SAML2_SOAP_ATTRIBUTE_QUERY)
    @Operation(summary = "Handle SAML2 SOAP Attribute Query Request")
    protected void handlePostRequest(final HttpServletResponse response,
                                     final HttpServletRequest request) throws Exception {
        val enabled = configurationContext.getCasProperties().getAuthn().getSamlIdp().getCore().isAttributeQueryProfileEnabled();
        if (!enabled) {
            LOGGER.warn("SAML2 attribute query profile is not enabled");
            response.setStatus(HttpStatus.SC_NOT_IMPLEMENTED);
            return;
        }

        val ctx = decodeSoapRequest(request);
        val query = (AttributeQuery) ctx.getMessage();
        try {
            val issuer = Objects.requireNonNull(query).getIssuer().getValue();
            val registeredService = verifySamlRegisteredService(issuer, request);
            val adaptor = getSamlMetadataFacadeFor(registeredService, query);
            val facade = adaptor.orElseThrow(() -> UnauthorizedServiceException.denied("Cannot find metadata linked to %s".formatted(issuer)));
            verifyAuthenticationContextSignature(ctx, request, query, facade, registeredService);

            val nameIdValue = determineNameIdForQuery(query, registeredService, facade);
            val factory = (SamlAttributeQueryTicketFactory) getConfigurationContext().getTicketFactory()
                .get(SamlAttributeQueryTicket.class);
            val id = factory.createTicketIdFor(nameIdValue, facade.getEntityId());
            LOGGER.debug("Created ticket id for attribute query [{}]", id);

View on GitHub (pinned to e7288fc434)