After upgrading spring-security-saml2-service-provider from 7.0.3 to 7.1.1, SAML HTTP-POST forms no longer preserve query parameters in the destination URL.
Both Saml2WebSsoAuthenticationRequestFilter and Saml2LogoutRequestFilter now use FormPostRedirectStrategy, which moves all destination query parameters into hidden form fields and removes the query string from the form action.
This changes the request sent to IdPs whose endpoints rely on query parameters for routing or binding selection. It also causes the actual request URL to differ from the Destination attribute in the signed SAML message.
We encountered this with RM Unify during IdP-initiated logout. Its logout response endpoint includes ?binding=post. After the upgrade, this parameter is submitted in the POST body instead, and RM Unify returns HTTP 500 despite the SAML LogoutResponse containing a successful status.
The same code path affects POST-binding authentication requests, although our observed failure was during logout.
Related refactoring: #16673
To Reproduce
- Configure an IdP with an HTTP-POST
SingleLogoutService endpoint containing a query parameter, for example:
<md:SingleLogoutService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="https://idp.example/slo?binding=post"/>
- Send a valid, signed IdP-initiated
LogoutRequest to the service provider.
- Inspect the generated HTML form for the
LogoutResponse.
In 7.1.1, the form is equivalent to:
<form method="post" action="https://idp.example/slo">
<input type="hidden" name="binding" value="post"/>
<input type="hidden" name="SAMLResponse" value="..."/>
<input type="hidden" name="RelayState" value="..."/>
</form>
The same behaviour can be observed during login when the selected HTTP-POST SingleSignOnService location contains query parameters.
Expected behavior
Preserve the destination URL, including its query string, in the form action. Only the SAML message and RelayState should be added as form fields:
<form method="post" action="https://idp.example/slo?binding=post">
<input type="hidden" name="SAMLResponse" value="..."/>
<input type="hidden" name="RelayState" value="..."/>
</form>
This was the behaviour in 7.0.3.
Sample
I do not currently have a standalone reproducer repository. The endpoint configuration and generated forms above illustrate the regression.
After upgrading
spring-security-saml2-service-providerfrom 7.0.3 to 7.1.1, SAML HTTP-POST forms no longer preserve query parameters in the destination URL.Both
Saml2WebSsoAuthenticationRequestFilterandSaml2LogoutRequestFilternow useFormPostRedirectStrategy, which moves all destination query parameters into hidden form fields and removes the query string from the form action.This changes the request sent to IdPs whose endpoints rely on query parameters for routing or binding selection. It also causes the actual request URL to differ from the
Destinationattribute in the signed SAML message.We encountered this with RM Unify during IdP-initiated logout. Its logout response endpoint includes
?binding=post. After the upgrade, this parameter is submitted in the POST body instead, and RM Unify returns HTTP 500 despite the SAMLLogoutResponsecontaining a successful status.The same code path affects POST-binding authentication requests, although our observed failure was during logout.
Related refactoring: #16673
To Reproduce
SingleLogoutServiceendpoint containing a query parameter, for example:LogoutRequestto the service provider.LogoutResponse.In 7.1.1, the form is equivalent to:
The same behaviour can be observed during login when the selected HTTP-POST
SingleSignOnServicelocation contains query parameters.Expected behavior
Preserve the destination URL, including its query string, in the form action. Only the SAML message and RelayState should be added as form fields:
This was the behaviour in 7.0.3.
Sample
I do not currently have a standalone reproducer repository. The endpoint configuration and generated forms above illustrate the regression.