123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- = 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.`
|