{"record":{"id":"486e4d3031c37f83","repo":"spring-projects/spring-security","slug":"invalid-destination","errorCode":"invalid_destination","errorMessage":"RelyingPartyRegistration has not been configured with a logout request endpoint","messagePattern":"RelyingPartyRegistration has not been configured with a logout request endpoint","errorType":"error_code","errorClass":"Saml2AuthenticationException","httpStatus":401,"severity":"error","filePath":"saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutRequestFilter.java","lineNumber":186,"sourceCode":"\t}\n\n\t/**\n\t * Sets the {@link SecurityContextHolderStrategy} to use. The default action is to use\n\t * the {@link SecurityContextHolderStrategy} stored in {@link SecurityContextHolder}.\n\t *\n\t * @since 5.8\n\t */\n\tpublic void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {\n\t\tAssert.notNull(securityContextHolderStrategy, \"securityContextHolderStrategy cannot be null\");\n\t\tthis.securityContextHolderStrategy = securityContextHolderStrategy;\n\t}\n\n\tprivate void validateLogoutRequest(HttpServletRequest request, Saml2LogoutRequestValidatorParameters parameters) {\n\t\tRelyingPartyRegistration registration = parameters.getRelyingPartyRegistration();\n\t\tif (registration.getSingleLogoutServiceLocation() == null) {\n\t\t\tthis.logger.trace(\n\t\t\t\t\t\"Did not process logout request since RelyingPartyRegistration has not been configured with a logout request endpoint\");\n\t\t\tthrow new Saml2AuthenticationException(new Saml2Error(Saml2ErrorCodes.INVALID_DESTINATION,\n\t\t\t\t\t\"RelyingPartyRegistration has not been configured with a logout request endpoint\"));\n\t\t}\n\n\t\tSaml2MessageBinding saml2MessageBinding = Saml2MessageBindingUtils.resolveBinding(request);\n\t\tif (!registration.getSingleLogoutServiceBindings().contains(saml2MessageBinding)) {\n\t\t\tthis.logger.trace(\"Did not process logout request since used incorrect binding\");\n\t\t\tthrow new Saml2AuthenticationException(\n\t\t\t\t\tnew Saml2Error(Saml2ErrorCodes.INVALID_REQUEST, \"Logout request used invalid binding\"));\n\t\t}\n\n\t\tSaml2LogoutValidatorResult result = this.logoutRequestValidator.validate(parameters);\n\t\tif (result.hasErrors()) {\n\t\t\tthis.logger.debug(LogMessage.format(\"Failed to validate LogoutRequest: %s\", result.getErrors()));\n\t\t\tthrow new Saml2AuthenticationException(\n\t\t\t\t\tnew Saml2Error(Saml2ErrorCodes.INVALID_REQUEST, \"Failed to validate the logout request\"));\n\t\t}\n\t}\n","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutRequestFilter.java#L168-L204","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\nRelyingPartyRegistration registration = RelyingPartyRegistration.withRegistrationId(\"idp\")\n    .entityId(\"https://idp/entity\").acsLocation(\"https://idp/acs\")\n    .singleLogoutServiceLocation(null) // or simply unset\n    .build();\n// after\nRelyingPartyRegistration registration = RelyingPartyRegistration.withRegistrationId(\"idp\")\n    .entityId(\"https://idp/entity\").acsLocation(\"https://idp/acs\")\n    .singleLogoutServiceLocation(\"https://idp/slo\")\n    .singleLogoutServiceBinding(Saml2MessageBinding.POST)\n    .build();","handlingStrategy":"validation","validationCode":"RelyingPartyRegistration reg = registrations.findByRegistrationId(id);\nif (reg.getSingleLogoutServiceLocation() == null) {\n    log.warn(\"Registration \" + id + \" has no SingleLogoutService location; SLO will fail\");\n}","typeGuard":null,"tryCatchPattern":"try { /* saml2Logout configuration */ } catch (Saml2AuthenticationException ex) {\n    if (Saml2ErrorCodes.INVALID_DESTINATION.equals(ex.getSaml2Error().getErrorCode())) {\n        log.warn(\"SLO not configured for registration\", ex);\n        response.sendError(HttpServletResponse.SC_BAD_REQUEST);\n    } else { throw ex; }\n}","preventionTips":["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"],"tags":["saml2","spring-security","logout","configuration","metadata"],"backgroundTag":"missing-required-config-field","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}