{"record":{"id":"75cdebf1a616e49c","repo":"spring-projects/spring-security","slug":"invalid-request-75cdeb","errorCode":"invalid_request","errorMessage":"Logout request used invalid binding","messagePattern":"Logout request used invalid binding","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":193,"sourceCode":"\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\n\tprivate void sendLogoutResponse(HttpServletRequest request, HttpServletResponse response,\n\t\t\tSaml2LogoutResponse logoutResponse) throws IOException {\n\t\tif (logoutResponse.getBinding() == Saml2MessageBinding.REDIRECT) {\n\t\t\tdoRedirect(request, response, logoutResponse);\n\t\t}\n\t\telse {\n\t\t\tdoPost(request, response, logoutResponse);","sourceCodeStart":175,"sourceCodeEnd":211,"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#L175-L211","documentation":"Saml2LogoutRequestFilter.validateLogoutRequest resolves the binding of the incoming logout request (from the request parameters/transport) and checks it is among the registration's getSingleLogoutServiceBindings(). If the used binding (e.g. REDIRECT) is not in the configured set (e.g. only POST), it throws Saml2AuthenticationException with code invalid_request and message 'Logout request used invalid binding'.","triggerScenarios":"The IDP sends the LogoutRequest via a binding (Redirect or POST) not listed in the RelyingPartyRegistration's singleLogoutServiceBindings, or the SP config lists the wrong binding(s).","commonSituations":"IDP metadata advertises Redirect binding but the SP registration was hand-configured with POST only (or vice versa); IDP config changed binding after metadata import; reverse proxy stripping query parameters making Redirect-bound messages look malformed.","solutions":["Align singleLogoutServiceBinding(s) in the registration with what the IDP actually sends (check IDP's SingleLogoutService Binding attribute in metadata)","Re-import IDP metadata so bindings are picked up automatically","Update the IDP's SLO binding setting to match the SP configuration","Verify proxies preserve both query parameters (Redirect binding) and form bodies (POST binding)"],"exampleFix":"// before (only POST configured, IDP sends Redirect)\n.singleLogoutServiceLocation(\"https://idp/slo\")\n.singleLogoutServiceBinding(Saml2MessageBinding.POST)\n// after (accept the binding the IDP uses)\n.singleLogoutServiceLocation(\"https://idp/slo\")\n.singleLogoutServiceBindings(b -> b.addAll(List.of(Saml2MessageBinding.POST, Saml2MessageBinding.REDIRECT)))","handlingStrategy":"validation","validationCode":"Saml2MessageBinding inbound = Saml2MessageBindingUtils.resolveBinding(request);\nif (!registration.getSingleLogoutServiceBindings().contains(inbound)) {\n    log.warn(\"SLO binding \" + inbound + \" not enabled for registration\");\n}","typeGuard":null,"tryCatchPattern":"try { /* saml2Logout configuration */ } catch (Saml2AuthenticationException ex) {\n    if (\"invalid_request\".equals(ex.getSaml2Error().getErrorCode())) {\n        log.warn(\"SLO binding mismatch\", ex);\n        response.sendError(HttpServletResponse.SC_BAD_REQUEST);\n    } else { throw ex; }\n}","preventionTips":["Copy the binding(s) from IDP metadata exactly; enable both POST and REDIRECT if in doubt","Re-import metadata after the IDP changes its SLO binding","Test SLO through the full proxy chain"],"tags":["saml2","spring-security","logout","binding-mismatch"],"backgroundTag":"invalid-config-value","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"}