apereo/cas · error · SamlException
Endpoint for is not available or does not define a binding…
Error message
Endpoint for is not available or does not define a binding for
What it means
SamlIdPUtils.determineEndpointForRequest() resolves the response endpoint for an AuthnRequest using the requested binding. If after checking metadata ACS, request-supplied ACS, and index-based lookup the endpoint is still null, it throws SamlException indicating the peer entity does not define an endpoint for that binding.
Solutions
- Add an AssertionConsumerService entry with the requested Binding (e.g. urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST) and Location to the SP metadata.
- Check the AuthnRequest's ProtocolBinding/AssertionConsumerServiceIndex/URL against the metadata and align them.
- Refresh the SP metadata in CAS so it reflects the SP's current ACS declarations.
- Verify the `binding` parameter passed by the caller matches a binding the SP actually supports.
Example fix
// before <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://sp.example.com/acs" index="0"/> // after <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://sp.example.com/acs" index="0" isDefault="true"/>
Defensive patterns
Strategy: validation
Validate before calling
// before responding
boolean hasBinding = adaptor.getAssertionConsumerServices().stream()
.anyMatch(acs -> binding.equalsIgnoreCase(acs.getBinding()));
if (!hasBinding) {
logger.warn("SP {} has no ACS for binding {}", adaptor.getEntityId(), binding);
} Try / catch
try {
endpoint = SamlIdPUtils.determineEndpointForRequest(authnRequest, adaptor, binding, fromReq, fromMeta, context);
} catch (SamlException e) {
logger.error("No endpoint for binding {}: {}", binding, e.getMessage());
} Prevention
- Ensure SP metadata declares an HTTP-POST ACS (the most commonly requested binding).
- Keep SP metadata refreshed so binding declarations stay current.
- Log the AuthnRequest ProtocolBinding/index and compare to metadata when debugging.
When it happens
Trigger: preparePeerEntitySamlEndpointContext() calls determineEndpointForRequest with a binding (e.g. POST or Redirect) for which neither the request's AssertionConsumerServiceURL/index nor the metadata's AssertionConsumerService entries yield a matching endpoint, leaving endpoint null.
Common situations: SP metadata only declares a SOAP or Artifact binding while CAS is asked to respond with POST; AuthnRequest references an ACS index/binding absent from metadata; metadata is stale relative to the SP's current configuration.
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
- Endpoint for does not define a binding or location for…
- No assertion consumer service could be found for entity
- Metadata directory location cannot be located/created
- Multiple S3 objects where found in bucket
- Metadata directory location cannot be located/created
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/98a1a377c78011df.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-saml-idp-core/src/main/java/org/apereo/cas/support/saml/SamlIdPUtils.java:119
* @param adaptor the adaptor
* @param binding the binding
* @return the assertion consumer service
*/
public static Endpoint determineEndpointForRequest(final Pair<? extends RequestAbstractType, MessageContext> authnContext,
final SamlRegisteredServiceMetadataAdaptor adaptor,
final String binding) {
var endpoint = (Endpoint) null;
val authnRequest = authnContext.getLeft();
if (authnRequest instanceof LogoutRequest) {
endpoint = adaptor.getSingleLogoutService(binding);
} else {
val acsEndpointFromReq = getAssertionConsumerServiceFromRequest(authnRequest, binding, adaptor);
val acsEndpointFromMetadata = adaptor.getAssertionConsumerService(binding);
endpoint = determineEndpointForRequest(authnRequest, adaptor, binding,
acsEndpointFromReq, acsEndpointFromMetadata, authnContext.getRight());
}
if (endpoint == null) {
throw new SamlException("Endpoint for " + authnRequest.getSchemaType()
+ " is not available or does not define a binding for " + binding);
}
val missingLocation = StringUtils.isBlank(endpoint.getResponseLocation()) && StringUtils.isBlank(endpoint.getLocation());
if (StringUtils.isBlank(endpoint.getBinding()) || missingLocation) {
throw new SamlException("Endpoint for " + authnRequest.getSchemaType()
+ " does not define a binding or location for binding " + binding);
}
return endpoint;
}
private static AssertionConsumerService determineEndpointForRequest(final RequestAbstractType authnRequest,
final SamlRegisteredServiceMetadataAdaptor adaptor,
final String binding,
@Nullable final AssertionConsumerService acsFromRequest,
final AssertionConsumerService acsFromMetadata,
final MessageContext authenticationContext) {
LOGGER.trace("ACS from authentication request is [{}], ACS from metadata is [{}] with binding [{}]",
acsFromRequest, acsFromMetadata, binding);View on GitHub (pinned to e7288fc434)