apereo/cas · error
Unable to resolve service provider assertion consumer…
Error message
Unable to resolve service provider assertion consumer service URL for AuthnRequest construction for entityID: [{}] What it means
During unsolicited (IdP-initiated) SSO, CAS resolved the SP's metadata but could not determine the Assertion Consumer Service (ACS) URL ('shire') to build the AuthnRequest. The chosen AssertionConsumerService had neither a usable ResponseLocation nor Location, or no ACS was present at all, so MessageDecodingException is thrown. CAS refuses to guess an ACS endpoint.
Solutions
- Add or correct the AssertionConsumerService (with Binding and Location, optionally ResponseLocation) in the SP's metadata so CAS can resolve an ACS URL.
- If the request supplies an ACS index, ensure the SP metadata contains an AssertionConsumerService at that index with the right binding.
- Check CAS SamlRegisteredService settings (e.g. assertionConsumerService URLs / white/black lists) are not filtering out the SP's ACS.
- Verify the providerId/entityID parameter resolves to the intended EntityDescriptor — a wrong match may select an entity without an ACS.
- Inspect DEBUG logs for the metadata adaptor's resolved EntityDescriptor to confirm what ACS entries were seen.
Example fix
// before: SP metadata without ACS
<md:SPSSODescriptor AuthnRequestsSigned="false" WantAssertionsSigned="true" protocolSupportEnumeration="..."/>
// after: declare the ACS
<md:SPSSODescriptor ... protocolSupportEnumeration="...">
<md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="https://sp.example.com/Shibboleth.sso/SAML2/POST" index="0" isDefault="true"/>
</md:SPSSODescriptor> Defensive patterns
Strategy: validation
Validate before calling
// Pre-check SP metadata exposes at least one ACS with a Location
val entity = metadataResolver.resolveSingle(criteria(issuer));
boolean acsOk = entity.getSPSSODescriptor(SAML_20_NS).getAssertionConsumerServices().stream()
.anyMatch(acs -> StringUtils.isNotBlank(acs.getLocation()));
if (!acsOk) throw new IllegalStateException("SP metadata has no usable ACS for " + issuer); Type guard
boolean hasAcsLocation(EntityDescriptor ed) { return Optional.ofNullable(ed)
.map(e -> e.getSPSSODescriptor(SAML20P_NS))
.map(sp -> sp.getAssertionConsumerServices())
.map(list -> list.stream().anyMatch(a -> StringUtils.isNotBlank(a.getLocation())))
.orElse(false); } Try / catch
try {
shire = extractShire(request, providerId);
} catch (MessageDecodingException e) {
LOGGER.error("No ACS resolvable for entityID {}", providerId, e);
// return a clear error to the requesting application
} Prevention
- Require SP metadata to declare an AssertionConsumerService before onboarding.
- If IdP-initiated SSO is used, verify the ACS index/binding exists in SP metadata.
- Check CAS service white/black ACS lists whenever SP metadata changes.
When it happens
Trigger: extractShire looks up the SP's AssertionConsumerService for the given providerId/entityID; the optional chain yields blank/null when metadata has no matching AssertionConsumerService entry, or the entry's location and responseLocation are both empty/missing.
Common situations: SP metadata lacks an AssertionConsumerService element (common with hand-written or minimal metadata); IdP-initiated request specifies an ACS index/binding not present in SP metadata; entityID resolves to the wrong EntityDescriptor; white/black-listed ACS filtering in CAS service config excludes the SP's declared ACS.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Unable to resolve SP ACS URL for AuthnRequest construction
- No metadata could be found for
- No providerId parameter given in unsolicited SSO…
- No assertion consumer service could be found for entity
- Endpoint for is not available or does not define a binding…
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/30d8662414491faf.
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/SamlIdPInitiatedProfileHandlerController.java:162
val builder = (SAMLObjectBuilder) builderFactory.getBuilder(qname);
return clazz.cast(Objects.requireNonNull(builder).buildObject());
}
protected String extractShire(final HttpServletRequest request, final String providerId,
final SamlRegisteredServiceMetadataAdaptor facade)
throws MessageDecodingException {
var shire = request.getParameter(SamlIdPConstants.SHIRE);
if (StringUtils.isBlank(shire)) {
LOGGER.info("Resolving service provider assertion consumer service URL for [{}] and binding [{}]",
providerId, SAMLConstants.SAML2_POST_BINDING_URI);
val acs = facade.getAssertionConsumerService(SAMLConstants.SAML2_POST_BINDING_URI);
shire = Optional.ofNullable(acs)
.map(service -> StringUtils.isBlank(service.getResponseLocation())
? service.getLocation()
: service.getResponseLocation()).orElse(null);
}
if (StringUtils.isBlank(shire)) {
LOGGER.warn("Unable to resolve service provider assertion consumer service URL for AuthnRequest construction for entityID: [{}]", providerId);
throw new MessageDecodingException("Unable to resolve SP ACS URL for AuthnRequest construction");
}
return shire;
}
protected String extractProviderId(final HttpServletRequest request) throws MessageDecodingException {
val providerId = request.getParameter(SamlIdPConstants.PROVIDER_ID);
if (StringUtils.isBlank(providerId)) {
LOGGER.warn("No providerId parameter given in unsolicited SSO authentication request.");
throw new MessageDecodingException("Missing providerId");
}
return providerId;
}
}
View on GitHub (pinned to e7288fc434)