mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-10-23 02:38:48 +00:00
148 lines
5.4 KiB
Plaintext
148 lines
5.4 KiB
Plaintext
= 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
|
|
}
|
|
}
|
|
}
|
|
----
|
|
======
|
|
|
|
== Favor `Saml2ResponseAuthenticationAccessor` over `Saml2AuthenticatedPrincipal`
|
|
|
|
Spring Security 7 separates `<saml2:Assertion>` details from the principal.
|
|
This allows Spring Security to retrieve needed assertion details to perform Single Logout.
|
|
|
|
This deprecates `Saml2AuthenticatedPrincipal`.
|
|
You no longer need to implement it to use `Saml2Authentication`.
|
|
|
|
Instead, the credential implements `Saml2ResponseAssertionAccessor`, which Spring Security 7 favors when determining the appropriate action based on the authentication.
|
|
|
|
This change is made automatically for you when using the defaults.
|
|
|
|
If this causes you trouble when upgrading, you can publish a custom `ResponseAuhenticationConverter` to return a `Saml2Authentication` instead of returning a `Saml2AssertionAuthentication` like so:
|
|
|
|
[tabs]
|
|
======
|
|
Java::
|
|
+
|
|
[source,java,role="primary"]
|
|
----
|
|
@Bean
|
|
OpenSaml5AuthenticationProvider authenticationProvider() {
|
|
OpenSaml5AuthenticationProvider authenticationProvider =
|
|
new OpenSaml5AuthenticationProvider();
|
|
ResponseAuthenticationConverter defaults = new ResponseAuthenticationConverter();
|
|
authenticationProvider.setResponseAuthenticationConverter(
|
|
defaults.andThen((authentication) -> new Saml2Authentication(
|
|
authentication.getPrincipal(),
|
|
authentication.getSaml2Response(),
|
|
authentication.getAuthorities())));
|
|
return authenticationProvider;
|
|
}
|
|
----
|
|
|
|
Kotlin::
|
|
+
|
|
[source,kotlin,role="secondary"]
|
|
----
|
|
@Bean
|
|
fun authenticationProvider(): OpenSaml5AuthenticationProvider {
|
|
val authenticationProvider = OpenSaml5AuthenticationProvider()
|
|
val defaults = ResponseAuthenticationConverter()
|
|
authenticationProvider.setResponseAuthenticationConverter(
|
|
defaults.andThen { authentication ->
|
|
Saml2Authentication(authentication.getPrincipal(),
|
|
authentication.getSaml2Response(),
|
|
authentication.getAuthorities())
|
|
})
|
|
return authenticationProvider
|
|
}
|
|
----
|
|
======
|
|
|
|
If you are constructing a `Saml2Authentication` instance yourself, consider changing to `Saml2AssertionAuthentication` to get the same benefit as the current default.
|
|
|
|
== Do Not Process `<saml2:Response>` GET Requests with `Saml2AuthenticationTokenConverter`
|
|
|
|
Spring Security does not support processing `<saml2:Response>` payloads over GET as this is not supported by the SAML 2.0 spec.
|
|
|
|
To better comply with this, `Saml2AuthenticationTokenConverter` and `OpenSaml5AuthenticationTokenConverter` will not process GET requests by default as of Spring Security 8.
|
|
To prepare for this, the property `shouldConvertGetRequests` is available.
|
|
To use it, publish your own converter like so:
|
|
|
|
[tabs]
|
|
======
|
|
Java::
|
|
+
|
|
[source,java,role="primary"]
|
|
----
|
|
@Bean
|
|
OpenSaml5AuthenticationTokenConverter authenticationConverter(RelyingPartyRegistrationRepository registrations) {
|
|
OpenSaml5AuthenticationTokenConverter authenticationConverter = new OpenSaml5AuthenticationTokenConverter(registrations);
|
|
authenticationConverter.setShouldConvertGetRequests(false);
|
|
return authenticationConverter;
|
|
}
|
|
----
|
|
|
|
Kotlin::
|
|
+
|
|
[source,kotlin,role="secondary"]
|
|
----
|
|
@Bean
|
|
fun authenticationConverter(val registrations: RelyingPartyRegistrationRepository): Saml2AuthenticationTokenConverter {
|
|
val authenticationConverter = Saml2AuthenticationTokenConverter(registrations)
|
|
authenticationConverter.setShouldConvertGetRequests(false)
|
|
return authenticationConverter
|
|
}
|
|
----
|
|
======
|
|
|
|
If you must continue using `Saml2AuthenticationTokenConverter` or `OpenSaml5AuthenticationTokenConverter` to process GET requests, you can call `setShouldConvertGetRequests` to `true.`
|