spring-projects/spring-security · error · Saml2AuthenticationException
invalid_destination
invalid_destination
Error message
RelyingPartyRegistration has not been configured with a logout request endpoint
What it means
Saml2LogoutRequestFilter.validateLogoutRequest checks that the RelyingPartyRegistration has a SingleLogoutServiceLocation configured. When it is null, the SP does not know where the IDP's logout endpoint is, so it throws Saml2AuthenticationException with code invalid_destination. The registration's metadata lacks the SingleLogoutService element.
Source
Thrown at saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutRequestFilter.java:186
}
/**
* Sets the {@link SecurityContextHolderStrategy} to use. The default action is to use
* the {@link SecurityContextHolderStrategy} stored in {@link SecurityContextHolder}.
*
* @since 5.8
*/
public void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {
Assert.notNull(securityContextHolderStrategy, "securityContextHolderStrategy cannot be null");
this.securityContextHolderStrategy = securityContextHolderStrategy;
}
private void validateLogoutRequest(HttpServletRequest request, Saml2LogoutRequestValidatorParameters parameters) {
RelyingPartyRegistration registration = parameters.getRelyingPartyRegistration();
if (registration.getSingleLogoutServiceLocation() == null) {
this.logger.trace(
"Did not process logout request since RelyingPartyRegistration has not been configured with a logout request endpoint");
throw new Saml2AuthenticationException(new Saml2Error(Saml2ErrorCodes.INVALID_DESTINATION,
"RelyingPartyRegistration has not been configured with a logout request endpoint"));
}
Saml2MessageBinding saml2MessageBinding = Saml2MessageBindingUtils.resolveBinding(request);
if (!registration.getSingleLogoutServiceBindings().contains(saml2MessageBinding)) {
this.logger.trace("Did not process logout request since used incorrect binding");
throw new Saml2AuthenticationException(
new Saml2Error(Saml2ErrorCodes.INVALID_REQUEST, "Logout request used invalid binding"));
}
Saml2LogoutValidatorResult result = this.logoutRequestValidator.validate(parameters);
if (result.hasErrors()) {
this.logger.debug(LogMessage.format("Failed to validate LogoutRequest: %s", result.getErrors()));
throw new Saml2AuthenticationException(
new Saml2Error(Saml2ErrorCodes.INVALID_REQUEST, "Failed to validate the logout request"));
}
}
View on GitHub (pinned to 96852e8860)
Solutions
- Configure the singleLogoutServiceLocation on the RelyingPartyRegistration, ideally by re-importing complete IDP metadata
- Re-export/re-download IDP metadata with SingleLogoutService enabled and refresh the metadata in the SP
- If building registrations in code, set .singleLogoutServiceLocation("https://idp/slo") and matching binding
- If the IDP truly lacks SLO, avoid routing SLO through Saml2LogoutRequestFilter for that registration
Example fix
// before
RelyingPartyRegistration registration = RelyingPartyRegistration.withRegistrationId("idp")
.entityId("https://idp/entity").acsLocation("https://idp/acs")
.singleLogoutServiceLocation(null) // or simply unset
.build();
// after
RelyingPartyRegistration registration = RelyingPartyRegistration.withRegistrationId("idp")
.entityId("https://idp/entity").acsLocation("https://idp/acs")
.singleLogoutServiceLocation("https://idp/slo")
.singleLogoutServiceBinding(Saml2MessageBinding.POST)
.build(); Defensive patterns
Strategy: validation
Validate before calling
RelyingPartyRegistration reg = registrations.findByRegistrationId(id);
if (reg.getSingleLogoutServiceLocation() == null) {
log.warn("Registration " + id + " has no SingleLogoutService location; SLO will fail");
} Try / catch
try { /* saml2Logout configuration */ } catch (Saml2AuthenticationException ex) {
if (Saml2ErrorCodes.INVALID_DESTINATION.equals(ex.getSaml2Error().getErrorCode())) {
log.warn("SLO not configured for registration", ex);
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
} else { throw ex; }
} Prevention
- Import IDP metadata so SingleLogoutService details come along automatically
- Assert at startup that every registration with SLO has a singleLogoutServiceLocation
- Refresh metadata after IDP-side SLO changes
When it happens
Trigger: A logout request arrives at /logout/saml2/sso while the matching RelyingPartyRegistration was built without singleLogoutServiceLocation (or the IDP metadata had no SingleLogoutService binding/Location).
Common situations: Hand-built RelyingPartyRegistration missing .singleLogoutServiceLocation(...); IDP metadata exported without SLO enabled; importing metadata from an IDP that does not advertise SLO; stale metadata cached before the IDP enabled SSO logout.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- relying_party_registration_not_found
- registration not found
- Metadata response is missing verification certificates, nece
- Metadata response is missing a SingleSignOnService, necessar
- Unsupported element type:
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/486e4d3031c37f83.
Report an issue: GitHub.