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

  1. Configure the singleLogoutServiceLocation on the RelyingPartyRegistration, ideally by re-importing complete IDP metadata
  2. Re-export/re-download IDP metadata with SingleLogoutService enabled and refresh the metadata in the SP
  3. If building registrations in code, set .singleLogoutServiceLocation("https://idp/slo") and matching binding
  4. 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

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


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/486e4d3031c37f83. Report an issue: GitHub.