Polish Documentation

Closes gh-14635
This commit is contained in:
Josh Cummings 2025-06-09 16:48:43 -06:00
parent 3ddf201d66
commit aa3135169d
6 changed files with 63 additions and 3 deletions

View File

@ -287,6 +287,7 @@ public class Saml2LogoutBeanDefinitionParserTests {
.andExpect(status().isBadRequest());
}
// gh-14635
@Test
public void saml2LogoutRequestWhenInvalidSamlRequestThen302Redirect() throws Exception {
this.spring.configLocations(this.xml("Default")).autowire();

View File

@ -6,6 +6,7 @@
* xref:migration/index.adoc[Migrating to 7]
** xref:migration/servlet/index.adoc[Servlet]
*** xref:migration/servlet/oauth2.adoc[OAuth 2.0]
*** xref:migration/servlet/saml2.adoc[SAML 2.0]
** xref:migration/reactive.adoc[Reactive]
* xref:getting-spring-security.adoc[Getting Spring Security]
* xref:attachment$api/java/index.html[Javadoc]

View File

@ -0,0 +1,56 @@
= SAML 2.0 Migrations
== Expect `<saml2:LogoutResponse>` When `<saml2:LogoutRequest>` Validation Fails
SAML identity providers expect service providers to return an error `<saml2:LogoutResponse>` if it fails to process the `<saml2:LogoutRequest>`.
Past versions of Spring Security returned a 401 in some cases, breaking the chain of logout requests and responses from each relying party.
In Spring Security 7, this behavior is repaired, and you need do nothing.
However, if this gives you trouble, you can revert back to the old behavior by publishing a `Saml2LogoutRequestResolver` that returns `null` when an error `<saml2:LogoutRequest>` is needed.
You can create a delegate like this one:
[tabs]
======
Java::
+
[source,java,role="primary"]
----
@Bean
Saml2LogoutResponseResolver logoutResponseResolver(RelyingPartyRegistrationRepository registrations) {
OpenSaml5LogoutResponseResolver delegate = new OpenSaml5LogoutResponseResolver(registrations);
return new Saml2LogoutResponseResolver() {
@Override
public void resolve(HttpServletRequest request, Authentication authentication) {
delegate.resolve(request, authentication);
}
@Override
public void resolve(HttpServletRequest request, Authentication authentication, Saml2AuthenticationException error) {
return null;
}
};
}
----
Kotlin::
+
[source,kotlin,role="secondary"]
----
@Bean
fun logoutResponseResolver(registrations: RelyingPartyRegistrationRepository?): Saml2LogoutResponseResolver {
val delegate = OpenSaml5LogoutResponseResolver(registrations)
return object : Saml2LogoutResponseResolver() {
override fun resolve(request: HttpServletRequest?, authentication: Authentication?) {
delegate.resolve(request, authentication)
}
override fun resolve(request: HttpServletRequest?, authentication: Authentication?, error: Saml2AuthenticationException?) {
return null
}
}
}
----
======

View File

@ -51,7 +51,9 @@ public interface Saml2LogoutResponseResolver {
* @param authentication the current user
* @param authenticationException the thrown exception when the logout request was
* processed
* @return a signed and serialized SAML 2.0 Logout Response
* @return a signed and serialized SAML 2.0 Logout Response, or {@code null} if it
* cannot generate a SAML 2.0 Error Logout Response
* @since 7.0
*/
default Saml2LogoutResponse resolve(HttpServletRequest request, Authentication authentication,
Saml2AuthenticationException authenticationException) {

View File

@ -65,7 +65,7 @@ public class OpenSaml4LogoutResponseResolverTests {
logoutResponseResolver.setParametersConsumer(parametersConsumer);
MockHttpServletRequest request = new MockHttpServletRequest();
RelyingPartyRegistration registration = TestRelyingPartyRegistrations.relyingPartyRegistration()
.assertingPartyMetadata(
.assertingPartyDetails(
(party) -> party.singleLogoutServiceResponseLocation("https://ap.example.com/logout"))
.build();
Authentication authentication = new TestingAuthenticationToken("user", "password");

View File

@ -99,7 +99,7 @@ public class Saml2LogoutRequestFilterTests {
@Test
public void doFilterWhenSamlRequestThenPosts() throws Exception {
RelyingPartyRegistration registration = TestRelyingPartyRegistrations.full()
.assertingPartyMetadata((party) -> party.singleLogoutServiceBinding(Saml2MessageBinding.POST))
.assertingPartyDetails((party) -> party.singleLogoutServiceBinding(Saml2MessageBinding.POST))
.build();
Authentication authentication = new TestingAuthenticationToken("user", "password");
given(this.securityContextHolderStrategy.getContext()).willReturn(new SecurityContextImpl(authentication));