浏览代码

Revert "Add Single Logout Support"

This reverts commit e807fae8692cc36c928a40fd6c5fa3ecd0abe932.
Josh Cummings 4 年之前
父节点
当前提交
37b40476e7
共有 41 个文件被更改,包括 35 次插入4957 次删除
  1. 8 267
      docs/manual/src/docs/asciidoc/_includes/servlet/saml2/saml2-login.adoc
  2. 0 7
      saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/core/Saml2ErrorCodes.java
  3. 0 217
      saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/authentication/logout/Saml2LogoutRequest.java
  4. 0 184
      saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/authentication/logout/Saml2LogoutResponse.java
  5. 0 10
      saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/metadata/OpenSamlMetadataResolver.java
  6. 3 25
      saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/registration/OpenSamlAssertingPartyMetadataConverter.java
  7. 6 238
      saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistration.java
  8. 11 10
      saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/DefaultRelyingPartyRegistrationResolver.java
  9. 0 112
      saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/HttpSessionLogoutRequestRepository.java
  10. 0 198
      saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSamlLogoutRequestHandler.java
  11. 0 243
      saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSamlLogoutRequestResolver.java
  12. 0 217
      saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSamlLogoutResponseHandler.java
  13. 0 268
      saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSamlLogoutResponseResolver.java
  14. 0 173
      saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSamlSigningUtils.java
  15. 0 218
      saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSamlVerificationUtils.java
  16. 0 92
      saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutRequestFilter.java
  17. 0 68
      saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutRequestRepository.java
  18. 0 82
      saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutRequestResolver.java
  19. 0 159
      saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutRequestSuccessHandler.java
  20. 0 117
      saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutResponseFilter.java
  21. 0 90
      saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutResponseResolver.java
  22. 0 148
      saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutResponseSuccessHandler.java
  23. 0 35
      saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2RequestAttributeNames.java
  24. 0 79
      saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2Utils.java
  25. 2 44
      saml2/saml2-service-provider/core/src/test/java/org/springframework/security/saml2/provider/service/authentication/TestOpenSamlObjects.java
  26. 2 4
      saml2/saml2-service-provider/core/src/test/java/org/springframework/security/saml2/provider/service/metadata/OpenSamlMetadataResolverTests.java
  27. 3 9
      saml2/saml2-service-provider/core/src/test/java/org/springframework/security/saml2/provider/service/registration/TestRelyingPartyRegistrations.java
  28. 0 3
      saml2/saml2-service-provider/core/src/test/java/org/springframework/security/saml2/provider/service/web/DefaultRelyingPartyRegistrationResolverTests.java
  29. 0 242
      saml2/saml2-service-provider/core/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/HttpSessionLogoutRequestRepositoryTests.java
  30. 0 182
      saml2/saml2-service-provider/core/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSamlLogoutRequestHandlerTests.java
  31. 0 112
      saml2/saml2-service-provider/core/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSamlLogoutRequestResolverTests.java
  32. 0 189
      saml2/saml2-service-provider/core/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSamlLogoutResponseHandlerTests.java
  33. 0 119
      saml2/saml2-service-provider/core/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSamlLogoutResponseResolverTests.java
  34. 0 116
      saml2/saml2-service-provider/core/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutRequestFilterTests.java
  35. 0 111
      saml2/saml2-service-provider/core/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutRequestSuccessHandlerTests.java
  36. 0 122
      saml2/saml2-service-provider/core/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutResponseFilterTests.java
  37. 0 95
      saml2/saml2-service-provider/core/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutResponseSuccessHandlerTests.java
  38. 0 91
      saml2/saml2-service-provider/opensaml3/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSaml3LogoutRequestResolver.java
  39. 0 89
      saml2/saml2-service-provider/opensaml3/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSaml3LogoutResponseResolver.java
  40. 0 87
      saml2/saml2-service-provider/opensaml4/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSaml4LogoutRequestResolver.java
  41. 0 85
      saml2/saml2-service-provider/opensaml4/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSaml4LogoutResponseResolver.java

+ 8 - 267
docs/manual/src/docs/asciidoc/_includes/servlet/saml2/saml2-login.adoc

@@ -1053,279 +1053,20 @@ filter.setRequestMatcher(new AntPathRequestMatcher("/saml2/metadata", "GET"));
 [[servlet-saml2login-logout]]
 [[servlet-saml2login-logout]]
 === Performing Single Logout
 === Performing Single Logout
 
 
-Spring Security ships with support for RP- and AP-initiated SAML 2.0 Single Logout.
+Spring Security does not yet support single logout.
 
 
-Briefly, there are two use cases Spring Security supports:
-
-* **RP-Initiated** - Your application has an endpoint that, when POSTed to, will logout the user and send a `saml2:LogoutRequest` to the asserting party.
-Thereafter, the asserting party will send back a `saml2:LogoutResponse` and allow your application to respond
-* **AP-Initiated** - Your application has an endpoint that will receive a `saml2:LogoutRequest` from the asserting party.
-Your application will complete its logout at that point and then send a `saml2:LogoutResponse` to the asserting party.
-
-[NOTE]
-In the **AP-Initiated** scenario, any local redirection that your application would do post-logout is rendered moot.
-Once your application sends a `saml2:LogoutResponse`, it no longer has control of the browser.
-
-=== Minimal Configuration for Single Logout
-
-To use Spring Security's SAML 2.0 Single Logout feature, you will need the following things:
-
-* First, the asserting party must support SAML 2.0 Single Logout
-* Second, the asserting party should be configured to sign and POST `saml2:LogoutRequest` s and `saml2:LogoutResponse` s your application's `/logout/saml2/slo` endpoint
-* Third, your application must have a PKCS#8 private key and X.509 certificate for signing `saml2:LogoutRequest` s and `saml2:LogoutResponse` s
-
-==== RP-Initiated Single Logout
-
-Given those, then for RP-initiated Single Logout, you can begin from the initial minimal example and add the following configuration:
-
-[source,java]
-----
-@Value("${private.key}") RSAPrivateKey key;
-@Value("${public.certificate}") X509Certificate certificate;
-
-@Bean
-RelyingPartyRegistrationRepository registrations() {
-    RelyingPartyRegistration relyingPartyRegistration = RelyingPartyRegistrations
-            .fromMetadataLocation("https://ap.example.org/metadata")
-            .registrationId("id")
-            .singleLogoutServiceLocation("{baseUrl}/logout/saml2/slo")
-            .signingX509Credentials((signing) -> signing.add(Saml2X509Credential.signing(key, certificate))) <1>
-            .build();
-    return new InMemoryRelyingPartyRegistrationRepository(relyingPartyRegistration);
-}
-
-@Bean
-SecurityFilterChain web(HttpSecurity http, RelyingPartyRegistrationRepository registrations) throws Exception {
-	RelyingPartyRegistrationResolver registrationResolver = new DefaultRelyingPartyRegistrationResolver(registrations);
-    LogoutHandler logoutResponseHandler = logoutResponseHandler(registrationResolver);
-    LogoutSuccessHandler logoutRequestSuccessHandler = logoutRequestSuccessHandler(registrationResolver);
-
-    http
-        .authorizeRequests((authorize) -> authorize
-            .anyRequest().authenticated()
-        )
-        .saml2Login(withDefaults())
-        .logout((logout) -> logout
-                .logoutUrl("/saml2/logout")
-                .logoutSuccessHandler(successHandler))
-        .addFilterBefore(new Saml2LogoutResponseFilter(logoutHandler), CsrfFilter.class);
-
-    return http.build();
-}
-
-private LogoutSuccessHandler logoutRequestSuccessHandler(RelyingPartyRegistrationResolver registrationResolver) { <2>
-    OpenSaml4LogoutRequestResolver logoutRequestResolver = new OpenSaml4LogoutRequestResolver(registrationResolver);
-    return new Saml2LogoutRequestSuccessHandler(logoutRequestResolver);
-}
-
-private LogoutHandler logoutHandler(RelyingPartyRegistrationResolver registrationResolver) { <3>
-    return new OpenSamlLogoutResponseHandler(relyingPartyRegistrationResolver);
-}
-----
-<1> - First, add your signing key to the `RelyingPartyRegistration` instance or to <<servlet-saml2login-rpr-duplicated,multiple instances>>
-<2> - Second, supply a `LogoutSuccessHandler` for initiating Single Logout, sending a `saml2:LogoutRequest` to the asserting party
-<3> - Third, supply the `LogoutHandler` s needed to handle the `saml2:LogoutResponse` s sent from the asserting party.
-
-==== Runtime Expectations for RP-Initiated
-
-Given the above configuration any logged in user can send a `POST /logout` to your application to perform RP-initiated SLO.
-Your application will then do the following:
-
-1. Logout the user and invalidate the session
-2. Use a `Saml2LogoutRequestResolver` to create, sign, and serialize a `<saml2:LogoutRequest>` based on the <<servlet-saml2login-relyingpartyregistration,`RelyingPartyRegistration`>> associated with the currently logged-in user.
-3. Send a redirect or post to the asserting party based on the <<servlet-saml2login-relyingpartyregistration,`RelyingPartyRegistration`>>
-4. Deserialize, verify, and process the `<saml2:LogoutResponse>` sent by the asserting party
-5. Redirect to any configured successful logout endpoint
-
-[TIP]
-If your asserting party does not send `<saml2:LogoutResponse>` s when logout is complete, the asserting party can still send a `POST /saml2/logout` and then there is no need to configure the `Saml2LogoutResponseHandler`.
-
-==== AP-Initiated Single Logout
-
-Instead of RP-initiated Single Logout, you can again begin from the initial minimal example and add the following configuration to achieve AP-initiated Single Logout:
-
-[source,java]
-----
-@Value("${private.key}") RSAPrivateKey key;
-@Value("${public.certificate}") X509Certificate certificate;
-
-@Bean
-RelyingPartyRegistrationRepository registrations() {
-    RelyingPartyRegistration relyingPartyRegistration = RelyingPartyRegistrations
-            .fromMetadataLocation("https://ap.example.org/metadata")
-            .registrationId("id")
-            .signingX509Credentials((signing) -> signing.add(Saml2X509Credential.signing(key, certificate))) <1>
-            .build();
-    return new InMemoryRelyingPartyRegistrationRepository(relyingPartyRegistration);
-}
-
-@Bean
-SecurityFilterChain web(HttpSecurity http, RelyingPartyRegistrationRepository registrations) throws Exception {
-	RelyingPartyRegistrationResolver registrationResolver = new DefaultRelyingPartyRegistrationResolver(registrations);
-    LogoutHandler logoutRequestHandler = logoutRequestHandler(registrationResolver);
-    LogoutSuccessHandler logoutResponseSuccessHandler = logoutResponseSuccessHandler(registrationResolver);
-
-    http
-        .authorizeRequests((authorize) -> authorize
-            .anyRequest().authenticated()
-        )
-        .saml2Login(withDefaults())
-        .addFilterBefore(new Saml2LogoutRequestFilter(logoutResponseSuccessHandler, logoutRequestHandler), CsrfFilter.class);
-
-    return http.build();
-}
-
-private LogoutHandler logoutHandler(RelyingPartyRegistrationResolver registrationResolver) { <2>
-    return new CompositeLogoutHandler(
-    		new OpenSamlLogoutRequestHandler(relyingPartyRegistrationResolver),
-            new SecurityContextLogoutHandler(),
-            new LogoutSuccessEventPublishingLogoutHandler());
-}
-
-private LogoutSuccessHandler logoutSuccessHandler(RelyingPartyRegistrationResolver registrationResolver) { <3>
-    OpenSaml4LogoutResponseResolver logoutResponseResolver = new OpenSaml4LogoutResponseResolver(registrationResolver);
-    return new Saml2LogoutResponseSuccessHandler(logoutResponseResolver);
-}
-----
-<1> - First, add your signing key to the `RelyingPartyRegistration` instance or to <<servlet-saml2login-rpr-duplicated,multiple instances>>
-<2> - Second, supply the `LogoutHandler` needed to handle the `saml2:LogoutRequest` s sent from the asserting party.
-<3> - Third, supply a `LogoutSuccessHandler` for completing Single Logout, sending a `saml2:LogoutResponse` to the asserting party
-
-==== Runtime Expectations for AP-Initiated
-
-Given the above configuration, an asserting party can send a `POST /logout/saml2` to your application that includes a `<saml2:LogoutRequest>`
-Also, your application can participate in an AP-initated logout when the asserting party sends a `<saml2:LogoutRequest>` to `/logout/saml2/slo`:
-
-1. Use a `Saml2LogoutRequestHandler` to deserialize, verify, and process the `<saml2:LogoutRequest>` sent by the asserting party
-2. Logout the user and invalidate the session
-3. Create, sign, and serialize a `<saml2:LogoutResponse>` based on the <<servlet-saml2login-relyingpartyregistration,`RelyingPartyRegistration`>> associated with the just logged-out user
-4. Send a redirect or post to the asserting party based on the <<servlet-saml2login-relyingpartyregistration,`RelyingPartyRegistration`>>
-
-[TIP]
-If your asserting party does not expect you do send a `<saml2:LogoutResponse>` s when logout is complete, you may not need to configure a `LogoutSuccessHandler`
-
-[NOTE]
-In the event that you need to support both logout flows, you can combine the above to configurations.
-
-=== Configuring Logout Endpoints
-
-There are three default endpoints that Spring Security's SAML 2.0 Single Logout support exposes:
-* `/logout` - the endpoint for initiating single logout with an asserting party
-* `/logout/saml2/slo` - the endpoint for receiving logout requests or responses from an asserting party
-
-Because the user is already logged in, the `registrationId` is already known.
-For this reason, `+{registrationId}+` is not part of these URLs by default.
-
-These URLs are customizable in the DSL.
-
-For example, if you are migrating your existing relying party over to Spring Security, your asserting party may already be pointing to `GET /SLOService.saml2`.
-To reduce changes in configuration for the asserting party, you can configure the filter in the DSL like so:
+Generally speaking, though, you can achieve this by creating and registering a custom `LogoutSuccessHandler` and `RequestMatcher`:
 
 
 [source,java]
 [source,java]
 ----
 ----
-Saml2LogoutResponseFilter filter = new Saml2LogoutResponseFilter(logoutHandler);
-filter.setLogoutRequestMatcher(new AntPathRequestMatcher("/SLOService.saml2", "GET"));
 http
 http
     // ...
     // ...
-    .addFilterBefore(filter, CsrfFilter.class);
-----
-
-=== Customizing `<saml2:LogoutRequest>` Resolution
-
-It's common to need to set other values in the `<saml2:LogoutRequest>` than the defaults that Spring Security provides.
-
-By default, Spring Security will issue a `<saml2:LogoutRequest>` and supply:
-
-* The `Destination` attribute - from `RelyingPartyRegistration#getAssertingPartyDetails#getSingleLogoutServiceLocation`
-* The `ID` attribute - a GUID
-* The `<Issuer>` element - from `RelyingPartyRegistration#getEntityId`
-* The `<NameID>` element - from `Authentication#getName`
-
-To add other values, you can use delegation, like so:
-
-[source,java]
-----
-OpenSamlLogoutRequestResolver delegate = new OpenSamlLogoutRequestResolver(registrationResolver);
-return (request, response, authentication) -> {
-	OpenSamlLogoutRequestBuilder builder = delegate.resolveLogoutRequest(request, response, authentication); <1>
-	builder.name(((Saml2AuthenticatedPrincipal) authentication.getPrincipal()).getFirstAttribute("CustomAttribute")); <2>
-	builder.logoutRequest((logoutRequest) -> logoutRequest.setIssueInstant(DateTime.now()));
-	return builder.logoutRequest(); <3>
-};
-----
-<1> - Spring Security applies default values to a `<saml2:LogoutRequest>`
-<2> - Your application specifies customizations
-<3> - You complete the invocation by calling `request()`
-
-[NOTE]
-Support for OpenSAML 4 is coming.
-In anticipation of that, `OpenSamlLogoutRequestResolver` does not add an `IssueInstant`.
-Once OpenSAML 4 support is added, the default will be able to appropriate negotiate that datatype change, meaning you will no longer have to set it.
-
-=== Customizing `<saml2:LogoutResponse>` Resolution
-
-It's common to need to set other values in the `<saml2:LogoutResponse>` than the defaults that Spring Security provides.
-
-By default, Spring Security will issue a `<saml2:LogoutResponse>` and supply:
-
-* The `Destination` attribute - from `RelyingPartyRegistration#getAssertingPartyDetails#getSingleLogoutServiceResponseLocation`
-* The `ID` attribute - a GUID
-* The `<Issuer>` element - from `RelyingPartyRegistration#getEntityId`
-* The `<Status>` element - `SUCCESS`
-
-To add other values, you can use delegation, like so:
-
-[source,java]
-----
-OpenSamlLogoutResponseResolver delegate = new OpenSamlLogoutResponseResolver(registrationResolver);
-return (request, response, authentication) -> {
-	OpenSamlLogoutResponseBuilder builder = delegate.resolveLogoutResponse(request, response, authentication); <1>
-    if (checkOtherPrevailingConditions()) {
-        builder.status(StatusCode.PARTIAL_LOGOUT); <2>
-    }
-	builder.logoutResponse((logoutResponse) -> logoutResponse.setIssueInstant(DateTime.now()));
-	return builder.logoutResponse(); <3>
-};
-----
-<1> - Spring Security applies default values to a `<saml2:LogoutResponse>`
-<2> - Your application specifies customizations
-<3> - You complete the invocation by calling `response()`
-
-[NOTE]
-Support for OpenSAML 4 is coming.
-In anticipation of that, `OpenSamlLogoutResponseResolver` does not add an `IssueInstant`.
-Once OpenSAML 4 support is added, the default will be able to appropriate negotiate that datatype change, meaning you will no longer have to set it.
-
-=== Customizing `<saml2:LogoutRequest>` Validation
-
-To customize validation, you can implement your own `LogoutHandler`.
-At this point, the validation is minimal, so you may be able to first delegate to the default `LogoutHandler` like so:
-
-[source,java]
-----
-LogoutHandler logoutHandler(RelyingPartyRegistrationResolver registrationResolver) {
-	OpenSamlLogoutRequestHandler delegate = new OpenSamlLogoutRequestHandler(registrationResolver);
-	return (request, response, authentication) -> {
-		delegate.logout(request, response, authentication); // verify signature, issuer, destination, and principal name
-		LogoutRequest logoutRequest = // ... parse using OpenSAML
-        // perform custom validation
-	}
-}
+    .logout(logout -> logout
+        .logoutSuccessHandler(myCustomSuccessHandler())
+        .logoutRequestMatcher(myRequestMatcher())
+    )
 ----
 ----
 
 
-=== Customizing `<saml2:LogoutResponse>` Validation
+The success handler will send logout requests to the asserting party.
 
 
-To customize validation, you can implement your own `LogoutHandler`.
-At this point, the validation is minimal, so you may be able to first delegate to the default `LogoutHandler` like so:
-
-[source,java]
-----
-LogoutHandler logoutHandler(RelyingPartyRegistrationResolver registrationResolver) {
-	OpenSamlLogoutResponseHandler delegate = new OpenSamlLogoutResponseHandler(registrationResolver);
-	return (request, response, authentication) -> {
-		delegate.logout(request, response, authentication); // verify signature, issuer, destination, and status
-		LogoutResponse logoutResponse = // ... parse using OpenSAML
-        // perform custom validation
-	}
-}
-----
+The request matcher will detect logout requests from the asserting party.

+ 0 - 7
saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/core/Saml2ErrorCodes.java

@@ -37,13 +37,6 @@ public interface Saml2ErrorCodes {
 	 */
 	 */
 	String MALFORMED_RESPONSE_DATA = "malformed_response_data";
 	String MALFORMED_RESPONSE_DATA = "malformed_response_data";
 
 
-	/**
-	 * Request is invalid in a general way.
-	 *
-	 * @since 5.5
-	 */
-	String INVALID_REQUEST = "invalid_request";
-
 	/**
 	/**
 	 * Response is invalid in a general way.
 	 * Response is invalid in a general way.
 	 *
 	 *

+ 0 - 217
saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/authentication/logout/Saml2LogoutRequest.java

@@ -1,217 +0,0 @@
-/*
- * Copyright 2002-2020 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.provider.service.authentication.logout;
-
-import java.io.Serializable;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.function.Consumer;
-
-import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
-import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
-import org.springframework.security.saml2.provider.service.web.authentication.logout.Saml2LogoutRequestResolver;
-
-/**
- * A class that represents a signed and serialized SAML 2.0 Logout Request
- *
- * @author Josh Cummings
- * @since 5.5
- */
-public final class Saml2LogoutRequest implements Serializable {
-
-	private final String location;
-
-	private final Saml2MessageBinding binding;
-
-	private final Map<String, String> parameters;
-
-	private final String id;
-
-	private final String relyingPartyRegistrationId;
-
-	private Saml2LogoutRequest(String location, Saml2MessageBinding binding, Map<String, String> parameters, String id,
-			String relyingPartyRegistrationId) {
-		this.location = location;
-		this.binding = binding;
-		this.parameters = Collections.unmodifiableMap(new HashMap<>(parameters));
-		this.id = id;
-		this.relyingPartyRegistrationId = relyingPartyRegistrationId;
-	}
-
-	/**
-	 * The unique identifier for this Logout Request
-	 * @return the Logout Request identifier
-	 */
-	public String getId() {
-		return this.id;
-	}
-
-	/**
-	 * Get the location of the asserting party's <a href=
-	 * "https://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf#page=7">SingleLogoutService</a>
-	 * @return the SingleLogoutService location
-	 */
-	public String getLocation() {
-		return this.location;
-	}
-
-	/**
-	 * Get the binding for the asserting party's <a href=
-	 * "https://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf#page=7">SingleLogoutService</a>
-	 * @return the SingleLogoutService binding
-	 */
-	public Saml2MessageBinding getBinding() {
-		return this.binding;
-	}
-
-	/**
-	 * Get the signed and serialized &lt;saml2:LogoutRequest&gt; payload
-	 * @return the signed and serialized &lt;saml2:LogoutRequest&gt; payload
-	 */
-	public String getSamlRequest() {
-		return this.parameters.get("SAMLRequest");
-	}
-
-	/**
-	 * The relay state associated with this Logout Request
-	 * @return the relay state
-	 */
-	public String getRelayState() {
-		return this.parameters.get("RelayState");
-	}
-
-	/**
-	 * Get the {@code name} parameter
-	 *
-	 * Useful when specifying additional query parameters for the Logout Request
-	 * @param name the parameter's name
-	 * @return the parameter's value
-	 */
-	public String getParameter(String name) {
-		return this.parameters.get(name);
-	}
-
-	/**
-	 * Get all parameters
-	 *
-	 * Useful when specifying additional query parameters for the Logout Request
-	 * @return
-	 */
-	public Map<String, String> getParameters() {
-		return this.parameters;
-	}
-
-	/**
-	 * The identifier for the {@link RelyingPartyRegistration} associated with this Logout
-	 * Request
-	 * @return the {@link RelyingPartyRegistration} id
-	 */
-	public String getRelyingPartyRegistrationId() {
-		return this.relyingPartyRegistrationId;
-	}
-
-	/**
-	 * Create a {@link Builder} instance from this {@link RelyingPartyRegistration}
-	 *
-	 * Specifically, this will pull the <a href=
-	 * "https://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf#page=7">SingleLogoutService</a>
-	 * location and binding from the {@link RelyingPartyRegistration}
-	 * @param registration the {@link RelyingPartyRegistration} to use
-	 * @return the {@link Builder} for further configurations
-	 */
-	public static Builder withRelyingPartyRegistration(RelyingPartyRegistration registration) {
-		return new Builder(registration);
-	}
-
-	public static final class Builder {
-
-		private final RelyingPartyRegistration registration;
-
-		private Map<String, String> parameters = new HashMap<>();
-
-		private String id;
-
-		private Builder(RelyingPartyRegistration registration) {
-			this.registration = registration;
-		}
-
-		/**
-		 * Use this signed and serialized and Base64-encoded &lt;saml2:LogoutRequest&gt;
-		 *
-		 * Note that if using the Redirect binding, the value should be
-		 * {@link java.util.zip.DeflaterOutputStream deflated} and then Base64-encoded.
-		 *
-		 * It should not be URL-encoded as this will be done when the request is sent
-		 * @param samlRequest the &lt;saml2:LogoutRequest&gt; to use
-		 * @return the {@link Builder} for further configurations
-		 * @see Saml2LogoutRequestResolver
-		 */
-		public Builder samlRequest(String samlRequest) {
-			this.parameters.put("SAMLRequest", samlRequest);
-			return this;
-		}
-
-		/**
-		 * Use this value for the relay state when sending the Logout Request to the
-		 * asserting party
-		 *
-		 * It should not be URL-encoded as this will be done when the request is sent
-		 * @param relayState the relay state
-		 * @return the {@link Builder} for further configurations
-		 */
-		public Builder relayState(String relayState) {
-			this.parameters.put("RelayState", relayState);
-			return this;
-		}
-
-		/**
-		 * This is the unique id used in the {@link #samlRequest}
-		 * @param id the Logout Request id
-		 * @return the {@link Builder} for further configurations
-		 */
-		public Builder id(String id) {
-			this.id = id;
-			return this;
-		}
-
-		/**
-		 * Use this {@link Consumer} to modify the set of query parameters
-		 *
-		 * No parameter should be URL-encoded as this will be done when the request is
-		 * sent
-		 * @param parametersConsumer the {@link Consumer}
-		 * @return the {@link Builder} for further configurations
-		 */
-		public Builder parameters(Consumer<Map<String, String>> parametersConsumer) {
-			parametersConsumer.accept(this.parameters);
-			return this;
-		}
-
-		/**
-		 * Build the {@link Saml2LogoutRequest}
-		 * @return a constructed {@link Saml2LogoutRequest}
-		 */
-		public Saml2LogoutRequest build() {
-			return new Saml2LogoutRequest(this.registration.getAssertingPartyDetails().getSingleLogoutServiceLocation(),
-					this.registration.getAssertingPartyDetails().getSingleLogoutServiceBinding(), this.parameters,
-					this.id, this.registration.getRegistrationId());
-		}
-
-	}
-
-}

+ 0 - 184
saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/authentication/logout/Saml2LogoutResponse.java

@@ -1,184 +0,0 @@
-/*
- * Copyright 2002-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.provider.service.authentication.logout;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.function.Consumer;
-
-import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
-import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
-import org.springframework.security.saml2.provider.service.web.authentication.logout.Saml2LogoutResponseResolver;
-
-/**
- * A class that represents a signed and serialized SAML 2.0 Logout Response
- *
- * @author Josh Cummings
- * @since 5.5
- */
-public final class Saml2LogoutResponse {
-
-	private final String location;
-
-	private final Saml2MessageBinding binding;
-
-	private final Map<String, String> parameters;
-
-	private Saml2LogoutResponse(String location, Saml2MessageBinding binding, Map<String, String> parameters) {
-		this.location = location;
-		this.binding = binding;
-		this.parameters = Collections.unmodifiableMap(new HashMap<>(parameters));
-	}
-
-	/**
-	 * Get the response location of the asserting party's <a href=
-	 * "https://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf#page=7">SingleLogoutService</a>
-	 * @return the SingleLogoutService response location
-	 */
-	public String getResponseLocation() {
-		return this.location;
-	}
-
-	/**
-	 * Get the binding for the asserting party's <a href=
-	 * "https://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf#page=7">SingleLogoutService</a>
-	 * @return the SingleLogoutService binding
-	 */
-	public Saml2MessageBinding getBinding() {
-		return this.binding;
-	}
-
-	/**
-	 * Get the signed and serialized &lt;saml2:LogoutResponse&gt; payload
-	 * @return the signed and serialized &lt;saml2:LogoutResponse&gt; payload
-	 */
-	public String getSamlResponse() {
-		return this.parameters.get("SAMLResponse");
-	}
-
-	/**
-	 * The relay state associated with this Logout Request
-	 * @return the relay state
-	 */
-	public String getRelayState() {
-		return this.parameters.get("RelayState");
-	}
-
-	/**
-	 * Get the {@code name} parameter, a short-hand for <code>
-	 *	getParameters().get(name)
-	 * </code>
-	 *
-	 * Useful when specifying additional query parameters for the Logout Response
-	 * @param name the parameter's name
-	 * @return the parameter's value
-	 */
-	public String getParameter(String name) {
-		return this.parameters.get(name);
-	}
-
-	/**
-	 * Get all parameters
-	 *
-	 * Useful when specifying additional query parameters for the Logout Response
-	 * @return
-	 */
-	public Map<String, String> getParameters() {
-		return this.parameters;
-	}
-
-	/**
-	 * Create a {@link Saml2LogoutResponse.Builder} instance from this
-	 * {@link RelyingPartyRegistration}
-	 *
-	 * Specifically, this will pull the <a href=
-	 * "https://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf#page=7">SingleLogoutService</a>
-	 * response location and binding from the {@link RelyingPartyRegistration}
-	 * @param registration the {@link RelyingPartyRegistration} to use
-	 * @return the {@link Saml2LogoutResponse.Builder} for further configurations
-	 */
-	public static Builder withRelyingPartyRegistration(RelyingPartyRegistration registration) {
-		return new Builder(registration);
-	}
-
-	public static final class Builder {
-
-		private String location;
-
-		private Saml2MessageBinding binding;
-
-		private Map<String, String> parameters = new HashMap<>();
-
-		private Builder(RelyingPartyRegistration registration) {
-			this.location = registration.getAssertingPartyDetails().getSingleLogoutServiceResponseLocation();
-			this.binding = registration.getAssertingPartyDetails().getSingleLogoutServiceBinding();
-		}
-
-		/**
-		 * Use this signed and serialized and Base64-encoded &lt;saml2:LogoutResponse&gt;
-		 *
-		 * Note that if using the Redirect binding, the value should be
-		 * {@link java.util.zip.DeflaterOutputStream deflated} and then Base64-encoded.
-		 *
-		 * It should not be URL-encoded as this will be done when the response is sent
-		 * @param samlResponse the &lt;saml2:LogoutResponse&gt; to use
-		 * @return the {@link Builder} for further configurations
-		 * @see Saml2LogoutResponseResolver
-		 */
-		public Builder samlResponse(String samlResponse) {
-			this.parameters.put("SAMLResponse", samlResponse);
-			return this;
-		}
-
-		/**
-		 * Use this value for the relay state when sending the Logout Request to the
-		 * asserting party
-		 *
-		 * It should not be URL-encoded as this will be done when the response is sent
-		 * @param relayState the relay state
-		 * @return the {@link Builder} for further configurations
-		 */
-		public Builder relayState(String relayState) {
-			this.parameters.put("RelayState", relayState);
-			return this;
-		}
-
-		/**
-		 * Use this {@link Consumer} to modify the set of query parameters
-		 *
-		 * No parameter should be URL-encoded as this will be done when the response is
-		 * sent, though any signature specified should be Base64-encoded
-		 * @param parametersConsumer the {@link Consumer}
-		 * @return the {@link Builder} for further configurations
-		 */
-		public Builder parameters(Consumer<Map<String, String>> parametersConsumer) {
-			parametersConsumer.accept(this.parameters);
-			return this;
-		}
-
-		/**
-		 * Build the {@link Saml2LogoutResponse}
-		 * @return a constructed {@link Saml2LogoutResponse}
-		 */
-		public Saml2LogoutResponse build() {
-			return new Saml2LogoutResponse(this.location, this.binding, this.parameters);
-		}
-
-	}
-
-}

+ 0 - 10
saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/metadata/OpenSamlMetadataResolver.java

@@ -32,7 +32,6 @@ import org.opensaml.saml.saml2.metadata.AssertionConsumerService;
 import org.opensaml.saml.saml2.metadata.EntityDescriptor;
 import org.opensaml.saml.saml2.metadata.EntityDescriptor;
 import org.opensaml.saml.saml2.metadata.KeyDescriptor;
 import org.opensaml.saml.saml2.metadata.KeyDescriptor;
 import org.opensaml.saml.saml2.metadata.SPSSODescriptor;
 import org.opensaml.saml.saml2.metadata.SPSSODescriptor;
-import org.opensaml.saml.saml2.metadata.SingleLogoutService;
 import org.opensaml.saml.saml2.metadata.impl.EntityDescriptorMarshaller;
 import org.opensaml.saml.saml2.metadata.impl.EntityDescriptorMarshaller;
 import org.opensaml.security.credential.UsageType;
 import org.opensaml.security.credential.UsageType;
 import org.opensaml.xmlsec.signature.KeyInfo;
 import org.opensaml.xmlsec.signature.KeyInfo;
@@ -86,7 +85,6 @@ public final class OpenSamlMetadataResolver implements Saml2MetadataResolver {
 		spSsoDescriptor.getKeyDescriptors()
 		spSsoDescriptor.getKeyDescriptors()
 				.addAll(buildKeys(registration.getDecryptionX509Credentials(), UsageType.ENCRYPTION));
 				.addAll(buildKeys(registration.getDecryptionX509Credentials(), UsageType.ENCRYPTION));
 		spSsoDescriptor.getAssertionConsumerServices().add(buildAssertionConsumerService(registration));
 		spSsoDescriptor.getAssertionConsumerServices().add(buildAssertionConsumerService(registration));
-		spSsoDescriptor.getSingleLogoutServices().add(buildSingleLogoutService(registration));
 		return spSsoDescriptor;
 		return spSsoDescriptor;
 	}
 	}
 
 
@@ -125,14 +123,6 @@ public final class OpenSamlMetadataResolver implements Saml2MetadataResolver {
 		return assertionConsumerService;
 		return assertionConsumerService;
 	}
 	}
 
 
-	private SingleLogoutService buildSingleLogoutService(RelyingPartyRegistration registration) {
-		SingleLogoutService singleLogoutService = build(SingleLogoutService.DEFAULT_ELEMENT_NAME);
-		singleLogoutService.setLocation(registration.getSingleLogoutServiceLocation());
-		singleLogoutService.setResponseLocation(registration.getSingleLogoutServiceResponseLocation());
-		singleLogoutService.setBinding(registration.getSingleLogoutServiceBinding().getUrn());
-		return singleLogoutService;
-	}
-
 	@SuppressWarnings("unchecked")
 	@SuppressWarnings("unchecked")
 	private <T> T build(QName elementName) {
 	private <T> T build(QName elementName) {
 		XMLObjectBuilder<?> builder = XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(elementName);
 		XMLObjectBuilder<?> builder = XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(elementName);

+ 3 - 25
saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/registration/OpenSamlAssertingPartyMetadataConverter.java

@@ -34,7 +34,6 @@ import org.opensaml.saml.saml2.metadata.EntityDescriptor;
 import org.opensaml.saml.saml2.metadata.Extensions;
 import org.opensaml.saml.saml2.metadata.Extensions;
 import org.opensaml.saml.saml2.metadata.IDPSSODescriptor;
 import org.opensaml.saml.saml2.metadata.IDPSSODescriptor;
 import org.opensaml.saml.saml2.metadata.KeyDescriptor;
 import org.opensaml.saml.saml2.metadata.KeyDescriptor;
-import org.opensaml.saml.saml2.metadata.SingleLogoutService;
 import org.opensaml.saml.saml2.metadata.SingleSignOnService;
 import org.opensaml.saml.saml2.metadata.SingleSignOnService;
 import org.opensaml.security.credential.UsageType;
 import org.opensaml.security.credential.UsageType;
 import org.opensaml.xmlsec.keyinfo.KeyInfoSupport;
 import org.opensaml.xmlsec.keyinfo.KeyInfoSupport;
@@ -106,10 +105,6 @@ class OpenSamlAssertingPartyMetadataConverter {
 			builder.assertingPartyDetails(
 			builder.assertingPartyDetails(
 					(party) -> party.signingAlgorithms((algorithms) -> algorithms.add(method.getAlgorithm())));
 					(party) -> party.signingAlgorithms((algorithms) -> algorithms.add(method.getAlgorithm())));
 		}
 		}
-		if (idpssoDescriptor.getSingleSignOnServices().isEmpty()) {
-			throw new Saml2Exception(
-					"Metadata response is missing a SingleSignOnService, necessary for sending AuthnRequests");
-		}
 		for (SingleSignOnService singleSignOnService : idpssoDescriptor.getSingleSignOnServices()) {
 		for (SingleSignOnService singleSignOnService : idpssoDescriptor.getSingleSignOnServices()) {
 			Saml2MessageBinding binding;
 			Saml2MessageBinding binding;
 			if (singleSignOnService.getBinding().equals(Saml2MessageBinding.POST.getUrn())) {
 			if (singleSignOnService.getBinding().equals(Saml2MessageBinding.POST.getUrn())) {
@@ -124,27 +119,10 @@ class OpenSamlAssertingPartyMetadataConverter {
 			builder.assertingPartyDetails(
 			builder.assertingPartyDetails(
 					(party) -> party.singleSignOnServiceLocation(singleSignOnService.getLocation())
 					(party) -> party.singleSignOnServiceLocation(singleSignOnService.getLocation())
 							.singleSignOnServiceBinding(binding));
 							.singleSignOnServiceBinding(binding));
-			break;
-		}
-		for (SingleLogoutService singleLogoutService : idpssoDescriptor.getSingleLogoutServices()) {
-			Saml2MessageBinding binding;
-			if (singleLogoutService.getBinding().equals(Saml2MessageBinding.POST.getUrn())) {
-				binding = Saml2MessageBinding.POST;
-			}
-			else if (singleLogoutService.getBinding().equals(Saml2MessageBinding.REDIRECT.getUrn())) {
-				binding = Saml2MessageBinding.REDIRECT;
-			}
-			else {
-				continue;
-			}
-			String responseLocation = (singleLogoutService.getResponseLocation() == null)
-					? singleLogoutService.getLocation() : singleLogoutService.getResponseLocation();
-			builder.assertingPartyDetails(
-					(party) -> party.singleLogoutServiceLocation(singleLogoutService.getLocation())
-							.singleLogoutServiceResponseLocation(responseLocation).singleLogoutServiceBinding(binding));
-			break;
+			return builder;
 		}
 		}
-		return builder;
+		throw new Saml2Exception(
+				"Metadata response is missing a SingleSignOnService, necessary for sending AuthnRequests");
 	}
 	}
 
 
 	private List<X509Certificate> certificates(KeyDescriptor keyDescriptor) {
 	private List<X509Certificate> certificates(KeyDescriptor keyDescriptor) {

+ 6 - 238
saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistration.java

@@ -81,12 +81,6 @@ public final class RelyingPartyRegistration {
 
 
 	private final Saml2MessageBinding assertionConsumerServiceBinding;
 	private final Saml2MessageBinding assertionConsumerServiceBinding;
 
 
-	private final String singleLogoutServiceLocation;
-
-	private final String singleLogoutServiceResponseLocation;
-
-	private final Saml2MessageBinding singleLogoutServiceBinding;
-
 	private final ProviderDetails providerDetails;
 	private final ProviderDetails providerDetails;
 
 
 	private final List<org.springframework.security.saml2.credentials.Saml2X509Credential> credentials;
 	private final List<org.springframework.security.saml2.credentials.Saml2X509Credential> credentials;
@@ -96,9 +90,7 @@ public final class RelyingPartyRegistration {
 	private final Collection<Saml2X509Credential> signingX509Credentials;
 	private final Collection<Saml2X509Credential> signingX509Credentials;
 
 
 	private RelyingPartyRegistration(String registrationId, String entityId, String assertionConsumerServiceLocation,
 	private RelyingPartyRegistration(String registrationId, String entityId, String assertionConsumerServiceLocation,
-			Saml2MessageBinding assertionConsumerServiceBinding, String singleLogoutServiceLocation,
-			String singleLogoutServiceResponseLocation, Saml2MessageBinding singleLogoutServiceBinding,
-			ProviderDetails providerDetails,
+			Saml2MessageBinding assertionConsumerServiceBinding, ProviderDetails providerDetails,
 			Collection<org.springframework.security.saml2.credentials.Saml2X509Credential> credentials,
 			Collection<org.springframework.security.saml2.credentials.Saml2X509Credential> credentials,
 			Collection<Saml2X509Credential> decryptionX509Credentials,
 			Collection<Saml2X509Credential> decryptionX509Credentials,
 			Collection<Saml2X509Credential> signingX509Credentials) {
 			Collection<Saml2X509Credential> signingX509Credentials) {
@@ -126,9 +118,6 @@ public final class RelyingPartyRegistration {
 		this.entityId = entityId;
 		this.entityId = entityId;
 		this.assertionConsumerServiceLocation = assertionConsumerServiceLocation;
 		this.assertionConsumerServiceLocation = assertionConsumerServiceLocation;
 		this.assertionConsumerServiceBinding = assertionConsumerServiceBinding;
 		this.assertionConsumerServiceBinding = assertionConsumerServiceBinding;
-		this.singleLogoutServiceLocation = singleLogoutServiceLocation;
-		this.singleLogoutServiceResponseLocation = singleLogoutServiceResponseLocation;
-		this.singleLogoutServiceBinding = singleLogoutServiceBinding;
 		this.providerDetails = providerDetails;
 		this.providerDetails = providerDetails;
 		this.credentials = Collections.unmodifiableList(new LinkedList<>(credentials));
 		this.credentials = Collections.unmodifiableList(new LinkedList<>(credentials));
 		this.decryptionX509Credentials = Collections.unmodifiableList(new LinkedList<>(decryptionX509Credentials));
 		this.decryptionX509Credentials = Collections.unmodifiableList(new LinkedList<>(decryptionX509Credentials));
@@ -188,51 +177,6 @@ public final class RelyingPartyRegistration {
 		return this.assertionConsumerServiceBinding;
 		return this.assertionConsumerServiceBinding;
 	}
 	}
 
 
-	/**
-	 * Get the <a href=
-	 * "https://wiki.shibboleth.net/confluence/display/CONCEPT/MetadataForIdP#MetadataForIdP-Logout">SingleLogoutService</a>
-	 * Binding.
-	 *
-	 * <p>
-	 * Equivalent to the value found in &lt;SingleLogoutService Binding="..."/&gt; in the
-	 * relying party's &lt;SPSSODescriptor&gt;.
-	 * @return the SingleLogoutService Binding
-	 * @since 5.5
-	 */
-	public Saml2MessageBinding getSingleLogoutServiceBinding() {
-		return this.singleLogoutServiceBinding;
-	}
-
-	/**
-	 * Get the <a href=
-	 * "https://wiki.shibboleth.net/confluence/display/CONCEPT/MetadataForIdP#MetadataForIdP-Logout">SingleLogoutService</a>
-	 * Location.
-	 *
-	 * <p>
-	 * Equivalent to the value found in &lt;SingleLogoutService Location="..."/&gt; in the
-	 * relying party's &lt;SPSSODescriptor&gt;.
-	 * @return the SingleLogoutService Location
-	 * @since 5.5
-	 */
-	public String getSingleLogoutServiceLocation() {
-		return this.singleLogoutServiceLocation;
-	}
-
-	/**
-	 * Get the <a href=
-	 * "https://wiki.shibboleth.net/confluence/display/CONCEPT/MetadataForIdP#MetadataForIdP-Logout">SingleLogoutService</a>
-	 * Response Location.
-	 *
-	 * <p>
-	 * Equivalent to the value found in &lt;SingleLogoutService
-	 * ResponseLocation="..."/&gt; in the relying party's &lt;SPSSODescriptor&gt;.
-	 * @return the SingleLogoutService Response Location
-	 * @since 5.5
-	 */
-	public String getSingleLogoutServiceResponseLocation() {
-		return this.singleLogoutServiceResponseLocation;
-	}
-
 	/**
 	/**
 	 * Get the {@link Collection} of decryption {@link Saml2X509Credential}s associated
 	 * Get the {@link Collection} of decryption {@link Saml2X509Credential}s associated
 	 * with this relying party
 	 * with this relying party
@@ -420,9 +364,6 @@ public final class RelyingPartyRegistration {
 				.decryptionX509Credentials((c) -> c.addAll(registration.getDecryptionX509Credentials()))
 				.decryptionX509Credentials((c) -> c.addAll(registration.getDecryptionX509Credentials()))
 				.assertionConsumerServiceLocation(registration.getAssertionConsumerServiceLocation())
 				.assertionConsumerServiceLocation(registration.getAssertionConsumerServiceLocation())
 				.assertionConsumerServiceBinding(registration.getAssertionConsumerServiceBinding())
 				.assertionConsumerServiceBinding(registration.getAssertionConsumerServiceBinding())
-				.singleLogoutServiceLocation(registration.getSingleLogoutServiceLocation())
-				.singleLogoutServiceResponseLocation(registration.getSingleLogoutServiceResponseLocation())
-				.singleLogoutServiceBinding(registration.getSingleLogoutServiceBinding())
 				.assertingPartyDetails((assertingParty) -> assertingParty
 				.assertingPartyDetails((assertingParty) -> assertingParty
 						.entityId(registration.getAssertingPartyDetails().getEntityId())
 						.entityId(registration.getAssertingPartyDetails().getEntityId())
 						.wantAuthnRequestsSigned(registration.getAssertingPartyDetails().getWantAuthnRequestsSigned())
 						.wantAuthnRequestsSigned(registration.getAssertingPartyDetails().getWantAuthnRequestsSigned())
@@ -435,13 +376,7 @@ public final class RelyingPartyRegistration {
 						.singleSignOnServiceLocation(
 						.singleSignOnServiceLocation(
 								registration.getAssertingPartyDetails().getSingleSignOnServiceLocation())
 								registration.getAssertingPartyDetails().getSingleSignOnServiceLocation())
 						.singleSignOnServiceBinding(
 						.singleSignOnServiceBinding(
-								registration.getAssertingPartyDetails().getSingleSignOnServiceBinding())
-						.singleLogoutServiceLocation(
-								registration.getAssertingPartyDetails().getSingleLogoutServiceLocation())
-						.singleLogoutServiceResponseLocation(
-								registration.getAssertingPartyDetails().getSingleLogoutServiceResponseLocation())
-						.singleLogoutServiceBinding(
-								registration.getAssertingPartyDetails().getSingleLogoutServiceBinding()));
+								registration.getAssertingPartyDetails().getSingleSignOnServiceBinding()));
 	}
 	}
 
 
 	private static Saml2X509Credential fromDeprecated(
 	private static Saml2X509Credential fromDeprecated(
@@ -510,17 +445,10 @@ public final class RelyingPartyRegistration {
 
 
 		private final Saml2MessageBinding singleSignOnServiceBinding;
 		private final Saml2MessageBinding singleSignOnServiceBinding;
 
 
-		private final String singleLogoutServiceLocation;
-
-		private final String singleLogoutServiceResponseLocation;
-
-		private final Saml2MessageBinding singleLogoutServiceBinding;
-
 		private AssertingPartyDetails(String entityId, boolean wantAuthnRequestsSigned, List<String> signingAlgorithms,
 		private AssertingPartyDetails(String entityId, boolean wantAuthnRequestsSigned, List<String> signingAlgorithms,
 				Collection<Saml2X509Credential> verificationX509Credentials,
 				Collection<Saml2X509Credential> verificationX509Credentials,
 				Collection<Saml2X509Credential> encryptionX509Credentials, String singleSignOnServiceLocation,
 				Collection<Saml2X509Credential> encryptionX509Credentials, String singleSignOnServiceLocation,
-				Saml2MessageBinding singleSignOnServiceBinding, String singleLogoutServiceLocation,
-				String singleLogoutServiceResponseLocation, Saml2MessageBinding singleLogoutServiceBinding) {
+				Saml2MessageBinding singleSignOnServiceBinding) {
 			Assert.hasText(entityId, "entityId cannot be null or empty");
 			Assert.hasText(entityId, "entityId cannot be null or empty");
 			Assert.notEmpty(signingAlgorithms, "signingAlgorithms cannot be empty");
 			Assert.notEmpty(signingAlgorithms, "signingAlgorithms cannot be empty");
 			Assert.notNull(verificationX509Credentials, "verificationX509Credentials cannot be null");
 			Assert.notNull(verificationX509Credentials, "verificationX509Credentials cannot be null");
@@ -544,9 +472,6 @@ public final class RelyingPartyRegistration {
 			this.encryptionX509Credentials = encryptionX509Credentials;
 			this.encryptionX509Credentials = encryptionX509Credentials;
 			this.singleSignOnServiceLocation = singleSignOnServiceLocation;
 			this.singleSignOnServiceLocation = singleSignOnServiceLocation;
 			this.singleSignOnServiceBinding = singleSignOnServiceBinding;
 			this.singleSignOnServiceBinding = singleSignOnServiceBinding;
-			this.singleLogoutServiceLocation = singleLogoutServiceLocation;
-			this.singleLogoutServiceResponseLocation = singleLogoutServiceResponseLocation;
-			this.singleLogoutServiceBinding = singleLogoutServiceBinding;
 		}
 		}
 
 
 		/**
 		/**
@@ -640,48 +565,6 @@ public final class RelyingPartyRegistration {
 			return this.singleSignOnServiceBinding;
 			return this.singleSignOnServiceBinding;
 		}
 		}
 
 
-		/**
-		 * Get the <a href=
-		 * "https://wiki.shibboleth.net/confluence/display/CONCEPT/MetadataForIdP#MetadataForIdP-Logout">SingleLogoutService</a>
-		 * Location.
-		 *
-		 * <p>
-		 * Equivalent to the value found in &lt;SingleLogoutService Location="..."/&gt; in
-		 * the asserting party's &lt;IDPSSODescriptor&gt;.
-		 * @return the SingleLogoutService Location
-		 */
-		public String getSingleLogoutServiceLocation() {
-			return this.singleLogoutServiceLocation;
-		}
-
-		/**
-		 * Get the <a href=
-		 * "https://wiki.shibboleth.net/confluence/display/CONCEPT/MetadataForIdP#MetadataForIdP-Logout">SingleLogoutService</a>
-		 * ResponseLocation.
-		 *
-		 * <p>
-		 * Equivalent to the value found in &lt;SingleLogoutService Location="..."/&gt; in
-		 * the asserting party's &lt;IDPSSODescriptor&gt;.
-		 * @return the SingleLogoutService Response Location
-		 */
-		public String getSingleLogoutServiceResponseLocation() {
-			return this.singleLogoutServiceResponseLocation;
-		}
-
-		/**
-		 * Get the <a href=
-		 * "https://wiki.shibboleth.net/confluence/display/CONCEPT/MetadataForIdP#MetadataForIdP-Logout">SingleLogoutService</a>
-		 * Binding.
-		 *
-		 * <p>
-		 * Equivalent to the value found in &lt;SingleLogoutService Binding="..."/&gt; in
-		 * the asserting party's &lt;IDPSSODescriptor&gt;.
-		 * @return the SingleLogoutService Binding
-		 */
-		public Saml2MessageBinding getSingleLogoutServiceBinding() {
-			return this.singleLogoutServiceBinding;
-		}
-
 		public static final class Builder {
 		public static final class Builder {
 
 
 			private String entityId;
 			private String entityId;
@@ -698,12 +581,6 @@ public final class RelyingPartyRegistration {
 
 
 			private Saml2MessageBinding singleSignOnServiceBinding = Saml2MessageBinding.REDIRECT;
 			private Saml2MessageBinding singleSignOnServiceBinding = Saml2MessageBinding.REDIRECT;
 
 
-			private String singleLogoutServiceLocation;
-
-			private String singleLogoutServiceResponseLocation;
-
-			private Saml2MessageBinding singleLogoutServiceBinding = Saml2MessageBinding.REDIRECT;
-
 			/**
 			/**
 			 * Set the asserting party's <a href=
 			 * Set the asserting party's <a href=
 			 * "https://wiki.shibboleth.net/confluence/display/CONCEPT/EntityNaming">EntityID</a>.
 			 * "https://wiki.shibboleth.net/confluence/display/CONCEPT/EntityNaming">EntityID</a>.
@@ -800,55 +677,6 @@ public final class RelyingPartyRegistration {
 				return this;
 				return this;
 			}
 			}
 
 
-			/**
-			 * Set the <a href=
-			 * "https://wiki.shibboleth.net/confluence/display/CONCEPT/MetadataForIdP#MetadataForIdP-Logout">SingleLogoutService</a>
-			 * Location.
-			 *
-			 * <p>
-			 * Equivalent to the value found in &lt;SingleLogoutService
-			 * Location="..."/&gt; in the asserting party's &lt;IDPSSODescriptor&gt;.
-			 * @return the SingleLogoutService Location
-			 * @since 5.5
-			 */
-			public Builder singleLogoutServiceLocation(String singleLogoutServiceLocation) {
-				this.singleLogoutServiceLocation = singleLogoutServiceLocation;
-				return this;
-			}
-
-			/**
-			 * Set the <a href=
-			 * "https://wiki.shibboleth.net/confluence/display/CONCEPT/MetadataForIdP#MetadataForIdP-Logout">SingleLogoutService</a>
-			 * Response Location.
-			 *
-			 * <p>
-			 * Equivalent to the value found in &lt;SingleLogoutService
-			 * ResponseLocation="..."/&gt; in the asserting party's
-			 * &lt;IDPSSODescriptor&gt;.
-			 * @return the SingleLogoutService Response Location
-			 * @since 5.5
-			 */
-			public Builder singleLogoutServiceResponseLocation(String singleLogoutServiceResponseLocation) {
-				this.singleLogoutServiceResponseLocation = singleLogoutServiceResponseLocation;
-				return this;
-			}
-
-			/**
-			 * Set the <a href=
-			 * "https://wiki.shibboleth.net/confluence/display/CONCEPT/MetadataForIdP#MetadataForIdP-Logout">SingleLogoutService</a>
-			 * Binding.
-			 *
-			 * <p>
-			 * Equivalent to the value found in &lt;SingleLogoutService Binding="..."/&gt;
-			 * in the asserting party's &lt;IDPSSODescriptor&gt;.
-			 * @return the SingleLogoutService Binding
-			 * @since 5.5
-			 */
-			public Builder singleLogoutServiceBinding(Saml2MessageBinding singleLogoutServiceBinding) {
-				this.singleLogoutServiceBinding = singleLogoutServiceBinding;
-				return this;
-			}
-
 			/**
 			/**
 			 * Creates an immutable ProviderDetails object representing the configuration
 			 * Creates an immutable ProviderDetails object representing the configuration
 			 * for an Identity Provider, IDP
 			 * for an Identity Provider, IDP
@@ -861,9 +689,7 @@ public final class RelyingPartyRegistration {
 
 
 				return new AssertingPartyDetails(this.entityId, this.wantAuthnRequestsSigned, signingAlgorithms,
 				return new AssertingPartyDetails(this.entityId, this.wantAuthnRequestsSigned, signingAlgorithms,
 						this.verificationX509Credentials, this.encryptionX509Credentials,
 						this.verificationX509Credentials, this.encryptionX509Credentials,
-						this.singleSignOnServiceLocation, this.singleSignOnServiceBinding,
-						this.singleLogoutServiceLocation, this.singleLogoutServiceResponseLocation,
-						this.singleLogoutServiceBinding);
+						this.singleSignOnServiceLocation, this.singleSignOnServiceBinding);
 			}
 			}
 
 
 		}
 		}
@@ -1004,12 +830,6 @@ public final class RelyingPartyRegistration {
 
 
 		private Saml2MessageBinding assertionConsumerServiceBinding = Saml2MessageBinding.POST;
 		private Saml2MessageBinding assertionConsumerServiceBinding = Saml2MessageBinding.POST;
 
 
-		private String singleLogoutServiceLocation;
-
-		private String singleLogoutServiceResponseLocation;
-
-		private Saml2MessageBinding singleLogoutServiceBinding = Saml2MessageBinding.POST;
-
 		private ProviderDetails.Builder providerDetails = new ProviderDetails.Builder();
 		private ProviderDetails.Builder providerDetails = new ProviderDetails.Builder();
 
 
 		private Collection<org.springframework.security.saml2.credentials.Saml2X509Credential> credentials = new HashSet<>();
 		private Collection<org.springframework.security.saml2.credentials.Saml2X509Credential> credentials = new HashSet<>();
@@ -1113,54 +933,6 @@ public final class RelyingPartyRegistration {
 			return this;
 			return this;
 		}
 		}
 
 
-		/**
-		 * Set the <a href=
-		 * "https://wiki.shibboleth.net/confluence/display/CONCEPT/MetadataForIdP#MetadataForIdP-Logout">SingleLogoutService</a>
-		 * Binding.
-		 *
-		 * <p>
-		 * Equivalent to the value found in &lt;SingleLogoutService Binding="..."/&gt; in
-		 * the relying party's &lt;SPSSODescriptor&gt;.
-		 * @return the SingleLogoutService Binding
-		 * @since 5.5
-		 */
-		public Builder singleLogoutServiceBinding(Saml2MessageBinding singleLogoutServiceBinding) {
-			this.singleLogoutServiceBinding = singleLogoutServiceBinding;
-			return this;
-		}
-
-		/**
-		 * Set the <a href=
-		 * "https://wiki.shibboleth.net/confluence/display/CONCEPT/MetadataForIdP#MetadataForIdP-Logout">SingleLogoutService</a>
-		 * Location.
-		 *
-		 * <p>
-		 * Equivalent to the value found in &lt;SingleLogoutService Location="..."/&gt; in
-		 * the relying party's &lt;SPSSODescriptor&gt;.
-		 * @return the SingleLogoutService Location
-		 * @since 5.5
-		 */
-		public Builder singleLogoutServiceLocation(String singleLogoutServiceLocation) {
-			this.singleLogoutServiceLocation = singleLogoutServiceLocation;
-			return this;
-		}
-
-		/**
-		 * Set the <a href=
-		 * "https://wiki.shibboleth.net/confluence/display/CONCEPT/MetadataForIdP#MetadataForIdP-Logout">SingleLogoutService</a>
-		 * Response Location.
-		 *
-		 * <p>
-		 * Equivalent to the value found in &lt;SingleLogoutService
-		 * ResponseLocation="..."/&gt; in the relying party's &lt;SPSSODescriptor&gt;.
-		 * @return the SingleLogoutService Response Location
-		 * @since 5.5
-		 */
-		public Builder singleLogoutServiceResponseLocation(String singleLogoutServiceResponseLocation) {
-			this.singleLogoutServiceResponseLocation = singleLogoutServiceResponseLocation;
-			return this;
-		}
-
 		/**
 		/**
 		 * Apply this {@link Consumer} to further configure the Asserting Party details
 		 * Apply this {@link Consumer} to further configure the Asserting Party details
 		 * @param assertingPartyDetails The {@link Consumer} to apply
 		 * @param assertingPartyDetails The {@link Consumer} to apply
@@ -1303,14 +1075,10 @@ public final class RelyingPartyRegistration {
 			for (Saml2X509Credential credential : this.providerDetails.assertingPartyDetailsBuilder.encryptionX509Credentials) {
 			for (Saml2X509Credential credential : this.providerDetails.assertingPartyDetailsBuilder.encryptionX509Credentials) {
 				this.credentials.add(toDeprecated(credential));
 				this.credentials.add(toDeprecated(credential));
 			}
 			}
-			if (this.singleLogoutServiceResponseLocation == null) {
-				this.singleLogoutServiceResponseLocation = this.singleLogoutServiceLocation;
-			}
 			return new RelyingPartyRegistration(this.registrationId, this.entityId,
 			return new RelyingPartyRegistration(this.registrationId, this.entityId,
 					this.assertionConsumerServiceLocation, this.assertionConsumerServiceBinding,
 					this.assertionConsumerServiceLocation, this.assertionConsumerServiceBinding,
-					this.singleLogoutServiceLocation, this.singleLogoutServiceResponseLocation,
-					this.singleLogoutServiceBinding, this.providerDetails.build(), this.credentials,
-					this.decryptionX509Credentials, this.signingX509Credentials);
+					this.providerDetails.build(), this.credentials, this.decryptionX509Credentials,
+					this.signingX509Credentials);
 		}
 		}
 
 
 	}
 	}

+ 11 - 10
saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/DefaultRelyingPartyRegistrationResolver.java

@@ -41,7 +41,8 @@ import org.springframework.web.util.UriComponentsBuilder;
  * @author Josh Cummings
  * @author Josh Cummings
  * @since 5.4
  * @since 5.4
  */
  */
-public final class DefaultRelyingPartyRegistrationResolver implements RelyingPartyRegistrationResolver {
+public final class DefaultRelyingPartyRegistrationResolver
+		implements Converter<HttpServletRequest, RelyingPartyRegistration>, RelyingPartyRegistrationResolver {
 
 
 	private static final char PATH_DELIMITER = '/';
 	private static final char PATH_DELIMITER = '/';
 
 
@@ -55,6 +56,14 @@ public final class DefaultRelyingPartyRegistrationResolver implements RelyingPar
 		this.relyingPartyRegistrationRepository = relyingPartyRegistrationRepository;
 		this.relyingPartyRegistrationRepository = relyingPartyRegistrationRepository;
 	}
 	}
 
 
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public RelyingPartyRegistration convert(HttpServletRequest request) {
+		return resolve(request, null);
+	}
+
 	/**
 	/**
 	 * {@inheritDoc}
 	 * {@inheritDoc}
 	 */
 	 */
@@ -77,14 +86,9 @@ public final class DefaultRelyingPartyRegistrationResolver implements RelyingPar
 		String relyingPartyEntityId = templateResolver.apply(relyingPartyRegistration.getEntityId());
 		String relyingPartyEntityId = templateResolver.apply(relyingPartyRegistration.getEntityId());
 		String assertionConsumerServiceLocation = templateResolver
 		String assertionConsumerServiceLocation = templateResolver
 				.apply(relyingPartyRegistration.getAssertionConsumerServiceLocation());
 				.apply(relyingPartyRegistration.getAssertionConsumerServiceLocation());
-		String singleLogoutServiceLocation = templateResolver
-				.apply(relyingPartyRegistration.getSingleLogoutServiceLocation());
-		String singleLogoutServiceResponseLocation = templateResolver
-				.apply(relyingPartyRegistration.getSingleLogoutServiceResponseLocation());
 		return RelyingPartyRegistration.withRelyingPartyRegistration(relyingPartyRegistration)
 		return RelyingPartyRegistration.withRelyingPartyRegistration(relyingPartyRegistration)
 				.entityId(relyingPartyEntityId).assertionConsumerServiceLocation(assertionConsumerServiceLocation)
 				.entityId(relyingPartyEntityId).assertionConsumerServiceLocation(assertionConsumerServiceLocation)
-				.singleLogoutServiceLocation(singleLogoutServiceLocation)
-				.singleLogoutServiceResponseLocation(singleLogoutServiceResponseLocation).build();
+				.build();
 	}
 	}
 
 
 	private Function<String, String> templateResolver(String applicationUri, RelyingPartyRegistration relyingParty) {
 	private Function<String, String> templateResolver(String applicationUri, RelyingPartyRegistration relyingParty) {
@@ -92,9 +96,6 @@ public final class DefaultRelyingPartyRegistrationResolver implements RelyingPar
 	}
 	}
 
 
 	private static String resolveUrlTemplate(String template, String baseUrl, RelyingPartyRegistration relyingParty) {
 	private static String resolveUrlTemplate(String template, String baseUrl, RelyingPartyRegistration relyingParty) {
-		if (template == null) {
-			return null;
-		}
 		String entityId = relyingParty.getAssertingPartyDetails().getEntityId();
 		String entityId = relyingParty.getAssertingPartyDetails().getEntityId();
 		String registrationId = relyingParty.getRegistrationId();
 		String registrationId = relyingParty.getRegistrationId();
 		Map<String, String> uriVariables = new HashMap<>();
 		Map<String, String> uriVariables = new HashMap<>();

+ 0 - 112
saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/HttpSessionLogoutRequestRepository.java

@@ -1,112 +0,0 @@
-/*
- * Copyright 2002-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.provider.service.web.authentication.logout;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-
-import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutRequest;
-import org.springframework.util.Assert;
-
-/**
- * An implementation of an {@link Saml2LogoutRequestRepository} that stores
- * {@link Saml2LogoutRequest} in the {@code HttpSession}.
- *
- * @author Josh Cummings
- * @since 5.5
- * @see Saml2LogoutRequestRepository
- * @see Saml2LogoutRequest
- */
-public final class HttpSessionLogoutRequestRepository implements Saml2LogoutRequestRepository {
-
-	private static final String DEFAULT_LOGOUT_REQUEST_ATTR_NAME = HttpSessionLogoutRequestRepository.class.getName()
-			+ ".LOGOUT_REQUEST";
-
-	/**
-	 * {@inheritDoc}
-	 */
-	@Override
-	public Saml2LogoutRequest loadLogoutRequest(HttpServletRequest request) {
-		Assert.notNull(request, "request cannot be null");
-		String stateParameter = this.getStateParameter(request);
-		if (stateParameter == null) {
-			return null;
-		}
-		Map<String, Saml2LogoutRequest> logoutRequests = this.getLogoutRequests(request);
-		return logoutRequests.get(stateParameter);
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	@Override
-	public void saveLogoutRequest(Saml2LogoutRequest logoutRequest, HttpServletRequest request,
-			HttpServletResponse response) {
-		Assert.notNull(request, "request cannot be null");
-		Assert.notNull(response, "response cannot be null");
-		if (logoutRequest == null) {
-			removeLogoutRequest(request, response);
-			return;
-		}
-		String state = logoutRequest.getRelayState();
-		Assert.hasText(state, "logoutRequest.state cannot be empty");
-		Map<String, Saml2LogoutRequest> logoutRequests = this.getLogoutRequests(request);
-		logoutRequests.put(state, logoutRequest);
-		request.getSession().setAttribute(DEFAULT_LOGOUT_REQUEST_ATTR_NAME, logoutRequests);
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	@Override
-	public Saml2LogoutRequest removeLogoutRequest(HttpServletRequest request, HttpServletResponse response) {
-		Assert.notNull(request, "request cannot be null");
-		Assert.notNull(response, "response cannot be null");
-		String stateParameter = getStateParameter(request);
-		if (stateParameter == null) {
-			return null;
-		}
-		Map<String, Saml2LogoutRequest> logoutRequests = getLogoutRequests(request);
-		Saml2LogoutRequest originalRequest = logoutRequests.remove(stateParameter);
-		if (!logoutRequests.isEmpty()) {
-			request.getSession().setAttribute(DEFAULT_LOGOUT_REQUEST_ATTR_NAME, logoutRequests);
-		}
-		else {
-			request.getSession().removeAttribute(DEFAULT_LOGOUT_REQUEST_ATTR_NAME);
-		}
-		return originalRequest;
-	}
-
-	private String getStateParameter(HttpServletRequest request) {
-		return request.getParameter("RelayState");
-	}
-
-	private Map<String, Saml2LogoutRequest> getLogoutRequests(HttpServletRequest request) {
-		HttpSession session = request.getSession(false);
-		Map<String, Saml2LogoutRequest> logoutRequests = (session != null)
-				? (Map<String, Saml2LogoutRequest>) session.getAttribute(DEFAULT_LOGOUT_REQUEST_ATTR_NAME) : null;
-		if (logoutRequests == null) {
-			return new HashMap<>();
-		}
-		return logoutRequests;
-	}
-
-}

+ 0 - 198
saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSamlLogoutRequestHandler.java

@@ -1,198 +0,0 @@
-/*
- * Copyright 2002-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.provider.service.web.authentication.logout;
-
-import java.io.ByteArrayInputStream;
-import java.nio.charset.StandardCharsets;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import net.shibboleth.utilities.java.support.xml.ParserPool;
-import org.opensaml.core.config.ConfigurationService;
-import org.opensaml.core.xml.config.XMLObjectProviderRegistry;
-import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
-import org.opensaml.saml.saml2.core.LogoutRequest;
-import org.opensaml.saml.saml2.core.NameID;
-import org.opensaml.saml.saml2.core.impl.LogoutRequestUnmarshaller;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-import org.springframework.http.HttpMethod;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.saml2.Saml2Exception;
-import org.springframework.security.saml2.core.OpenSamlInitializationService;
-import org.springframework.security.saml2.core.Saml2Error;
-import org.springframework.security.saml2.core.Saml2ErrorCodes;
-import org.springframework.security.saml2.core.Saml2ResponseValidatorResult;
-import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
-import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
-import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver;
-import org.springframework.security.saml2.provider.service.web.authentication.logout.OpenSamlVerificationUtils.VerifierPartial;
-import org.springframework.security.web.authentication.logout.LogoutHandler;
-import org.springframework.util.Assert;
-
-/**
- * A {@link LogoutHandler} that handles SAML 2.0 Logout Requests received from a SAML 2.0
- * Asserting Party.
- *
- * @author Josh Cummings
- * @since 5.5
- */
-public final class OpenSamlLogoutRequestHandler implements LogoutHandler {
-
-	static {
-		OpenSamlInitializationService.initialize();
-	}
-
-	private final RelyingPartyRegistrationResolver relyingPartyRegistrationResolver;
-
-	private final ParserPool parserPool;
-
-	private final LogoutRequestUnmarshaller unmarshaller;
-
-	/**
-	 * Constructs a {@link OpenSamlLogoutRequestHandler} from the provided parameters
-	 * @param relyingPartyRegistrationResolver the
-	 * {@link RelyingPartyRegistrationResolver} from which to derive the
-	 * {@link RelyingPartyRegistration}
-	 */
-	public OpenSamlLogoutRequestHandler(RelyingPartyRegistrationResolver relyingPartyRegistrationResolver) {
-		this.relyingPartyRegistrationResolver = relyingPartyRegistrationResolver;
-		XMLObjectProviderRegistry registry = ConfigurationService.get(XMLObjectProviderRegistry.class);
-		this.parserPool = registry.getParserPool();
-		this.unmarshaller = (LogoutRequestUnmarshaller) XMLObjectProviderRegistrySupport.getUnmarshallerFactory()
-				.getUnmarshaller(LogoutRequest.DEFAULT_ELEMENT_NAME);
-	}
-
-	/**
-	 * Processes the SAML 2.0 Logout Request received from the SAML 2.0 Asserting Party.
-	 *
-	 * By default, verifies the signature, validates the issuer, destination, and user
-	 * identifier.
-	 *
-	 * If any processing step fails, a {@link Saml2Exception} is thrown, stopping the
-	 * logout process
-	 * @param request the HTTP request
-	 * @param response the HTTP response
-	 * @param authentication the current principal details
-	 */
-	@Override
-	public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
-		String serialized = request.getParameter("SAMLRequest");
-		Assert.notNull(serialized, "SAMLRequest cannot be null");
-		byte[] b = Saml2Utils.samlDecode(serialized);
-		serialized = inflateIfRequired(request, b);
-		RelyingPartyRegistration registration = this.relyingPartyRegistrationResolver.resolve(request,
-				getRegistrationId(authentication));
-		Assert.notNull(registration, "Failed to lookup RelyingPartyRegistration for request");
-		LogoutRequest logoutRequest = parse(serialized);
-		Saml2ResponseValidatorResult result = verifySignature(request, logoutRequest, registration);
-		result = result.concat(validateRequest(logoutRequest, registration, authentication));
-		if (result.hasErrors()) {
-			throw new Saml2Exception("Failed to validate LogoutRequest: " + result.getErrors().iterator().next());
-		}
-		request.setAttribute(LogoutRequest.class.getName(), logoutRequest);
-	}
-
-	private String getRegistrationId(Authentication authentication) {
-		if (authentication instanceof Saml2Authentication) {
-			return ((Saml2Authentication) authentication).getRelyingPartyRegistrationId();
-		}
-		return null;
-	}
-
-	private String inflateIfRequired(HttpServletRequest request, byte[] b) {
-		if (HttpMethod.GET.matches(request.getMethod())) {
-			return Saml2Utils.samlInflate(b);
-		}
-		return new String(b, StandardCharsets.UTF_8);
-	}
-
-	private LogoutRequest parse(String request) throws Saml2Exception {
-		try {
-			Document document = this.parserPool
-					.parse(new ByteArrayInputStream(request.getBytes(StandardCharsets.UTF_8)));
-			Element element = document.getDocumentElement();
-			return (LogoutRequest) this.unmarshaller.unmarshall(element);
-		}
-		catch (Exception ex) {
-			throw new Saml2Exception("Failed to deserialize LogoutRequest", ex);
-		}
-	}
-
-	private Saml2ResponseValidatorResult verifySignature(HttpServletRequest request, LogoutRequest logoutRequest,
-			RelyingPartyRegistration registration) {
-		VerifierPartial partial = OpenSamlVerificationUtils.verifySignature(logoutRequest, registration);
-		if (logoutRequest.isSigned()) {
-			return partial.post(logoutRequest.getSignature());
-		}
-		return partial.redirect(request, "SAMLRequest");
-	}
-
-	private Saml2ResponseValidatorResult validateRequest(LogoutRequest request, RelyingPartyRegistration registration,
-			Authentication authentication) {
-		Saml2ResponseValidatorResult result = Saml2ResponseValidatorResult.success();
-		return result.concat(validateIssuer(request, registration)).concat(validateDestination(request, registration))
-				.concat(validateName(request, authentication));
-	}
-
-	private Saml2ResponseValidatorResult validateIssuer(LogoutRequest request, RelyingPartyRegistration registration) {
-		if (request.getIssuer() == null) {
-			return Saml2ResponseValidatorResult
-					.failure(new Saml2Error(Saml2ErrorCodes.INVALID_ISSUER, "Failed to find issuer in LogoutResponse"));
-		}
-		String issuer = request.getIssuer().getValue();
-		if (!issuer.equals(registration.getAssertingPartyDetails().getEntityId())) {
-			return Saml2ResponseValidatorResult.failure(
-					new Saml2Error(Saml2ErrorCodes.INVALID_ISSUER, "Failed to match issuer to configured issuer"));
-		}
-		return Saml2ResponseValidatorResult.success();
-	}
-
-	private Saml2ResponseValidatorResult validateDestination(LogoutRequest request,
-			RelyingPartyRegistration registration) {
-		if (request.getDestination() == null) {
-			return Saml2ResponseValidatorResult.failure(new Saml2Error(Saml2ErrorCodes.INVALID_DESTINATION,
-					"Failed to find destination in LogoutResponse"));
-		}
-		String destination = request.getDestination();
-		if (!destination.equals(registration.getSingleLogoutServiceLocation())) {
-			return Saml2ResponseValidatorResult.failure(new Saml2Error(Saml2ErrorCodes.INVALID_DESTINATION,
-					"Failed to match destination to configured destination"));
-		}
-		return Saml2ResponseValidatorResult.success();
-	}
-
-	private Saml2ResponseValidatorResult validateName(LogoutRequest request, Authentication authentication) {
-		if (authentication == null) {
-			return Saml2ResponseValidatorResult.success();
-		}
-		NameID nameId = request.getNameID();
-		if (nameId == null) {
-			return Saml2ResponseValidatorResult.failure(
-					new Saml2Error(Saml2ErrorCodes.SUBJECT_NOT_FOUND, "Failed to find subject in LogoutRequest"));
-		}
-		String name = nameId.getValue();
-		if (!name.equals(authentication.getName())) {
-			return Saml2ResponseValidatorResult.failure(new Saml2Error(Saml2ErrorCodes.INVALID_REQUEST,
-					"Failed to match subject in LogoutRequest with currently logged in user"));
-		}
-		return Saml2ResponseValidatorResult.success();
-	}
-
-}

+ 0 - 243
saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSamlLogoutRequestResolver.java

@@ -1,243 +0,0 @@
-/*
- * Copyright 2002-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.provider.service.web.authentication.logout;
-
-import java.nio.charset.StandardCharsets;
-import java.util.Map;
-import java.util.UUID;
-import java.util.function.Consumer;
-
-import javax.servlet.http.HttpServletRequest;
-
-import net.shibboleth.utilities.java.support.xml.SerializeSupport;
-import org.opensaml.core.config.ConfigurationService;
-import org.opensaml.core.xml.config.XMLObjectProviderRegistry;
-import org.opensaml.core.xml.io.MarshallingException;
-import org.opensaml.saml.saml2.core.Issuer;
-import org.opensaml.saml.saml2.core.LogoutRequest;
-import org.opensaml.saml.saml2.core.NameID;
-import org.opensaml.saml.saml2.core.impl.IssuerBuilder;
-import org.opensaml.saml.saml2.core.impl.LogoutRequestBuilder;
-import org.opensaml.saml.saml2.core.impl.LogoutRequestMarshaller;
-import org.opensaml.saml.saml2.core.impl.NameIDBuilder;
-import org.w3c.dom.Element;
-
-import org.springframework.security.core.Authentication;
-import org.springframework.security.saml2.Saml2Exception;
-import org.springframework.security.saml2.core.OpenSamlInitializationService;
-import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
-import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutRequest;
-import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
-import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
-import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver;
-import org.springframework.util.Assert;
-
-/**
- * A {@link Saml2LogoutRequestResolver} for resolving SAML 2.0 Logout Requests with
- * OpenSAML
- *
- * Note that there are {@link Saml2LogoutRequestResolver} implements that are targeted for
- * OpenSAML 3 and OpenSAML 4 via {@code OpenSaml3LogoutRequestResolver} and
- * {@code OpenSaml4LogoutRequestResolver}
- *
- * @author Josh Cummings
- * @since 5.5
- */
-public final class OpenSamlLogoutRequestResolver implements Saml2LogoutRequestResolver {
-
-	private final RelyingPartyRegistrationResolver relyingPartyRegistrationResolver;
-
-	/**
-	 * Construct a {@link OpenSamlLogoutRequestResolver} using the provided parameters
-	 * @param relyingPartyRegistrationResolver the
-	 * {@link RelyingPartyRegistrationResolver} for selecting the
-	 * {@link RelyingPartyRegistration}
-	 */
-	public OpenSamlLogoutRequestResolver(RelyingPartyRegistrationResolver relyingPartyRegistrationResolver) {
-		this.relyingPartyRegistrationResolver = relyingPartyRegistrationResolver;
-	}
-
-	/**
-	 * Prepare to create, sign, and serialize a SAML 2.0 Logout Request.
-	 *
-	 * By default, includes a {@code NameID} based on the {@link Authentication} instance
-	 * as well as the {@code Destination} and {@code Issuer} based on the
-	 * {@link RelyingPartyRegistration} derived from the {@link Authentication}.
-	 *
-	 * The {@link Authentication} must be of type {@link Saml2Authentication} in order to
-	 * look up the {@link RelyingPartyRegistration} that holds the signing key.
-	 * @param request the HTTP request
-	 * @param authentication the current principal details
-	 * @return a builder, useful for overriding any aspects of the SAML 2.0 Logout Request
-	 * that the resolver supplied
-	 */
-	@Override
-	public OpenSamlLogoutRequestBuilder resolveLogoutRequest(HttpServletRequest request,
-			Authentication authentication) {
-		Assert.notNull(authentication, "Failed to lookup logged-in user for formulating LogoutRequest");
-		RelyingPartyRegistration registration = this.relyingPartyRegistrationResolver.resolve(request,
-				getRegistrationId(authentication));
-		Assert.notNull(registration, "Failed to lookup RelyingPartyRegistration for formulating LogoutRequest");
-		return new OpenSamlLogoutRequestBuilder(registration)
-				.destination(registration.getAssertingPartyDetails().getSingleLogoutServiceLocation())
-				.issuer(registration.getEntityId()).name(authentication.getName());
-	}
-
-	private String getRegistrationId(Authentication authentication) {
-		if (authentication instanceof Saml2Authentication) {
-			return ((Saml2Authentication) authentication).getRelyingPartyRegistrationId();
-		}
-		return null;
-	}
-
-	/**
-	 * A builder, useful for overriding any aspects of the SAML 2.0 Logout Request that
-	 * the resolver supplied.
-	 *
-	 * The request returned from the {@link #logoutRequest()} method is signed and
-	 * serialized. It will at minimum include an {@code ID} and a {@code RelayState},
-	 * though note that callers should also provide an {@code IssueInstant}. For your
-	 * convenience, {@link OpenSamlLogoutRequestResolver} also sets some default values.
-	 *
-	 * This builder is specifically handy for getting access to the underlying
-	 * {@link LogoutRequest} to make changes before it gets signed and serialized
-	 *
-	 * @see OpenSamlLogoutRequestResolver#resolveLogoutRequest
-	 */
-	public static final class OpenSamlLogoutRequestBuilder
-			implements Saml2LogoutRequestBuilder<OpenSamlLogoutRequestBuilder> {
-
-		static {
-			OpenSamlInitializationService.initialize();
-		}
-
-		private final LogoutRequestMarshaller marshaller;
-
-		private final IssuerBuilder issuerBuilder;
-
-		private final NameIDBuilder nameIdBuilder;
-
-		private final RelyingPartyRegistration registration;
-
-		private final LogoutRequest logoutRequest;
-
-		private String relayState;
-
-		/**
-		 * Construct a {@link OpenSamlLogoutRequestBuilder} using the provided parameters
-		 * @param registration the {@link RelyingPartyRegistration} to use
-		 */
-		public OpenSamlLogoutRequestBuilder(RelyingPartyRegistration registration) {
-			Assert.notNull(registration, "registration cannot be null");
-			this.registration = registration;
-			XMLObjectProviderRegistry registry = ConfigurationService.get(XMLObjectProviderRegistry.class);
-			this.marshaller = (LogoutRequestMarshaller) registry.getMarshallerFactory()
-					.getMarshaller(LogoutRequest.DEFAULT_ELEMENT_NAME);
-			Assert.notNull(this.marshaller, "logoutRequestMarshaller must be configured in OpenSAML");
-			LogoutRequestBuilder logoutRequestBuilder = (LogoutRequestBuilder) registry.getBuilderFactory()
-					.getBuilder(LogoutRequest.DEFAULT_ELEMENT_NAME);
-			Assert.notNull(logoutRequestBuilder, "logoutRequestBuilder must be configured in OpenSAML");
-			this.issuerBuilder = (IssuerBuilder) registry.getBuilderFactory().getBuilder(Issuer.DEFAULT_ELEMENT_NAME);
-			Assert.notNull(this.issuerBuilder, "issuerBuilder must be configured in OpenSAML");
-			this.nameIdBuilder = (NameIDBuilder) registry.getBuilderFactory().getBuilder(NameID.DEFAULT_ELEMENT_NAME);
-			Assert.notNull(this.nameIdBuilder, "nameIdBuilder must be configured in OpenSAML");
-			this.logoutRequest = logoutRequestBuilder.buildObject();
-		}
-
-		/**
-		 * {@inheritDoc}
-		 */
-		@Override
-		public OpenSamlLogoutRequestBuilder name(String name) {
-			NameID nameId = this.nameIdBuilder.buildObject();
-			nameId.setValue(name);
-			this.logoutRequest.setNameID(nameId);
-			return this;
-		}
-
-		/**
-		 * {@inheritDoc}
-		 */
-		@Override
-		public OpenSamlLogoutRequestBuilder relayState(String relayState) {
-			this.relayState = relayState;
-			return this;
-		}
-
-		/**
-		 * Mutate the {@link LogoutRequest} using the provided {@link Consumer}
-		 * @param request the Logout Request {@link Consumer} to use
-		 * @return the {@link OpenSamlLogoutRequestBuilder} for further customizations
-		 */
-		public OpenSamlLogoutRequestBuilder logoutRequest(Consumer<LogoutRequest> request) {
-			request.accept(this.logoutRequest);
-			return this;
-		}
-
-		private OpenSamlLogoutRequestBuilder destination(String destination) {
-			this.logoutRequest.setDestination(destination);
-			return this;
-		}
-
-		private OpenSamlLogoutRequestBuilder issuer(String issuer) {
-			Issuer iss = this.issuerBuilder.buildObject();
-			iss.setValue(issuer);
-			this.logoutRequest.setIssuer(iss);
-			return this;
-		}
-
-		/**
-		 * {@inheritDoc}
-		 */
-		@Override
-		public Saml2LogoutRequest logoutRequest() {
-			if (this.logoutRequest.getID() == null) {
-				this.logoutRequest.setID("LR" + UUID.randomUUID());
-			}
-			if (this.relayState == null) {
-				this.relayState = UUID.randomUUID().toString();
-			}
-			Saml2LogoutRequest.Builder result = Saml2LogoutRequest.withRelyingPartyRegistration(this.registration)
-					.id(this.logoutRequest.getID());
-			if (this.registration.getAssertingPartyDetails()
-					.getSingleLogoutServiceBinding() == Saml2MessageBinding.POST) {
-				String xml = serialize(OpenSamlSigningUtils.sign(this.logoutRequest, this.registration));
-				return result.samlRequest(Saml2Utils.samlEncode(xml.getBytes(StandardCharsets.UTF_8))).build();
-			}
-			else {
-				String xml = serialize(this.logoutRequest);
-				String deflatedAndEncoded = Saml2Utils.samlEncode(Saml2Utils.samlDeflate(xml));
-				result.samlRequest(deflatedAndEncoded);
-				Map<String, String> parameters = OpenSamlSigningUtils.sign(this.registration)
-						.param("SAMLRequest", deflatedAndEncoded).param("RelayState", this.relayState).parameters();
-				return result.parameters((params) -> params.putAll(parameters)).build();
-			}
-		}
-
-		private String serialize(LogoutRequest logoutRequest) {
-			try {
-				Element element = this.marshaller.marshall(logoutRequest);
-				return SerializeSupport.nodeToString(element);
-			}
-			catch (MarshallingException ex) {
-				throw new Saml2Exception(ex);
-			}
-		}
-
-	}
-
-}

+ 0 - 217
saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSamlLogoutResponseHandler.java

@@ -1,217 +0,0 @@
-/*
- * Copyright 2002-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.provider.service.web.authentication.logout;
-
-import java.io.ByteArrayInputStream;
-import java.nio.charset.StandardCharsets;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import net.shibboleth.utilities.java.support.xml.ParserPool;
-import org.opensaml.core.config.ConfigurationService;
-import org.opensaml.core.xml.config.XMLObjectProviderRegistry;
-import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
-import org.opensaml.saml.saml2.core.LogoutResponse;
-import org.opensaml.saml.saml2.core.StatusCode;
-import org.opensaml.saml.saml2.core.impl.LogoutResponseUnmarshaller;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-import org.springframework.http.HttpMethod;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.saml2.Saml2Exception;
-import org.springframework.security.saml2.core.OpenSamlInitializationService;
-import org.springframework.security.saml2.core.Saml2Error;
-import org.springframework.security.saml2.core.Saml2ErrorCodes;
-import org.springframework.security.saml2.core.Saml2ResponseValidatorResult;
-import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutRequest;
-import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
-import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver;
-import org.springframework.security.saml2.provider.service.web.authentication.logout.OpenSamlVerificationUtils.VerifierPartial;
-import org.springframework.security.web.authentication.logout.LogoutHandler;
-import org.springframework.util.Assert;
-
-/**
- * A {@link LogoutHandler} that handles SAML 2.0 Logout Responses received from a SAML 2.0
- * Asserting Party.
- *
- * @author Josh Cummings
- * @since 5.5
- */
-public final class OpenSamlLogoutResponseHandler implements LogoutHandler {
-
-	static {
-		OpenSamlInitializationService.initialize();
-	}
-
-	private final RelyingPartyRegistrationResolver relyingPartyRegistrationResolver;
-
-	private final ParserPool parserPool;
-
-	private final LogoutResponseUnmarshaller unmarshaller;
-
-	private Saml2LogoutRequestRepository logoutRequestRepository = new HttpSessionLogoutRequestRepository();
-
-	/**
-	 * Constructs a {@link OpenSamlLogoutResponseHandler} from the provided parameters
-	 * @param relyingPartyRegistrationResolver the
-	 * {@link RelyingPartyRegistrationResolver} from which to derive the
-	 * {@link RelyingPartyRegistration}
-	 */
-	public OpenSamlLogoutResponseHandler(RelyingPartyRegistrationResolver relyingPartyRegistrationResolver) {
-		this.relyingPartyRegistrationResolver = relyingPartyRegistrationResolver;
-		XMLObjectProviderRegistry registry = ConfigurationService.get(XMLObjectProviderRegistry.class);
-		this.parserPool = registry.getParserPool();
-		this.unmarshaller = (LogoutResponseUnmarshaller) XMLObjectProviderRegistrySupport.getUnmarshallerFactory()
-				.getUnmarshaller(LogoutResponse.DEFAULT_ELEMENT_NAME);
-	}
-
-	/**
-	 * Processes the SAML 2.0 Logout Response received from the SAML 2.0 Asserting Party.
-	 *
-	 * By default, verifies the signature, validates the issuer, destination, and status.
-	 *
-	 * If any processing step fails, a {@link Saml2Exception} is thrown, stopping the
-	 * logout process
-	 * @param request the HTTP request
-	 * @param response the HTTP response
-	 * @param authentication the current principal details
-	 */
-	@Override
-	public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
-		String serialized = request.getParameter("SAMLResponse");
-		Assert.notNull(serialized, "SAMLResponse cannot be null");
-		byte[] b = Saml2Utils.samlDecode(serialized);
-		serialized = inflateIfRequired(request, b);
-		Saml2LogoutRequest logoutRequest = this.logoutRequestRepository.removeLogoutRequest(request, response);
-		if (logoutRequest == null) {
-			throw new Saml2Exception("Failed to find associated LogoutRequest");
-		}
-		RelyingPartyRegistration registration = this.relyingPartyRegistrationResolver.resolve(request,
-				logoutRequest.getRelyingPartyRegistrationId());
-		LogoutResponse logoutResponse = parse(serialized);
-		Saml2ResponseValidatorResult result = verifySignature(request, logoutResponse, registration)
-				.concat(validateRequest(logoutResponse, registration))
-				.concat(validateLogoutRequest(logoutResponse, logoutRequest.getId()));
-		if (result.hasErrors()) {
-			throw new Saml2Exception("Failed to validate LogoutResponse: " + result.getErrors().iterator().next());
-		}
-	}
-
-	/**
-	 * Use this {@link Saml2LogoutRequestRepository} for looking up the associated logout
-	 * request.
-	 * @param logoutRequestRepository the {@link Saml2LogoutRequestRepository} to use
-	 */
-	public void setLogoutRequestRepository(Saml2LogoutRequestRepository logoutRequestRepository) {
-		Assert.notNull(logoutRequestRepository, "logoutRequestRepository cannot be null");
-		this.logoutRequestRepository = logoutRequestRepository;
-	}
-
-	private String inflateIfRequired(HttpServletRequest request, byte[] b) {
-		if (HttpMethod.GET.matches(request.getMethod())) {
-			return Saml2Utils.samlInflate(b);
-		}
-		return new String(b, StandardCharsets.UTF_8);
-	}
-
-	private LogoutResponse parse(String response) throws Saml2Exception {
-		try {
-			Document document = this.parserPool
-					.parse(new ByteArrayInputStream(response.getBytes(StandardCharsets.UTF_8)));
-			Element element = document.getDocumentElement();
-			return (LogoutResponse) this.unmarshaller.unmarshall(element);
-		}
-		catch (Exception ex) {
-			throw new Saml2Exception("Failed to deserialize LogoutResponse", ex);
-		}
-	}
-
-	private Saml2ResponseValidatorResult verifySignature(HttpServletRequest request, LogoutResponse response,
-			RelyingPartyRegistration registration) {
-		VerifierPartial partial = OpenSamlVerificationUtils.verifySignature(response, registration);
-		if (response.isSigned()) {
-			return partial.post(response.getSignature());
-		}
-		return partial.redirect(request, "SAMLResponse");
-	}
-
-	private Saml2ResponseValidatorResult validateRequest(LogoutResponse response,
-			RelyingPartyRegistration registration) {
-		Saml2ResponseValidatorResult result = Saml2ResponseValidatorResult.success();
-		return result.concat(validateIssuer(response, registration)).concat(validateDestination(response, registration))
-				.concat(validateStatus(response));
-	}
-
-	private Saml2ResponseValidatorResult validateIssuer(LogoutResponse response,
-			RelyingPartyRegistration registration) {
-		if (response.getIssuer() == null) {
-			return Saml2ResponseValidatorResult
-					.failure(new Saml2Error(Saml2ErrorCodes.INVALID_ISSUER, "Failed to find issuer in LogoutResponse"));
-		}
-		String issuer = response.getIssuer().getValue();
-		if (!issuer.equals(registration.getAssertingPartyDetails().getEntityId())) {
-			return Saml2ResponseValidatorResult.failure(
-					new Saml2Error(Saml2ErrorCodes.INVALID_ISSUER, "Failed to match issuer to configured issuer"));
-		}
-		return Saml2ResponseValidatorResult.success();
-	}
-
-	private Saml2ResponseValidatorResult validateDestination(LogoutResponse response,
-			RelyingPartyRegistration registration) {
-		if (response.getDestination() == null) {
-			return Saml2ResponseValidatorResult.failure(new Saml2Error(Saml2ErrorCodes.INVALID_DESTINATION,
-					"Failed to find destination in LogoutResponse"));
-		}
-		String destination = response.getDestination();
-		if (!destination.equals(registration.getSingleLogoutServiceResponseLocation())) {
-			return Saml2ResponseValidatorResult.failure(new Saml2Error(Saml2ErrorCodes.INVALID_DESTINATION,
-					"Failed to match destination to configured destination"));
-		}
-		return Saml2ResponseValidatorResult.success();
-	}
-
-	private Saml2ResponseValidatorResult validateStatus(LogoutResponse response) {
-		if (response.getStatus() == null) {
-			return Saml2ResponseValidatorResult.success();
-		}
-		if (response.getStatus().getStatusCode() == null) {
-			return Saml2ResponseValidatorResult.success();
-		}
-		if (StatusCode.SUCCESS.equals(response.getStatus().getStatusCode().getValue())) {
-			return Saml2ResponseValidatorResult.success();
-		}
-		if (StatusCode.PARTIAL_LOGOUT.equals(response.getStatus().getStatusCode().getValue())) {
-			return Saml2ResponseValidatorResult.success();
-		}
-		return Saml2ResponseValidatorResult
-				.failure(new Saml2Error(Saml2ErrorCodes.INVALID_RESPONSE, "Response indicated logout failed"));
-	}
-
-	private Saml2ResponseValidatorResult validateLogoutRequest(LogoutResponse response, String id) {
-		if (response.getInResponseTo() == null) {
-			return Saml2ResponseValidatorResult.success();
-		}
-		if (response.getInResponseTo().equals(id)) {
-			return Saml2ResponseValidatorResult.success();
-		}
-		return Saml2ResponseValidatorResult.failure(new Saml2Error(Saml2ErrorCodes.INVALID_RESPONSE,
-				"LogoutResponse InResponseTo doesn't match ID of associated LogoutRequest"));
-	}
-
-}

+ 0 - 268
saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSamlLogoutResponseResolver.java

@@ -1,268 +0,0 @@
-/*
- * Copyright 2002-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.provider.service.web.authentication.logout;
-
-import java.nio.charset.StandardCharsets;
-import java.util.UUID;
-import java.util.function.Consumer;
-
-import javax.servlet.http.HttpServletRequest;
-
-import net.shibboleth.utilities.java.support.xml.SerializeSupport;
-import org.opensaml.core.config.ConfigurationService;
-import org.opensaml.core.xml.config.XMLObjectProviderRegistry;
-import org.opensaml.core.xml.io.MarshallingException;
-import org.opensaml.saml.saml2.core.Issuer;
-import org.opensaml.saml.saml2.core.LogoutRequest;
-import org.opensaml.saml.saml2.core.LogoutResponse;
-import org.opensaml.saml.saml2.core.Status;
-import org.opensaml.saml.saml2.core.StatusCode;
-import org.opensaml.saml.saml2.core.impl.IssuerBuilder;
-import org.opensaml.saml.saml2.core.impl.LogoutResponseBuilder;
-import org.opensaml.saml.saml2.core.impl.LogoutResponseMarshaller;
-import org.opensaml.saml.saml2.core.impl.StatusBuilder;
-import org.opensaml.saml.saml2.core.impl.StatusCodeBuilder;
-import org.w3c.dom.Element;
-
-import org.springframework.security.core.Authentication;
-import org.springframework.security.saml2.Saml2Exception;
-import org.springframework.security.saml2.core.OpenSamlInitializationService;
-import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
-import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutResponse;
-import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
-import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
-import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver;
-import org.springframework.security.saml2.provider.service.web.authentication.logout.OpenSamlSigningUtils.QueryParametersPartial;
-import org.springframework.util.Assert;
-
-/**
- * A {@link Saml2LogoutRequestResolver} for resolving SAML 2.0 Logout Responses with
- * OpenSAML
- *
- * Note that there are {@link Saml2LogoutRequestResolver} implements that are targeted for
- * OpenSAML 3 and OpenSAML 4 via {@code OpenSaml3LogoutResponseResolver} and
- * {@code OpenSaml4LogoutResponseResolver}
- *
- * @author Josh Cummings
- * @since 5.5
- */
-public final class OpenSamlLogoutResponseResolver implements Saml2LogoutResponseResolver {
-
-	private final RelyingPartyRegistrationResolver relyingPartyRegistrationResolver;
-
-	/**
-	 * Construct a {@link OpenSamlLogoutResponseResolver} using the provided parameters
-	 * @param relyingPartyRegistrationResolver the
-	 * {@link RelyingPartyRegistrationResolver} for selecting the
-	 * {@link RelyingPartyRegistration}
-	 */
-	public OpenSamlLogoutResponseResolver(RelyingPartyRegistrationResolver relyingPartyRegistrationResolver) {
-		this.relyingPartyRegistrationResolver = relyingPartyRegistrationResolver;
-	}
-
-	/**
-	 * Prepare to create, sign, and serialize a SAML 2.0 Logout Response.
-	 *
-	 * By default, includes a {@code RelayState} based on the {@link HttpServletRequest}
-	 * as well as the {@code Destination} and {@code Issuer} based on the
-	 * {@link RelyingPartyRegistration} derived from the {@link Authentication}. The
-	 * logout response is also marked as {@code SUCCESS}.
-	 *
-	 * The {@link Authentication} must be of type {@link Saml2Authentication} in order to
-	 * look up the {@link RelyingPartyRegistration} that holds the signing key.
-	 * @param request the HTTP request
-	 * @param authentication the current principal details
-	 * @return a builder, useful for overriding any aspects of the SAML 2.0 Logout Request
-	 * that the resolver supplied
-	 */
-	@Override
-	public OpenSamlLogoutResponseBuilder resolveLogoutResponse(HttpServletRequest request,
-			Authentication authentication) {
-		LogoutRequest logoutRequest = (LogoutRequest) request.getAttribute(LogoutRequest.class.getName());
-		if (logoutRequest == null) {
-			throw new Saml2Exception("Failed to find associated LogoutRequest");
-		}
-		RelyingPartyRegistration registration = this.relyingPartyRegistrationResolver.resolve(request,
-				getRegistrationId(authentication));
-		Assert.notNull(registration, "Failed to lookup RelyingPartyRegistration for request");
-		return new OpenSamlLogoutResponseBuilder(registration)
-				.destination(registration.getAssertingPartyDetails().getSingleLogoutServiceResponseLocation())
-				.issuer(registration.getEntityId()).status(StatusCode.SUCCESS)
-				.relayState(request.getParameter("RelayState")).inResponseTo(logoutRequest.getID());
-	}
-
-	private String getRegistrationId(Authentication authentication) {
-		if (authentication instanceof Saml2Authentication) {
-			return ((Saml2Authentication) authentication).getRelyingPartyRegistrationId();
-		}
-		return null;
-	}
-
-	/**
-	 * A builder, useful for overriding any aspects of the SAML 2.0 Logout Response that
-	 * the resolver supplied.
-	 *
-	 * The request returned from the {@link #logoutResponse()} method is signed and
-	 * serialized. It will at minimum include an {@code ID}, though note that callers
-	 * should include an {@code InResponseTo} and {@code IssueInstant}. For your
-	 * convenience, {@link OpenSamlLogoutResponseResolver} also sets some default values.
-	 *
-	 * This builder is specifically handy for getting access to the underlying
-	 * {@link LogoutResponse} to make changes before it gets signed and serialized
-	 *
-	 * @see OpenSamlLogoutResponseResolver#resolveLogoutResponse
-	 */
-	public static final class OpenSamlLogoutResponseBuilder
-			implements Saml2LogoutResponseBuilder<OpenSamlLogoutResponseBuilder> {
-
-		static {
-			OpenSamlInitializationService.initialize();
-		}
-
-		private final LogoutResponseMarshaller marshaller;
-
-		private final LogoutResponseBuilder logoutResponseBuilder;
-
-		private final IssuerBuilder issuerBuilder;
-
-		private final StatusBuilder statusBuilder;
-
-		private final StatusCodeBuilder statusCodeBuilder;
-
-		private final RelyingPartyRegistration registration;
-
-		private final LogoutResponse logoutResponse;
-
-		private String relayState;
-
-		/**
-		 * Construct a {@link OpenSamlLogoutResponseBuilder} using the provided parameters
-		 * @param registration the {@link RelyingPartyRegistration} to use
-		 */
-		public OpenSamlLogoutResponseBuilder(RelyingPartyRegistration registration) {
-			Assert.notNull(registration, "registration cannot be null");
-			this.registration = registration;
-			XMLObjectProviderRegistry registry = ConfigurationService.get(XMLObjectProviderRegistry.class);
-			this.marshaller = (LogoutResponseMarshaller) registry.getMarshallerFactory()
-					.getMarshaller(LogoutResponse.DEFAULT_ELEMENT_NAME);
-			Assert.notNull(this.marshaller, "logoutResponseMarshaller must be configured in OpenSAML");
-			this.logoutResponseBuilder = (LogoutResponseBuilder) registry.getBuilderFactory()
-					.getBuilder(LogoutResponse.DEFAULT_ELEMENT_NAME);
-			Assert.notNull(this.logoutResponseBuilder, "logoutResponseBuilder must be configured in OpenSAML");
-			this.issuerBuilder = (IssuerBuilder) registry.getBuilderFactory().getBuilder(Issuer.DEFAULT_ELEMENT_NAME);
-			Assert.notNull(this.issuerBuilder, "issuerBuilder must be configured in OpenSAML");
-			this.statusBuilder = (StatusBuilder) registry.getBuilderFactory().getBuilder(Status.DEFAULT_ELEMENT_NAME);
-			Assert.notNull(this.statusBuilder, "statusBuilder must be configured in OpenSAML");
-			this.statusCodeBuilder = (StatusCodeBuilder) registry.getBuilderFactory()
-					.getBuilder(StatusCode.DEFAULT_ELEMENT_NAME);
-			Assert.notNull(this.statusCodeBuilder, "statusCodeBuilder must be configured in OpenSAML");
-			this.logoutResponse = this.logoutResponseBuilder.buildObject();
-		}
-
-		/**
-		 * {@inheritDoc}
-		 */
-		@Override
-		public OpenSamlLogoutResponseBuilder inResponseTo(String inResponseTo) {
-			this.logoutResponse.setInResponseTo(inResponseTo);
-			return this;
-		}
-
-		/**
-		 * {@inheritDoc}
-		 */
-		@Override
-		public OpenSamlLogoutResponseBuilder status(String status) {
-			StatusCode code = this.statusCodeBuilder.buildObject();
-			code.setValue(status);
-			Status s = this.statusBuilder.buildObject();
-			s.setStatusCode(code);
-			this.logoutResponse.setStatus(s);
-			return this;
-		}
-
-		/**
-		 * {@inheritDoc}
-		 */
-		@Override
-		public OpenSamlLogoutResponseBuilder relayState(String relayState) {
-			this.relayState = relayState;
-			return this;
-		}
-
-		/**
-		 * Mutate the {@link LogoutResponse} using the provided {@link Consumer}
-		 * @param response the Logout Response {@link Consumer} to use
-		 * @return the {@link OpenSamlLogoutResponseBuilder} for further customizations
-		 */
-		public OpenSamlLogoutResponseBuilder logoutResponse(Consumer<LogoutResponse> response) {
-			response.accept(this.logoutResponse);
-			return this;
-		}
-
-		private OpenSamlLogoutResponseBuilder destination(String destination) {
-			this.logoutResponse.setDestination(destination);
-			return this;
-		}
-
-		private OpenSamlLogoutResponseBuilder issuer(String issuer) {
-			Issuer iss = this.issuerBuilder.buildObject();
-			iss.setValue(issuer);
-			this.logoutResponse.setIssuer(iss);
-			return this;
-		}
-
-		/**
-		 * {@inheritDoc}
-		 */
-		@Override
-		public Saml2LogoutResponse logoutResponse() {
-			Saml2LogoutResponse.Builder result = Saml2LogoutResponse.withRelyingPartyRegistration(this.registration);
-			if (this.logoutResponse.getID() == null) {
-				this.logoutResponse.setID("LR" + UUID.randomUUID());
-			}
-			if (this.registration.getAssertingPartyDetails()
-					.getSingleLogoutServiceBinding() == Saml2MessageBinding.POST) {
-				String xml = serialize(OpenSamlSigningUtils.sign(this.logoutResponse, this.registration));
-				return result.samlResponse(Saml2Utils.samlEncode(xml.getBytes(StandardCharsets.UTF_8))).build();
-			}
-			else {
-				String xml = serialize(this.logoutResponse);
-				String deflatedAndEncoded = Saml2Utils.samlEncode(Saml2Utils.samlDeflate(xml));
-				result.samlResponse(deflatedAndEncoded);
-				QueryParametersPartial partial = OpenSamlSigningUtils.sign(this.registration).param("SAMLResponse",
-						deflatedAndEncoded);
-				if (this.relayState != null) {
-					partial.param("RelayState", this.relayState);
-				}
-				return result.parameters((params) -> params.putAll(partial.parameters())).build();
-			}
-		}
-
-		private String serialize(LogoutResponse logoutResponse) {
-			try {
-				Element element = this.marshaller.marshall(logoutResponse);
-				return SerializeSupport.nodeToString(element);
-			}
-			catch (MarshallingException ex) {
-				throw new Saml2Exception(ex);
-			}
-		}
-
-	}
-
-}

+ 0 - 173
saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSamlSigningUtils.java

@@ -1,173 +0,0 @@
-/*
- * Copyright 2002-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.provider.service.web.authentication.logout;
-
-import java.nio.charset.StandardCharsets;
-import java.security.PrivateKey;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
-import net.shibboleth.utilities.java.support.xml.SerializeSupport;
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
-import org.opensaml.core.xml.io.Marshaller;
-import org.opensaml.core.xml.io.MarshallingException;
-import org.opensaml.saml.security.impl.SAMLMetadataSignatureSigningParametersResolver;
-import org.opensaml.security.SecurityException;
-import org.opensaml.security.credential.BasicCredential;
-import org.opensaml.security.credential.Credential;
-import org.opensaml.security.credential.CredentialSupport;
-import org.opensaml.security.credential.UsageType;
-import org.opensaml.xmlsec.SignatureSigningParameters;
-import org.opensaml.xmlsec.SignatureSigningParametersResolver;
-import org.opensaml.xmlsec.criterion.SignatureSigningConfigurationCriterion;
-import org.opensaml.xmlsec.crypto.XMLSigningUtil;
-import org.opensaml.xmlsec.impl.BasicSignatureSigningConfiguration;
-import org.opensaml.xmlsec.signature.SignableXMLObject;
-import org.opensaml.xmlsec.signature.support.SignatureConstants;
-import org.opensaml.xmlsec.signature.support.SignatureSupport;
-import org.w3c.dom.Element;
-
-import org.springframework.security.saml2.Saml2Exception;
-import org.springframework.security.saml2.core.Saml2X509Credential;
-import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
-import org.springframework.util.Assert;
-import org.springframework.web.util.UriComponentsBuilder;
-import org.springframework.web.util.UriUtils;
-
-/**
- * Utility methods for signing SAML components with OpenSAML
- *
- * For internal use only.
- *
- * @author Josh Cummings
- */
-final class OpenSamlSigningUtils {
-
-	static String serialize(XMLObject object) {
-		try {
-			Marshaller marshaller = XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(object);
-			Element element = marshaller.marshall(object);
-			return SerializeSupport.nodeToString(element);
-		}
-		catch (MarshallingException ex) {
-			throw new Saml2Exception(ex);
-		}
-	}
-
-	static <O extends SignableXMLObject> O sign(O object, RelyingPartyRegistration relyingPartyRegistration) {
-		SignatureSigningParameters parameters = resolveSigningParameters(relyingPartyRegistration);
-		try {
-			SignatureSupport.signObject(object, parameters);
-			return object;
-		}
-		catch (Exception ex) {
-			throw new Saml2Exception(ex);
-		}
-	}
-
-	static QueryParametersPartial sign(RelyingPartyRegistration registration) {
-		return new QueryParametersPartial(registration);
-	}
-
-	private static SignatureSigningParameters resolveSigningParameters(
-			RelyingPartyRegistration relyingPartyRegistration) {
-		List<Credential> credentials = resolveSigningCredentials(relyingPartyRegistration);
-		List<String> algorithms = relyingPartyRegistration.getAssertingPartyDetails().getSigningAlgorithms();
-		List<String> digests = Collections.singletonList(SignatureConstants.ALGO_ID_DIGEST_SHA256);
-		String canonicalization = SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS;
-		SignatureSigningParametersResolver resolver = new SAMLMetadataSignatureSigningParametersResolver();
-		CriteriaSet criteria = new CriteriaSet();
-		BasicSignatureSigningConfiguration signingConfiguration = new BasicSignatureSigningConfiguration();
-		signingConfiguration.setSigningCredentials(credentials);
-		signingConfiguration.setSignatureAlgorithms(algorithms);
-		signingConfiguration.setSignatureReferenceDigestMethods(digests);
-		signingConfiguration.setSignatureCanonicalizationAlgorithm(canonicalization);
-		criteria.add(new SignatureSigningConfigurationCriterion(signingConfiguration));
-		try {
-			SignatureSigningParameters parameters = resolver.resolveSingle(criteria);
-			Assert.notNull(parameters, "Failed to resolve any signing credential");
-			return parameters;
-		}
-		catch (Exception ex) {
-			throw new Saml2Exception(ex);
-		}
-	}
-
-	private static List<Credential> resolveSigningCredentials(RelyingPartyRegistration relyingPartyRegistration) {
-		List<Credential> credentials = new ArrayList<>();
-		for (Saml2X509Credential x509Credential : relyingPartyRegistration.getSigningX509Credentials()) {
-			X509Certificate certificate = x509Credential.getCertificate();
-			PrivateKey privateKey = x509Credential.getPrivateKey();
-			BasicCredential credential = CredentialSupport.getSimpleCredential(certificate, privateKey);
-			credential.setEntityId(relyingPartyRegistration.getEntityId());
-			credential.setUsageType(UsageType.SIGNING);
-			credentials.add(credential);
-		}
-		return credentials;
-	}
-
-	static class QueryParametersPartial {
-
-		final RelyingPartyRegistration registration;
-
-		final Map<String, String> components = new LinkedHashMap<>();
-
-		QueryParametersPartial(RelyingPartyRegistration registration) {
-			this.registration = registration;
-		}
-
-		QueryParametersPartial param(String key, String value) {
-			this.components.put(key, value);
-			return this;
-		}
-
-		Map<String, String> parameters() {
-			SignatureSigningParameters parameters = resolveSigningParameters(this.registration);
-			Credential credential = parameters.getSigningCredential();
-			String algorithmUri = parameters.getSignatureAlgorithm();
-			this.components.put("SigAlg", algorithmUri);
-			UriComponentsBuilder builder = UriComponentsBuilder.newInstance();
-			for (Map.Entry<String, String> component : this.components.entrySet()) {
-				builder.queryParam(component.getKey(),
-						UriUtils.encode(component.getValue(), StandardCharsets.ISO_8859_1));
-			}
-			String queryString = builder.build(true).toString().substring(1);
-			try {
-				byte[] rawSignature = XMLSigningUtil.signWithURI(credential, algorithmUri,
-						queryString.getBytes(StandardCharsets.UTF_8));
-				String b64Signature = Saml2Utils.samlEncode(rawSignature);
-				this.components.put("Signature", b64Signature);
-			}
-			catch (SecurityException ex) {
-				throw new Saml2Exception(ex);
-			}
-			return this.components;
-		}
-
-	}
-
-	private OpenSamlSigningUtils() {
-
-	}
-
-}

+ 0 - 218
saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSamlVerificationUtils.java

@@ -1,218 +0,0 @@
-/*
- * Copyright 2002-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.provider.service.web.authentication.logout;
-
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-
-import javax.servlet.http.HttpServletRequest;
-
-import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
-import org.opensaml.core.criterion.EntityIdCriterion;
-import org.opensaml.saml.common.xml.SAMLConstants;
-import org.opensaml.saml.criterion.ProtocolCriterion;
-import org.opensaml.saml.metadata.criteria.role.impl.EvaluableProtocolRoleDescriptorCriterion;
-import org.opensaml.saml.saml2.core.Issuer;
-import org.opensaml.saml.saml2.core.RequestAbstractType;
-import org.opensaml.saml.saml2.core.StatusResponseType;
-import org.opensaml.saml.security.impl.SAMLSignatureProfileValidator;
-import org.opensaml.security.credential.Credential;
-import org.opensaml.security.credential.CredentialResolver;
-import org.opensaml.security.credential.UsageType;
-import org.opensaml.security.credential.criteria.impl.EvaluableEntityIDCredentialCriterion;
-import org.opensaml.security.credential.criteria.impl.EvaluableUsageCredentialCriterion;
-import org.opensaml.security.credential.impl.CollectionCredentialResolver;
-import org.opensaml.security.criteria.UsageCriterion;
-import org.opensaml.security.x509.BasicX509Credential;
-import org.opensaml.xmlsec.config.impl.DefaultSecurityConfigurationBootstrap;
-import org.opensaml.xmlsec.signature.Signature;
-import org.opensaml.xmlsec.signature.support.SignatureTrustEngine;
-import org.opensaml.xmlsec.signature.support.impl.ExplicitKeySignatureTrustEngine;
-
-import org.springframework.security.saml2.core.Saml2Error;
-import org.springframework.security.saml2.core.Saml2ErrorCodes;
-import org.springframework.security.saml2.core.Saml2ResponseValidatorResult;
-import org.springframework.security.saml2.core.Saml2X509Credential;
-import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
-import org.springframework.web.util.UriUtils;
-
-/**
- * Utility methods for verifying SAML component signatures with OpenSAML
- *
- * For internal use only.
- *
- * @author Josh Cummings
- */
-
-final class OpenSamlVerificationUtils {
-
-	static VerifierPartial verifySignature(StatusResponseType object, RelyingPartyRegistration registration) {
-		return new VerifierPartial(object, registration);
-	}
-
-	static VerifierPartial verifySignature(RequestAbstractType object, RelyingPartyRegistration registration) {
-		return new VerifierPartial(object, registration);
-	}
-
-	static class VerifierPartial {
-
-		private final String id;
-
-		private final CriteriaSet criteria;
-
-		private final SignatureTrustEngine trustEngine;
-
-		VerifierPartial(StatusResponseType object, RelyingPartyRegistration registration) {
-			this.id = object.getID();
-			this.criteria = verificationCriteria(object.getIssuer());
-			this.trustEngine = trustEngine(registration);
-		}
-
-		VerifierPartial(RequestAbstractType object, RelyingPartyRegistration registration) {
-			this.id = object.getID();
-			this.criteria = verificationCriteria(object.getIssuer());
-			this.trustEngine = trustEngine(registration);
-		}
-
-		Saml2ResponseValidatorResult redirect(HttpServletRequest request, String objectParameterName) {
-			RedirectSignature signature = new RedirectSignature(request, objectParameterName);
-			if (signature.getAlgorithm() == null) {
-				return Saml2ResponseValidatorResult.failure(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
-						"Missing signature algorithm for object [" + this.id + "]"));
-			}
-			if (!signature.hasSignature()) {
-				return Saml2ResponseValidatorResult.failure(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
-						"Missing signature for object [" + this.id + "]"));
-			}
-			Collection<Saml2Error> errors = new ArrayList<>();
-			String algorithmUri = signature.getAlgorithm();
-			try {
-				if (!this.trustEngine.validate(signature.getSignature(), signature.getContent(), algorithmUri,
-						this.criteria, null)) {
-					errors.add(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
-							"Invalid signature for object [" + this.id + "]"));
-				}
-			}
-			catch (Exception ex) {
-				errors.add(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
-						"Invalid signature for object [" + this.id + "]: "));
-			}
-			return Saml2ResponseValidatorResult.failure(errors);
-		}
-
-		Saml2ResponseValidatorResult post(Signature signature) {
-			Collection<Saml2Error> errors = new ArrayList<>();
-			SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator();
-			try {
-				profileValidator.validate(signature);
-			}
-			catch (Exception ex) {
-				errors.add(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
-						"Invalid signature for object [" + this.id + "]: "));
-			}
-
-			try {
-				if (!this.trustEngine.validate(signature, this.criteria)) {
-					errors.add(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
-							"Invalid signature for object [" + this.id + "]"));
-				}
-			}
-			catch (Exception ex) {
-				errors.add(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
-						"Invalid signature for object [" + this.id + "]: "));
-			}
-
-			return Saml2ResponseValidatorResult.failure(errors);
-		}
-
-		private CriteriaSet verificationCriteria(Issuer issuer) {
-			CriteriaSet criteria = new CriteriaSet();
-			criteria.add(new EvaluableEntityIDCredentialCriterion(new EntityIdCriterion(issuer.getValue())));
-			criteria.add(new EvaluableProtocolRoleDescriptorCriterion(new ProtocolCriterion(SAMLConstants.SAML20P_NS)));
-			criteria.add(new EvaluableUsageCredentialCriterion(new UsageCriterion(UsageType.SIGNING)));
-			return criteria;
-		}
-
-		private SignatureTrustEngine trustEngine(RelyingPartyRegistration registration) {
-			Set<Credential> credentials = new HashSet<>();
-			Collection<Saml2X509Credential> keys = registration.getAssertingPartyDetails()
-					.getVerificationX509Credentials();
-			for (Saml2X509Credential key : keys) {
-				BasicX509Credential cred = new BasicX509Credential(key.getCertificate());
-				cred.setUsageType(UsageType.SIGNING);
-				cred.setEntityId(registration.getAssertingPartyDetails().getEntityId());
-				credentials.add(cred);
-			}
-			CredentialResolver credentialsResolver = new CollectionCredentialResolver(credentials);
-			return new ExplicitKeySignatureTrustEngine(credentialsResolver,
-					DefaultSecurityConfigurationBootstrap.buildBasicInlineKeyInfoCredentialResolver());
-		}
-
-		private static class RedirectSignature {
-
-			private final HttpServletRequest request;
-
-			private final String objectParameterName;
-
-			RedirectSignature(HttpServletRequest request, String objectParameterName) {
-				this.request = request;
-				this.objectParameterName = objectParameterName;
-			}
-
-			String getAlgorithm() {
-				return this.request.getParameter("SigAlg");
-			}
-
-			byte[] getContent() {
-				if (this.request.getParameter("RelayState") != null) {
-					return String.format("%s=%s&RelayState=%s&SigAlg=%s", this.objectParameterName,
-							UriUtils.encode(this.request.getParameter(this.objectParameterName),
-									StandardCharsets.ISO_8859_1),
-							UriUtils.encode(this.request.getParameter("RelayState"), StandardCharsets.ISO_8859_1),
-							UriUtils.encode(getAlgorithm(), StandardCharsets.ISO_8859_1))
-							.getBytes(StandardCharsets.UTF_8);
-				}
-				else {
-					return String
-							.format("%s=%s&SigAlg=%s", this.objectParameterName,
-									UriUtils.encode(this.request.getParameter(this.objectParameterName),
-											StandardCharsets.ISO_8859_1),
-									UriUtils.encode(getAlgorithm(), StandardCharsets.ISO_8859_1))
-							.getBytes(StandardCharsets.UTF_8);
-				}
-			}
-
-			byte[] getSignature() {
-				return Saml2Utils.samlDecode(this.request.getParameter("Signature"));
-			}
-
-			boolean hasSignature() {
-				return this.request.getParameter("Signature") != null;
-			}
-
-		}
-
-	}
-
-	private OpenSamlVerificationUtils() {
-
-	}
-
-}

+ 0 - 92
saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutRequestFilter.java

@@ -1,92 +0,0 @@
-/*
- * Copyright 2002-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.provider.service.web.authentication.logout;
-
-import java.io.IOException;
-
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.web.authentication.logout.LogoutHandler;
-import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
-import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
-import org.springframework.security.web.util.matcher.RequestMatcher;
-import org.springframework.util.Assert;
-import org.springframework.web.filter.OncePerRequestFilter;
-
-/**
- * A filter for handling logout requests in the form of a &lt;saml2:LogoutRequest&gt; sent
- * from the asserting party.
- *
- * @author Josh Cummings
- * @since 5.5
- */
-public final class Saml2LogoutRequestFilter extends OncePerRequestFilter {
-
-	private static final String DEFAULT_LOGOUT_ENDPOINT = "/logout/saml2/slo";
-
-	private RequestMatcher logoutRequestMatcher = new AntPathRequestMatcher(DEFAULT_LOGOUT_ENDPOINT);
-
-	private final LogoutHandler logoutHandler;
-
-	private final LogoutSuccessHandler logoutSuccessHandler;
-
-	/**
-	 * Constructs a {@link Saml2LogoutResponseFilter} for accepting SAML 2.0 Logout
-	 * Requests from the asserting party
-	 * @param logoutSuccessHandler the success handler to be run after the logout request
-	 * passes validation and other logout operations succeed. This success handler will
-	 * typically be one that issues a SAML 2.0 Logout Response to the asserting party,
-	 * like {@link Saml2LogoutResponseSuccessHandler}
-	 * @param logoutHandler the handler for handling the logout request, may be a
-	 * {@link org.springframework.security.web.authentication.logout.CompositeLogoutHandler}
-	 * that handles other logout concerns
-	 */
-	public Saml2LogoutRequestFilter(LogoutSuccessHandler logoutSuccessHandler, LogoutHandler logoutHandler) {
-		this.logoutSuccessHandler = logoutSuccessHandler;
-		this.logoutHandler = logoutHandler;
-	}
-
-	@Override
-	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
-			throws ServletException, IOException {
-
-		if (!this.logoutRequestMatcher.matches(request)) {
-			chain.doFilter(request, response);
-			return;
-		}
-
-		if (request.getParameter("SAMLRequest") == null) {
-			chain.doFilter(request, response);
-			return;
-		}
-
-		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
-		this.logoutHandler.logout(request, response, authentication);
-		this.logoutSuccessHandler.onLogoutSuccess(request, response, authentication);
-	}
-
-	public void setLogoutRequestMatcher(RequestMatcher logoutRequestMatcher) {
-		Assert.notNull(logoutRequestMatcher, "logoutRequestMatcher cannot be null");
-		this.logoutRequestMatcher = logoutRequestMatcher;
-	}
-
-}

+ 0 - 68
saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutRequestRepository.java

@@ -1,68 +0,0 @@
-/*
- * Copyright 2002-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.provider.service.web.authentication.logout;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutRequest;
-
-/**
- * Implementations of this interface are responsible for the persistence of
- * {@link Saml2LogoutRequest} between requests.
- *
- * <p>
- * Used by the {@link Saml2LogoutRequestSuccessHandler} for persisting the Logout Request
- * before it initiates the SAML 2.0 SLO flow. As well, used by
- * {@link OpenSamlLogoutResponseHandler} for resolving the Logout Request associated with
- * that Logout Response.
- *
- * @author Josh Cummings
- * @since 5.5
- * @see Saml2LogoutRequest
- * @see HttpSessionLogoutRequestRepository
- */
-public interface Saml2LogoutRequestRepository {
-
-	/**
-	 * Returns the {@link Saml2LogoutRequest} associated to the provided
-	 * {@code HttpServletRequest} or {@code null} if not available.
-	 * @param request the {@code HttpServletRequest}
-	 * @return the {@link Saml2LogoutRequest} or {@code null} if not available
-	 */
-	Saml2LogoutRequest loadLogoutRequest(HttpServletRequest request);
-
-	/**
-	 * Persists the {@link Saml2LogoutRequest} associating it to the provided
-	 * {@code HttpServletRequest} and/or {@code HttpServletResponse}.
-	 * @param logoutRequest the {@link Saml2LogoutRequest}
-	 * @param request the {@code HttpServletRequest}
-	 * @param response the {@code HttpServletResponse}
-	 */
-	void saveLogoutRequest(Saml2LogoutRequest logoutRequest, HttpServletRequest request, HttpServletResponse response);
-
-	/**
-	 * Removes and returns the {@link Saml2LogoutRequest} associated to the provided
-	 * {@code HttpServletRequest} and {@code HttpServletResponse} or if not available
-	 * returns {@code null}.
-	 * @param request the {@code HttpServletRequest}
-	 * @param response the {@code HttpServletResponse}
-	 * @return the {@link Saml2LogoutRequest} or {@code null} if not available
-	 */
-	Saml2LogoutRequest removeLogoutRequest(HttpServletRequest request, HttpServletResponse response);
-
-}

+ 0 - 82
saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutRequestResolver.java

@@ -1,82 +0,0 @@
-/*
- * Copyright 2002-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.provider.service.web.authentication.logout;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.springframework.security.core.Authentication;
-import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutRequest;
-import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
-
-/**
- * Creates a signed SAML 2.0 Logout Request based on information from the
- * {@link HttpServletRequest} and current {@link Authentication}.
- *
- * The returned logout request is suitable for sending to the asserting party based on,
- * for example, the location and binding specified in
- * {@link RelyingPartyRegistration#getAssertingPartyDetails()}.
- *
- * @author Josh Cummings
- * @since 5.5
- * @see RelyingPartyRegistration
- */
-public interface Saml2LogoutRequestResolver {
-
-	/**
-	 * Prepare to create, sign, and serialize a SAML 2.0 Logout Request.
-	 *
-	 * By default, includes a {@code NameID} based on the {@link Authentication} instance.
-	 * @param request the HTTP request
-	 * @param authentication the current principal details
-	 * @return a builder, useful for overriding any aspects of the SAML 2.0 Logout Request
-	 * that the resolver supplied
-	 */
-	Saml2LogoutRequestBuilder<?> resolveLogoutRequest(HttpServletRequest request, Authentication authentication);
-
-	/**
-	 * A partial application, useful for overriding any aspects of the SAML 2.0 Logout
-	 * Request that the resolver supplied.
-	 *
-	 * The request returned from the {@link #logoutRequest()} method is signed and
-	 * serialized
-	 */
-	interface Saml2LogoutRequestBuilder<P extends Saml2LogoutRequestBuilder<P>> {
-
-		/**
-		 * Use the given name in the SAML 2.0 Logout Request
-		 * @param name the name to use
-		 * @return the {@link Saml2LogoutRequestBuilder} for further customizations
-		 */
-		P name(String name);
-
-		/**
-		 * Use this relay state when sending the logout response
-		 * @param relayState the relay state to use
-		 * @return the {@link Saml2LogoutRequestBuilder} for further customizations
-		 */
-		P relayState(String relayState);
-
-		/**
-		 * Return a signed and serialized SAML 2.0 Logout Request and associated signed
-		 * request parameters
-		 * @return a signed and serialized SAML 2.0 Logout Request
-		 */
-		Saml2LogoutRequest logoutRequest();
-
-	}
-
-}

+ 0 - 159
saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutRequestSuccessHandler.java

@@ -1,159 +0,0 @@
-/*
- * Copyright 2002-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.provider.service.web.authentication.logout;
-
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.springframework.http.MediaType;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutRequest;
-import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
-import org.springframework.security.web.DefaultRedirectStrategy;
-import org.springframework.security.web.RedirectStrategy;
-import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
-import org.springframework.util.Assert;
-import org.springframework.util.StringUtils;
-import org.springframework.web.util.HtmlUtils;
-import org.springframework.web.util.UriComponentsBuilder;
-import org.springframework.web.util.UriUtils;
-
-/**
- * A success handler for issuing a SAML 2.0 Logout Response in response to the SAML 2.0
- * Logout Request that the SAML 2.0 Asserting Party sent
- *
- * @author Josh Cummings
- * @since 5.5
- */
-public final class Saml2LogoutRequestSuccessHandler implements LogoutSuccessHandler {
-
-	private final Saml2LogoutRequestResolver logoutRequestResolver;
-
-	private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
-
-	private Saml2LogoutRequestRepository logoutRequestRepository = new HttpSessionLogoutRequestRepository();
-
-	/**
-	 * Constructs a {@link Saml2LogoutRequestSuccessHandler} using the provided parameters
-	 * @param logoutRequestResolver the {@link Saml2LogoutRequestResolver} to use
-	 */
-	public Saml2LogoutRequestSuccessHandler(Saml2LogoutRequestResolver logoutRequestResolver) {
-		this.logoutRequestResolver = logoutRequestResolver;
-	}
-
-	/**
-	 * Produce and send a SAML 2.0 Logout Response based on the SAML 2.0 Logout Request
-	 * received from the asserting party
-	 * @param request the HTTP request
-	 * @param response the HTTP response
-	 * @param authentication the current principal details
-	 * @throws IOException when failing to write to the response
-	 */
-	@Override
-	public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
-			throws IOException {
-		Saml2LogoutRequestResolver.Saml2LogoutRequestBuilder<?> builder = this.logoutRequestResolver
-				.resolveLogoutRequest(request, authentication);
-		if (builder == null) {
-			return;
-		}
-		Saml2LogoutRequest logoutRequest = builder.logoutRequest();
-		this.logoutRequestRepository.saveLogoutRequest(logoutRequest, request, response);
-		if (logoutRequest.getBinding() == Saml2MessageBinding.REDIRECT) {
-			doRedirect(request, response, logoutRequest);
-		}
-		else {
-			doPost(response, logoutRequest);
-		}
-	}
-
-	public void setLogoutRequestRepository(Saml2LogoutRequestRepository logoutRequestRepository) {
-		Assert.notNull(logoutRequestRepository, "logoutRequestRepository cannot be null");
-		this.logoutRequestRepository = logoutRequestRepository;
-	}
-
-	private void doRedirect(HttpServletRequest request, HttpServletResponse response, Saml2LogoutRequest logoutRequest)
-			throws IOException {
-		String location = logoutRequest.getLocation();
-		UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(location);
-		addParameter("SAMLRequest", logoutRequest, uriBuilder);
-		addParameter("RelayState", logoutRequest, uriBuilder);
-		addParameter("SigAlg", logoutRequest, uriBuilder);
-		addParameter("Signature", logoutRequest, uriBuilder);
-		this.redirectStrategy.sendRedirect(request, response, uriBuilder.build(true).toUriString());
-	}
-
-	private void addParameter(String name, Saml2LogoutRequest logoutRequest, UriComponentsBuilder builder) {
-		Assert.hasText(name, "name cannot be empty or null");
-		if (StringUtils.hasText(logoutRequest.getParameter(name))) {
-			builder.queryParam(UriUtils.encode(name, StandardCharsets.ISO_8859_1),
-					UriUtils.encode(logoutRequest.getParameter(name), StandardCharsets.ISO_8859_1));
-		}
-	}
-
-	private void doPost(HttpServletResponse response, Saml2LogoutRequest logoutRequest) throws IOException {
-		String html = createSamlPostRequestFormData(logoutRequest);
-		response.setContentType(MediaType.TEXT_HTML_VALUE);
-		response.getWriter().write(html);
-	}
-
-	private String createSamlPostRequestFormData(Saml2LogoutRequest logoutRequest) {
-		String location = logoutRequest.getLocation();
-		String samlRequest = logoutRequest.getSamlRequest();
-		String relayState = logoutRequest.getRelayState();
-		StringBuilder html = new StringBuilder();
-		html.append("<!DOCTYPE html>\n");
-		html.append("<html>\n").append("    <head>\n");
-		html.append("        <meta charset=\"utf-8\" />\n");
-		html.append("    </head>\n");
-		html.append("    <body onload=\"document.forms[0].submit()\">\n");
-		html.append("        <noscript>\n");
-		html.append("            <p>\n");
-		html.append("                <strong>Note:</strong> Since your browser does not support JavaScript,\n");
-		html.append("                you must press the Continue button once to proceed.\n");
-		html.append("            </p>\n");
-		html.append("        </noscript>\n");
-		html.append("        \n");
-		html.append("        <form action=\"");
-		html.append(location);
-		html.append("\" method=\"post\">\n");
-		html.append("            <div>\n");
-		html.append("                <input type=\"hidden\" name=\"SAMLRequest\" value=\"");
-		html.append(HtmlUtils.htmlEscape(samlRequest));
-		html.append("\"/>\n");
-		if (StringUtils.hasText(relayState)) {
-			html.append("                <input type=\"hidden\" name=\"RelayState\" value=\"");
-			html.append(HtmlUtils.htmlEscape(relayState));
-			html.append("\"/>\n");
-		}
-		html.append("            </div>\n");
-		html.append("            <noscript>\n");
-		html.append("                <div>\n");
-		html.append("                    <input type=\"submit\" value=\"Continue\"/>\n");
-		html.append("                </div>\n");
-		html.append("            </noscript>\n");
-		html.append("        </form>\n");
-		html.append("        \n");
-		html.append("    </body>\n");
-		html.append("</html>");
-		return html.toString();
-	}
-
-}

+ 0 - 117
saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutResponseFilter.java

@@ -1,117 +0,0 @@
-/*
- * Copyright 2002-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.provider.service.web.authentication.logout;
-
-import java.io.IOException;
-
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.web.authentication.logout.CompositeLogoutHandler;
-import org.springframework.security.web.authentication.logout.LogoutHandler;
-import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
-import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
-import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
-import org.springframework.security.web.util.matcher.RequestMatcher;
-import org.springframework.util.Assert;
-import org.springframework.web.filter.OncePerRequestFilter;
-
-/**
- * A filter for handling a &lt;saml2:LogoutResponse&gt; sent from the asserting party. A
- * &lt;saml2:LogoutResponse&gt; is sent in response to a &lt;saml2:LogoutRequest&gt;
- * already sent by the relying party.
- *
- * Note that before a &lt;saml2:LogoutRequest&gt; is sent, the user is logged out. Given
- * that, this implementation should not use any {@link LogoutHandler} or
- * {@link LogoutSuccessHandler} that rely on the user being logged in.
- *
- * @author Josh Cummings
- * @since 5.5
- */
-public final class Saml2LogoutResponseFilter extends OncePerRequestFilter {
-
-	private static final String DEFAULT_LOGOUT_ENDPOINT = "/logout/saml2/slo";
-
-	private RequestMatcher logoutRequestMatcher = new AntPathRequestMatcher(DEFAULT_LOGOUT_ENDPOINT);
-
-	private final LogoutHandler logoutHandler;
-
-	private LogoutSuccessHandler logoutSuccessHandler = new SimpleUrlLogoutSuccessHandler();
-
-	/**
-	 * Constructs a {@link Saml2LogoutResponseFilter} for accepting SAML 2.0 Logout
-	 * Responses from the asserting party
-	 * @param logoutHandler the handlers for handling the logout response
-	 */
-	public Saml2LogoutResponseFilter(LogoutHandler logoutHandler) {
-		this.logoutHandler = new CompositeLogoutHandler(logoutHandler);
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	@Override
-	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
-			throws ServletException, IOException {
-
-		if (!this.logoutRequestMatcher.matches(request)) {
-			chain.doFilter(request, response);
-			return;
-		}
-
-		if (request.getParameter("SAMLResponse") == null) {
-			chain.doFilter(request, response);
-			return;
-		}
-
-		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
-		this.logoutHandler.logout(request, response, authentication);
-		this.logoutSuccessHandler.onLogoutSuccess(request, response, authentication);
-	}
-
-	/**
-	 * Use this {@link RequestMatcher} for requests
-	 *
-	 * This is handy when your asserting party needs it to be a specific endpoint instead
-	 * of the default.
-	 * @param logoutRequestMatcher the {@link RequestMatcher} to use
-	 */
-	public void setLogoutRequestMatcher(RequestMatcher logoutRequestMatcher) {
-		Assert.notNull(logoutRequestMatcher, "logoutRequestMatcher cannot be null");
-		this.logoutRequestMatcher = logoutRequestMatcher;
-	}
-
-	/**
-	 * Use this {@link LogoutSuccessHandler} when complete
-	 *
-	 * Note that when a &lt;saml2:LogoutResponse&gt; is received, the end user is already
-	 * logged out. Any {@link LogoutSuccessHandler} used here should not rely on the
-	 * {@link Authentication}. {@link SimpleUrlLogoutSuccessHandler} is an example of
-	 * this.
-	 * @param logoutSuccessHandler the {@link LogoutSuccessHandler} to use
-	 * @see SimpleUrlLogoutSuccessHandler
-	 */
-	public void setLogoutSuccessHandler(LogoutSuccessHandler logoutSuccessHandler) {
-		Assert.notNull(logoutSuccessHandler, "logoutSuccessHandler cannot be null");
-		this.logoutSuccessHandler = logoutSuccessHandler;
-	}
-
-}

+ 0 - 90
saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutResponseResolver.java

@@ -1,90 +0,0 @@
-/*
- * Copyright 2002-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.provider.service.web.authentication.logout;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.springframework.security.core.Authentication;
-import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutResponse;
-import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
-
-/**
- * Creates a signed SAML 2.0 Logout Response based on information from the
- * {@link HttpServletRequest} and current {@link Authentication}.
- *
- * The returned logout response is suitable for sending to the asserting party based on,
- * for example, the location and binding specified in
- * {@link RelyingPartyRegistration#getAssertingPartyDetails()}.
- *
- * @author Josh Cummings
- * @since 5.5
- * @see RelyingPartyRegistration
- */
-public interface Saml2LogoutResponseResolver {
-
-	/**
-	 * Prepare to create, sign, and serialize a SAML 2.0 Logout Response.
-	 * @param request the HTTP request
-	 * @param authentication the current principal details
-	 * @return a builder, useful for overriding any aspects of the SAML 2.0 Logout
-	 * Response that the resolver supplied
-	 */
-	Saml2LogoutResponseBuilder<?> resolveLogoutResponse(HttpServletRequest request, Authentication authentication);
-
-	/**
-	 * A partial application, useful for overriding any aspects of the SAML 2.0 Logout
-	 * Response that the resolver supplied.
-	 *
-	 * The response returned from the {@link #logoutResponse()} method is signed and
-	 * serialized
-	 */
-	interface Saml2LogoutResponseBuilder<P extends Saml2LogoutResponseBuilder<P>> {
-
-		/**
-		 * Use this value as the {@code InResponseTo} identifier for the associated SAML
-		 * 2.0 Logout Request
-		 * @param name the logout request identifier
-		 * @return the {@link Saml2LogoutResponseBuilder} for further customizations
-		 */
-		P inResponseTo(String name);
-
-		/**
-		 * Use this status code in the logout response.
-		 *
-		 * The default is {@code SUCCESS}.
-		 * @param status the status code to use
-		 * @return the {@link Saml2LogoutResponseBuilder} for further customizations
-		 */
-		P status(String status);
-
-		/**
-		 * Use this relay state when sending the logout response
-		 * @param relayState the relay state to use
-		 * @return the {@link Saml2LogoutResponseBuilder} for further customizations
-		 */
-		P relayState(String relayState);
-
-		/**
-		 * Return a signed and serialized SAML 2.0 Logout Response and associated signed
-		 * request parameters
-		 * @return a signed and serialized SAML 2.0 Logout Response
-		 */
-		Saml2LogoutResponse logoutResponse();
-
-	}
-
-}

+ 0 - 148
saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutResponseSuccessHandler.java

@@ -1,148 +0,0 @@
-/*
- * Copyright 2002-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.provider.service.web.authentication.logout;
-
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.springframework.http.MediaType;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutResponse;
-import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
-import org.springframework.security.web.DefaultRedirectStrategy;
-import org.springframework.security.web.RedirectStrategy;
-import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
-import org.springframework.util.Assert;
-import org.springframework.util.StringUtils;
-import org.springframework.web.util.HtmlUtils;
-import org.springframework.web.util.UriComponentsBuilder;
-import org.springframework.web.util.UriUtils;
-
-/**
- * A success handler for issuing a SAML 2.0 Logout Response in response to the SAML 2.0
- * Logout Request that the SAML 2.0 Asserting Party sent
- *
- * @author Josh Cummings
- * @since 5.5
- */
-public final class Saml2LogoutResponseSuccessHandler implements LogoutSuccessHandler {
-
-	private final Saml2LogoutResponseResolver logoutResponseResolver;
-
-	private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
-
-	/**
-	 * Constructs a {@link Saml2LogoutResponseSuccessHandler} using the provided
-	 * parameters
-	 * @param logoutResponseResolver the {@link Saml2LogoutResponseResolver} to use
-	 */
-	public Saml2LogoutResponseSuccessHandler(Saml2LogoutResponseResolver logoutResponseResolver) {
-		this.logoutResponseResolver = logoutResponseResolver;
-	}
-
-	/**
-	 * Produce and send a SAML 2.0 Logout Response based on the SAML 2.0 Logout Request
-	 * received from the asserting party
-	 * @param request the HTTP request
-	 * @param response the HTTP response
-	 * @param authentication the current principal details
-	 * @throws IOException when failing to write to the response
-	 */
-	@Override
-	public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
-			throws IOException {
-		Saml2LogoutResponse logoutResponse = this.logoutResponseResolver.resolveLogoutResponse(request, authentication)
-				.logoutResponse();
-		if (logoutResponse.getBinding() == Saml2MessageBinding.REDIRECT) {
-			doRedirect(request, response, logoutResponse);
-		}
-		else {
-			doPost(response, logoutResponse);
-		}
-	}
-
-	private void doRedirect(HttpServletRequest request, HttpServletResponse response,
-			Saml2LogoutResponse logoutResponse) throws IOException {
-		String location = logoutResponse.getResponseLocation();
-		UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(location);
-		addParameter("SAMLResponse", logoutResponse, uriBuilder);
-		addParameter("RelayState", logoutResponse, uriBuilder);
-		addParameter("SigAlg", logoutResponse, uriBuilder);
-		addParameter("Signature", logoutResponse, uriBuilder);
-		this.redirectStrategy.sendRedirect(request, response, uriBuilder.build(true).toUriString());
-	}
-
-	private void addParameter(String name, Saml2LogoutResponse logoutResponse, UriComponentsBuilder builder) {
-		Assert.hasText(name, "name cannot be empty or null");
-		if (StringUtils.hasText(logoutResponse.getParameter(name))) {
-			builder.queryParam(UriUtils.encode(name, StandardCharsets.ISO_8859_1),
-					UriUtils.encode(logoutResponse.getParameter(name), StandardCharsets.ISO_8859_1));
-		}
-	}
-
-	private void doPost(HttpServletResponse response, Saml2LogoutResponse logoutResponse) throws IOException {
-		String html = createSamlPostRequestFormData(logoutResponse);
-		response.setContentType(MediaType.TEXT_HTML_VALUE);
-		response.getWriter().write(html);
-	}
-
-	private String createSamlPostRequestFormData(Saml2LogoutResponse logoutResponse) {
-		String location = logoutResponse.getResponseLocation();
-		String samlRequest = logoutResponse.getSamlResponse();
-		String relayState = logoutResponse.getRelayState();
-		StringBuilder html = new StringBuilder();
-		html.append("<!DOCTYPE html>\n");
-		html.append("<html>\n").append("    <head>\n");
-		html.append("        <meta charset=\"utf-8\" />\n");
-		html.append("    </head>\n");
-		html.append("    <body onload=\"document.forms[0].submit()\">\n");
-		html.append("        <noscript>\n");
-		html.append("            <p>\n");
-		html.append("                <strong>Note:</strong> Since your browser does not support JavaScript,\n");
-		html.append("                you must press the Continue button once to proceed.\n");
-		html.append("            </p>\n");
-		html.append("        </noscript>\n");
-		html.append("        \n");
-		html.append("        <form action=\"");
-		html.append(location);
-		html.append("\" method=\"post\">\n");
-		html.append("            <div>\n");
-		html.append("                <input type=\"hidden\" name=\"SAMLResponse\" value=\"");
-		html.append(HtmlUtils.htmlEscape(samlRequest));
-		html.append("\"/>\n");
-		if (StringUtils.hasText(relayState)) {
-			html.append("                <input type=\"hidden\" name=\"RelayState\" value=\"");
-			html.append(HtmlUtils.htmlEscape(relayState));
-			html.append("\"/>\n");
-		}
-		html.append("            </div>\n");
-		html.append("            <noscript>\n");
-		html.append("                <div>\n");
-		html.append("                    <input type=\"submit\" value=\"Continue\"/>\n");
-		html.append("                </div>\n");
-		html.append("            </noscript>\n");
-		html.append("        </form>\n");
-		html.append("        \n");
-		html.append("    </body>\n");
-		html.append("</html>");
-		return html.toString();
-	}
-
-}

+ 0 - 35
saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2RequestAttributeNames.java

@@ -1,35 +0,0 @@
-/*
- * Copyright 2002-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.provider.service.web.authentication.logout;
-
-/**
- * Attribute names for coordinating between SAML 2.0 Logout components.
- *
- * For internal use only.
- *
- * @author Josh Cummings
- */
-
-final class Saml2RequestAttributeNames {
-
-	static final String LOGOUT_REQUEST_ID = Saml2RequestAttributeNames.class.getName() + "_LOGOUT_REQUEST_ID";
-
-	private Saml2RequestAttributeNames() {
-
-	}
-
-}

+ 0 - 79
saml2/saml2-service-provider/core/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2Utils.java

@@ -1,79 +0,0 @@
-/*
- * Copyright 2002-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.provider.service.web.authentication.logout;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.util.zip.Deflater;
-import java.util.zip.DeflaterOutputStream;
-import java.util.zip.Inflater;
-import java.util.zip.InflaterOutputStream;
-
-import org.apache.commons.codec.binary.Base64;
-
-import org.springframework.security.saml2.Saml2Exception;
-
-/**
- * Utility methods for working with serialized SAML messages.
- *
- * For internal use only.
- *
- * @author Josh Cummings
- */
-final class Saml2Utils {
-
-	private static Base64 BASE64 = new Base64(0, new byte[] { '\n' });
-
-	private Saml2Utils() {
-	}
-
-	static String samlEncode(byte[] b) {
-		return BASE64.encodeAsString(b);
-	}
-
-	static byte[] samlDecode(String s) {
-		return BASE64.decode(s);
-	}
-
-	static byte[] samlDeflate(String s) {
-		try {
-			ByteArrayOutputStream b = new ByteArrayOutputStream();
-			DeflaterOutputStream deflater = new DeflaterOutputStream(b, new Deflater(Deflater.DEFLATED, true));
-			deflater.write(s.getBytes(StandardCharsets.UTF_8));
-			deflater.finish();
-			return b.toByteArray();
-		}
-		catch (IOException ex) {
-			throw new Saml2Exception("Unable to deflate string", ex);
-		}
-	}
-
-	static String samlInflate(byte[] b) {
-		try {
-			ByteArrayOutputStream out = new ByteArrayOutputStream();
-			InflaterOutputStream iout = new InflaterOutputStream(out, new Inflater(true));
-			iout.write(b);
-			iout.finish();
-			return new String(out.toByteArray(), StandardCharsets.UTF_8);
-		}
-		catch (IOException ex) {
-			throw new Saml2Exception("Unable to inflate string", ex);
-		}
-	}
-
-}

+ 2 - 44
saml2/saml2-service-provider/core/src/test/java/org/springframework/security/saml2/provider/service/authentication/TestOpenSamlObjects.java

@@ -54,8 +54,6 @@ import org.opensaml.saml.saml2.core.EncryptedAssertion;
 import org.opensaml.saml.saml2.core.EncryptedAttribute;
 import org.opensaml.saml.saml2.core.EncryptedAttribute;
 import org.opensaml.saml.saml2.core.EncryptedID;
 import org.opensaml.saml.saml2.core.EncryptedID;
 import org.opensaml.saml.saml2.core.Issuer;
 import org.opensaml.saml.saml2.core.Issuer;
-import org.opensaml.saml.saml2.core.LogoutRequest;
-import org.opensaml.saml.saml2.core.LogoutResponse;
 import org.opensaml.saml.saml2.core.NameID;
 import org.opensaml.saml.saml2.core.NameID;
 import org.opensaml.saml.saml2.core.Response;
 import org.opensaml.saml.saml2.core.Response;
 import org.opensaml.saml.saml2.core.Status;
 import org.opensaml.saml.saml2.core.Status;
@@ -65,10 +63,6 @@ import org.opensaml.saml.saml2.core.SubjectConfirmation;
 import org.opensaml.saml.saml2.core.SubjectConfirmationData;
 import org.opensaml.saml.saml2.core.SubjectConfirmationData;
 import org.opensaml.saml.saml2.core.impl.AttributeBuilder;
 import org.opensaml.saml.saml2.core.impl.AttributeBuilder;
 import org.opensaml.saml.saml2.core.impl.AttributeStatementBuilder;
 import org.opensaml.saml.saml2.core.impl.AttributeStatementBuilder;
-import org.opensaml.saml.saml2.core.impl.IssuerBuilder;
-import org.opensaml.saml.saml2.core.impl.LogoutRequestBuilder;
-import org.opensaml.saml.saml2.core.impl.LogoutResponseBuilder;
-import org.opensaml.saml.saml2.core.impl.NameIDBuilder;
 import org.opensaml.saml.saml2.core.impl.StatusBuilder;
 import org.opensaml.saml.saml2.core.impl.StatusBuilder;
 import org.opensaml.saml.saml2.core.impl.StatusCodeBuilder;
 import org.opensaml.saml.saml2.core.impl.StatusCodeBuilder;
 import org.opensaml.saml.saml2.encryption.Encrypter;
 import org.opensaml.saml.saml2.encryption.Encrypter;
@@ -89,7 +83,6 @@ import org.springframework.security.saml2.Saml2Exception;
 import org.springframework.security.saml2.core.OpenSamlInitializationService;
 import org.springframework.security.saml2.core.OpenSamlInitializationService;
 import org.springframework.security.saml2.core.Saml2X509Credential;
 import org.springframework.security.saml2.core.Saml2X509Credential;
 import org.springframework.security.saml2.core.TestSaml2X509Credentials;
 import org.springframework.security.saml2.core.TestSaml2X509Credentials;
-import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
 
 
 public final class TestOpenSamlObjects {
 public final class TestOpenSamlObjects {
 
 
@@ -100,7 +93,7 @@ public final class TestOpenSamlObjects {
 
 
 	private static String DESTINATION = "https://localhost/login/saml2/sso/idp-alias";
 	private static String DESTINATION = "https://localhost/login/saml2/sso/idp-alias";
 
 
-	public static String RELYING_PARTY_ENTITY_ID = "https://localhost/saml2/service-provider-metadata/idp-alias";
+	private static String RELYING_PARTY_ENTITY_ID = "https://localhost/saml2/service-provider-metadata/idp-alias";
 
 
 	private static String ASSERTING_PARTY_ENTITY_ID = "https://some.idp.test/saml2/idp";
 	private static String ASSERTING_PARTY_ENTITY_ID = "https://some.idp.test/saml2/idp";
 
 
@@ -228,7 +221,7 @@ public final class TestOpenSamlObjects {
 		return signable;
 		return signable;
 	}
 	}
 
 
-	public static <T extends SignableSAMLObject> T signed(T signable, Saml2X509Credential credential, String entityId) {
+	static <T extends SignableSAMLObject> T signed(T signable, Saml2X509Credential credential, String entityId) {
 		return signed(signable, credential, entityId, SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256);
 		return signed(signable, credential, entityId, SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256);
 	}
 	}
 
 
@@ -349,41 +342,6 @@ public final class TestOpenSamlObjects {
 		return status;
 		return status;
 	}
 	}
 
 
-	public static LogoutRequest assertingPartyLogoutRequest(RelyingPartyRegistration registration) {
-		LogoutRequestBuilder logoutRequestBuilder = new LogoutRequestBuilder();
-		LogoutRequest logoutRequest = logoutRequestBuilder.buildObject();
-		logoutRequest.setID("id");
-		NameIDBuilder nameIdBuilder = new NameIDBuilder();
-		NameID nameId = nameIdBuilder.buildObject();
-		nameId.setValue("user");
-		logoutRequest.setNameID(nameId);
-		IssuerBuilder issuerBuilder = new IssuerBuilder();
-		Issuer issuer = issuerBuilder.buildObject();
-		issuer.setValue(registration.getAssertingPartyDetails().getEntityId());
-		logoutRequest.setIssuer(issuer);
-		logoutRequest.setDestination(registration.getSingleLogoutServiceLocation());
-		return logoutRequest;
-	}
-
-	public static LogoutResponse assertingPartyLogoutResponse(RelyingPartyRegistration registration) {
-		LogoutResponseBuilder logoutResponseBuilder = new LogoutResponseBuilder();
-		LogoutResponse logoutResponse = logoutResponseBuilder.buildObject();
-		logoutResponse.setID("id");
-		StatusBuilder statusBuilder = new StatusBuilder();
-		StatusCodeBuilder statusCodeBuilder = new StatusCodeBuilder();
-		StatusCode code = statusCodeBuilder.buildObject();
-		code.setValue(StatusCode.SUCCESS);
-		Status status = statusBuilder.buildObject();
-		status.setStatusCode(code);
-		logoutResponse.setStatus(status);
-		IssuerBuilder issuerBuilder = new IssuerBuilder();
-		Issuer issuer = issuerBuilder.buildObject();
-		issuer.setValue(registration.getAssertingPartyDetails().getEntityId());
-		logoutResponse.setIssuer(issuer);
-		logoutResponse.setDestination(registration.getSingleLogoutServiceResponseLocation());
-		return logoutResponse;
-	}
-
 	static <T extends XMLObject> T build(QName qName) {
 	static <T extends XMLObject> T build(QName qName) {
 		return (T) XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(qName).buildObject(qName);
 		return (T) XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(qName).buildObject(qName);
 	}
 	}

+ 2 - 4
saml2/saml2-service-provider/core/src/test/java/org/springframework/security/saml2/provider/service/metadata/OpenSamlMetadataResolverTests.java

@@ -41,8 +41,7 @@ public class OpenSamlMetadataResolverTests {
 				.contains("<md:KeyDescriptor use=\"encryption\">")
 				.contains("<md:KeyDescriptor use=\"encryption\">")
 				.contains("<ds:X509Certificate>MIICgTCCAeoCCQCuVzyqFgMSyDANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBh")
 				.contains("<ds:X509Certificate>MIICgTCCAeoCCQCuVzyqFgMSyDANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBh")
 				.contains("Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\"")
 				.contains("Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\"")
-				.contains("Location=\"https://rp.example.org/acs\" index=\"1\"")
-				.contains("ResponseLocation=\"https://rp.example.org/logout/saml2/response\"");
+				.contains("Location=\"https://rp.example.org/acs\" index=\"1\"");
 	}
 	}
 
 
 	@Test
 	@Test
@@ -57,8 +56,7 @@ public class OpenSamlMetadataResolverTests {
 				.contains("WantAssertionsSigned=\"true\"").doesNotContain("<md:KeyDescriptor use=\"signing\">")
 				.contains("WantAssertionsSigned=\"true\"").doesNotContain("<md:KeyDescriptor use=\"signing\">")
 				.doesNotContain("<md:KeyDescriptor use=\"encryption\">")
 				.doesNotContain("<md:KeyDescriptor use=\"encryption\">")
 				.contains("Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST\"")
 				.contains("Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST\"")
-				.contains("Location=\"https://rp.example.org/acs\" index=\"1\"")
-				.contains("ResponseLocation=\"https://rp.example.org/logout/saml2/response\"");
+				.contains("Location=\"https://rp.example.org/acs\" index=\"1\"");
 	}
 	}
 
 
 }
 }

+ 3 - 9
saml2/saml2-service-provider/core/src/test/java/org/springframework/security/saml2/provider/service/registration/TestRelyingPartyRegistrations.java

@@ -37,23 +37,17 @@ public final class TestRelyingPartyRegistrations {
 		String apEntityId = "https://simplesaml-for-spring-saml.apps.pcfone.io/saml2/idp/metadata.php";
 		String apEntityId = "https://simplesaml-for-spring-saml.apps.pcfone.io/saml2/idp/metadata.php";
 		Saml2X509Credential verificationCertificate = TestSaml2X509Credentials.relyingPartyVerifyingCredential();
 		Saml2X509Credential verificationCertificate = TestSaml2X509Credentials.relyingPartyVerifyingCredential();
 		String singleSignOnServiceLocation = "https://simplesaml-for-spring-saml.apps.pcfone.io/saml2/idp/SSOService.php";
 		String singleSignOnServiceLocation = "https://simplesaml-for-spring-saml.apps.pcfone.io/saml2/idp/SSOService.php";
-		String singleLogoutServiceLocation = "{baseUrl}/logout/saml2/slo";
 		return RelyingPartyRegistration.withRegistrationId(registrationId).entityId(rpEntityId)
 		return RelyingPartyRegistration.withRegistrationId(registrationId).entityId(rpEntityId)
 				.assertionConsumerServiceLocation(assertionConsumerServiceLocation)
 				.assertionConsumerServiceLocation(assertionConsumerServiceLocation)
-				.singleLogoutServiceLocation(singleLogoutServiceLocation).credentials((c) -> c.add(signingCredential))
+				.credentials((c) -> c.add(signingCredential))
 				.providerDetails((c) -> c.entityId(apEntityId).webSsoUrl(singleSignOnServiceLocation))
 				.providerDetails((c) -> c.entityId(apEntityId).webSsoUrl(singleSignOnServiceLocation))
 				.credentials((c) -> c.add(verificationCertificate));
 				.credentials((c) -> c.add(verificationCertificate));
 	}
 	}
 
 
 	public static RelyingPartyRegistration.Builder noCredentials() {
 	public static RelyingPartyRegistration.Builder noCredentials() {
 		return RelyingPartyRegistration.withRegistrationId("registration-id").entityId("rp-entity-id")
 		return RelyingPartyRegistration.withRegistrationId("registration-id").entityId("rp-entity-id")
-				.singleLogoutServiceLocation("https://rp.example.org/logout/saml2/request")
-				.singleLogoutServiceResponseLocation("https://rp.example.org/logout/saml2/response")
-				.assertionConsumerServiceLocation("https://rp.example.org/acs")
-				.assertingPartyDetails((party) -> party.entityId("ap-entity-id")
-						.singleSignOnServiceLocation("https://ap.example.org/sso")
-						.singleLogoutServiceLocation("https://ap.example.org/logout/saml2/request")
-						.singleLogoutServiceResponseLocation("https://ap.example.org/logout/saml2/response"));
+				.assertionConsumerServiceLocation("https://rp.example.org/acs").assertingPartyDetails((party) -> party
+						.entityId("ap-entity-id").singleSignOnServiceLocation("https://ap.example.org/sso"));
 	}
 	}
 
 
 	public static RelyingPartyRegistration.Builder full() {
 	public static RelyingPartyRegistration.Builder full() {

+ 0 - 3
saml2/saml2-service-provider/core/src/test/java/org/springframework/security/saml2/provider/service/web/DefaultRelyingPartyRegistrationResolverTests.java

@@ -52,9 +52,6 @@ public class DefaultRelyingPartyRegistrationResolverTests {
 				.isEqualTo("http://localhost/saml2/service-provider-metadata/" + this.registration.getRegistrationId());
 				.isEqualTo("http://localhost/saml2/service-provider-metadata/" + this.registration.getRegistrationId());
 		assertThat(registration.getAssertionConsumerServiceLocation())
 		assertThat(registration.getAssertionConsumerServiceLocation())
 				.isEqualTo("http://localhost/login/saml2/sso/" + this.registration.getRegistrationId());
 				.isEqualTo("http://localhost/login/saml2/sso/" + this.registration.getRegistrationId());
-		assertThat(registration.getSingleLogoutServiceLocation()).isEqualTo("http://localhost/logout/saml2/slo");
-		assertThat(registration.getSingleLogoutServiceResponseLocation())
-				.isEqualTo("http://localhost/logout/saml2/slo");
 	}
 	}
 
 
 	@Test
 	@Test

+ 0 - 242
saml2/saml2-service-provider/core/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/HttpSessionLogoutRequestRepositoryTests.java

@@ -1,242 +0,0 @@
-/*
- * Copyright 2002-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.provider.service.web.authentication.logout;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.junit.Test;
-
-import org.springframework.mock.web.MockHttpServletRequest;
-import org.springframework.mock.web.MockHttpServletResponse;
-import org.springframework.mock.web.MockHttpSession;
-import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutRequest;
-import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
-import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
-
-/**
- * Tests for {@link HttpSessionLogoutRequestRepository}
- */
-public class HttpSessionLogoutRequestRepositoryTests {
-
-	private HttpSessionLogoutRequestRepository logoutRequestRepository = new HttpSessionLogoutRequestRepository();
-
-	@Test
-	public void loadLogoutRequestWhenHttpServletRequestIsNullThenThrowIllegalArgumentException() {
-		assertThatIllegalArgumentException().isThrownBy(() -> this.logoutRequestRepository.loadLogoutRequest(null));
-	}
-
-	@Test
-	public void loadLogoutRequestWhenNotSavedThenReturnNull() {
-		MockHttpServletRequest request = new MockHttpServletRequest();
-		request.addParameter("RelayState", "state-1234");
-		Saml2LogoutRequest logoutRequest = this.logoutRequestRepository.loadLogoutRequest(request);
-		assertThat(logoutRequest).isNull();
-	}
-
-	@Test
-	public void loadLogoutRequestWhenSavedThenReturnLogoutRequest() {
-		MockHttpServletRequest request = new MockHttpServletRequest();
-		MockHttpServletResponse response = new MockHttpServletResponse();
-		Saml2LogoutRequest logoutRequest = createLogoutRequest().build();
-		this.logoutRequestRepository.saveLogoutRequest(logoutRequest, request, response);
-		request.addParameter("RelayState", logoutRequest.getRelayState());
-		Saml2LogoutRequest loadedLogoutRequest = this.logoutRequestRepository.loadLogoutRequest(request);
-		assertThat(loadedLogoutRequest).isEqualTo(logoutRequest);
-	}
-
-	// gh-5110
-	@Test
-	public void loadLogoutRequestWhenMultipleSavedThenReturnMatchingLogoutRequest() {
-		MockHttpServletRequest request = new MockHttpServletRequest();
-		MockHttpServletResponse response = new MockHttpServletResponse();
-		String state1 = "state-1122";
-		Saml2LogoutRequest logoutRequest1 = createLogoutRequest().relayState(state1).build();
-		this.logoutRequestRepository.saveLogoutRequest(logoutRequest1, request, response);
-		String state2 = "state-3344";
-		Saml2LogoutRequest logoutRequest2 = createLogoutRequest().relayState(state2).build();
-		this.logoutRequestRepository.saveLogoutRequest(logoutRequest2, request, response);
-		String state3 = "state-5566";
-		Saml2LogoutRequest logoutRequest3 = createLogoutRequest().relayState(state3).build();
-		this.logoutRequestRepository.saveLogoutRequest(logoutRequest3, request, response);
-		request.addParameter("RelayState", state1);
-		Saml2LogoutRequest loadedLogoutRequest1 = this.logoutRequestRepository.loadLogoutRequest(request);
-		assertThat(loadedLogoutRequest1).isEqualTo(logoutRequest1);
-		request.removeParameter("RelayState");
-		request.addParameter("RelayState", state2);
-		Saml2LogoutRequest loadedLogoutRequest2 = this.logoutRequestRepository.loadLogoutRequest(request);
-		assertThat(loadedLogoutRequest2).isEqualTo(logoutRequest2);
-		request.removeParameter("RelayState");
-		request.addParameter("RelayState", state3);
-		Saml2LogoutRequest loadedLogoutRequest3 = this.logoutRequestRepository.loadLogoutRequest(request);
-		assertThat(loadedLogoutRequest3).isEqualTo(logoutRequest3);
-	}
-
-	@Test
-	public void loadLogoutRequestWhenSavedAndStateParameterNullThenReturnNull() {
-		MockHttpServletRequest request = new MockHttpServletRequest();
-		Saml2LogoutRequest logoutRequest = createLogoutRequest().build();
-		this.logoutRequestRepository.saveLogoutRequest(logoutRequest, request, new MockHttpServletResponse());
-		assertThat(this.logoutRequestRepository.loadLogoutRequest(request)).isNull();
-	}
-
-	@Test
-	public void saveLogoutRequestWhenHttpServletRequestIsNullThenThrowIllegalArgumentException() {
-		Saml2LogoutRequest logoutRequest = createLogoutRequest().build();
-		assertThatIllegalArgumentException().isThrownBy(() -> this.logoutRequestRepository
-				.saveLogoutRequest(logoutRequest, null, new MockHttpServletResponse()));
-	}
-
-	@Test
-	public void saveLogoutRequestWhenHttpServletResponseIsNullThenThrowIllegalArgumentException() {
-		Saml2LogoutRequest logoutRequest = createLogoutRequest().build();
-		assertThatIllegalArgumentException().isThrownBy(() -> this.logoutRequestRepository
-				.saveLogoutRequest(logoutRequest, new MockHttpServletRequest(), null));
-	}
-
-	@Test
-	public void saveLogoutRequestWhenStateNullThenThrowIllegalArgumentException() {
-		Saml2LogoutRequest logoutRequest = createLogoutRequest().relayState(null).build();
-		assertThatIllegalArgumentException().isThrownBy(() -> this.logoutRequestRepository
-				.saveLogoutRequest(logoutRequest, new MockHttpServletRequest(), new MockHttpServletResponse()));
-	}
-
-	@Test
-	public void saveLogoutRequestWhenNotNullThenSaved() {
-		MockHttpServletRequest request = new MockHttpServletRequest();
-		Saml2LogoutRequest logoutRequest = createLogoutRequest().build();
-		this.logoutRequestRepository.saveLogoutRequest(logoutRequest, request, new MockHttpServletResponse());
-		request.addParameter("RelayState", logoutRequest.getRelayState());
-		Saml2LogoutRequest loadedLogoutRequest = this.logoutRequestRepository.loadLogoutRequest(request);
-		assertThat(loadedLogoutRequest).isEqualTo(logoutRequest);
-	}
-
-	@Test
-	public void saveLogoutRequestWhenNoExistingSessionAndDistributedSessionThenSaved() {
-		MockHttpServletRequest request = new MockHttpServletRequest();
-		request.setSession(new MockDistributedHttpSession());
-		Saml2LogoutRequest logoutRequest = createLogoutRequest().build();
-		this.logoutRequestRepository.saveLogoutRequest(logoutRequest, request, new MockHttpServletResponse());
-		request.addParameter("RelayState", logoutRequest.getRelayState());
-		Saml2LogoutRequest loadedLogoutRequest = this.logoutRequestRepository.loadLogoutRequest(request);
-		assertThat(loadedLogoutRequest).isEqualTo(logoutRequest);
-	}
-
-	@Test
-	public void saveLogoutRequestWhenExistingSessionAndDistributedSessionThenSaved() {
-		MockHttpServletRequest request = new MockHttpServletRequest();
-		request.setSession(new MockDistributedHttpSession());
-		Saml2LogoutRequest logoutRequest1 = createLogoutRequest().build();
-		this.logoutRequestRepository.saveLogoutRequest(logoutRequest1, request, new MockHttpServletResponse());
-		Saml2LogoutRequest logoutRequest2 = createLogoutRequest().build();
-		this.logoutRequestRepository.saveLogoutRequest(logoutRequest2, request, new MockHttpServletResponse());
-		request.addParameter("RelayState", logoutRequest2.getRelayState());
-		Saml2LogoutRequest loadedLogoutRequest = this.logoutRequestRepository.loadLogoutRequest(request);
-		assertThat(loadedLogoutRequest).isEqualTo(logoutRequest2);
-	}
-
-	@Test
-	public void saveLogoutRequestWhenNullThenRemoved() {
-		MockHttpServletRequest request = new MockHttpServletRequest();
-		MockHttpServletResponse response = new MockHttpServletResponse();
-		Saml2LogoutRequest logoutRequest = createLogoutRequest().build();
-		this.logoutRequestRepository.saveLogoutRequest(logoutRequest, request, response);
-		request.addParameter("RelayState", logoutRequest.getRelayState());
-		this.logoutRequestRepository.saveLogoutRequest(null, request, response);
-		Saml2LogoutRequest loadedLogoutRequest = this.logoutRequestRepository.loadLogoutRequest(request);
-		assertThat(loadedLogoutRequest).isNull();
-	}
-
-	@Test
-	public void removeLogoutRequestWhenHttpServletRequestIsNullThenThrowIllegalArgumentException() {
-		assertThatIllegalArgumentException().isThrownBy(
-				() -> this.logoutRequestRepository.removeLogoutRequest(null, new MockHttpServletResponse()));
-	}
-
-	@Test
-	public void removeLogoutRequestWhenHttpServletResponseIsNullThenThrowIllegalArgumentException() {
-		assertThatIllegalArgumentException()
-				.isThrownBy(() -> this.logoutRequestRepository.removeLogoutRequest(new MockHttpServletRequest(), null));
-	}
-
-	@Test
-	public void removeLogoutRequestWhenSavedThenRemoved() {
-		MockHttpServletRequest request = new MockHttpServletRequest();
-		MockHttpServletResponse response = new MockHttpServletResponse();
-		Saml2LogoutRequest logoutRequest = createLogoutRequest().build();
-		this.logoutRequestRepository.saveLogoutRequest(logoutRequest, request, response);
-		request.addParameter("RelayState", logoutRequest.getRelayState());
-		Saml2LogoutRequest removedLogoutRequest = this.logoutRequestRepository.removeLogoutRequest(request, response);
-		Saml2LogoutRequest loadedLogoutRequest = this.logoutRequestRepository.loadLogoutRequest(request);
-		assertThat(removedLogoutRequest).isNotNull();
-		assertThat(loadedLogoutRequest).isNull();
-	}
-
-	// gh-5263
-	@Test
-	public void removeLogoutRequestWhenSavedThenRemovedFromSession() {
-		MockHttpServletRequest request = new MockHttpServletRequest();
-		MockHttpServletResponse response = new MockHttpServletResponse();
-		Saml2LogoutRequest logoutRequest = createLogoutRequest().build();
-		this.logoutRequestRepository.saveLogoutRequest(logoutRequest, request, response);
-		request.addParameter("RelayState", logoutRequest.getRelayState());
-		Saml2LogoutRequest removedLogoutRequest = this.logoutRequestRepository.removeLogoutRequest(request, response);
-		String sessionAttributeName = HttpSessionLogoutRequestRepository.class.getName() + ".AUTHORIZATION_REQUEST";
-		assertThat(removedLogoutRequest).isNotNull();
-		assertThat(request.getSession().getAttribute(sessionAttributeName)).isNull();
-	}
-
-	@Test
-	public void removeLogoutRequestWhenNotSavedThenNotRemoved() {
-		MockHttpServletRequest request = new MockHttpServletRequest();
-		request.addParameter("RelayState", "state-1234");
-		MockHttpServletResponse response = new MockHttpServletResponse();
-		Saml2LogoutRequest removedLogoutRequest = this.logoutRequestRepository.removeLogoutRequest(request, response);
-		assertThat(removedLogoutRequest).isNull();
-	}
-
-	private Saml2LogoutRequest.Builder createLogoutRequest() {
-		RelyingPartyRegistration registration = TestRelyingPartyRegistrations.full().build();
-		return Saml2LogoutRequest.withRelyingPartyRegistration(registration).samlRequest("request").id("id")
-				.parameters((params) -> params.put("RelayState", "state-1234"));
-	}
-
-	static class MockDistributedHttpSession extends MockHttpSession {
-
-		@Override
-		public Object getAttribute(String name) {
-			return wrap(super.getAttribute(name));
-		}
-
-		@Override
-		public void setAttribute(String name, Object value) {
-			super.setAttribute(name, wrap(value));
-		}
-
-		private Object wrap(Object object) {
-			if (object instanceof Map) {
-				object = new HashMap<>((Map<Object, Object>) object);
-			}
-			return object;
-		}
-
-	}
-
-}

+ 0 - 182
saml2/saml2-service-provider/core/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSamlLogoutRequestHandlerTests.java

@@ -1,182 +0,0 @@
-/*
- * Copyright 2002-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.provider.service.web.authentication.logout;
-
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.junit.Test;
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.saml.saml2.core.LogoutRequest;
-
-import org.springframework.mock.web.MockHttpServletRequest;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.saml2.Saml2Exception;
-import org.springframework.security.saml2.core.Saml2ErrorCodes;
-import org.springframework.security.saml2.core.TestSaml2X509Credentials;
-import org.springframework.security.saml2.provider.service.authentication.DefaultSaml2AuthenticatedPrincipal;
-import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
-import org.springframework.security.saml2.provider.service.authentication.TestOpenSamlObjects;
-import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
-import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations;
-import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver;
-import org.springframework.security.saml2.provider.service.web.authentication.logout.OpenSamlSigningUtils.QueryParametersPartial;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
-import static org.mockito.BDDMockito.given;
-import static org.mockito.BDDMockito.mock;
-
-/**
- * Tests for {@link OpenSamlLogoutRequestHandler}
- *
- * @author Josh Cummings
- */
-public class OpenSamlLogoutRequestHandlerTests {
-
-	private final RelyingPartyRegistrationResolver resolver = mock(RelyingPartyRegistrationResolver.class);
-
-	private final OpenSamlLogoutRequestHandler handler = new OpenSamlLogoutRequestHandler(this.resolver);
-
-	@Test
-	public void handleWhenAuthenticatedThenSavesRequestId() {
-		RelyingPartyRegistration registration = registration().build();
-		LogoutRequest logoutRequest = TestOpenSamlObjects.assertingPartyLogoutRequest(registration);
-		sign(logoutRequest, registration);
-		Authentication authentication = authentication(registration);
-		MockHttpServletRequest request = post(logoutRequest);
-		given(this.resolver.resolve(request, registration.getRegistrationId())).willReturn(registration);
-		this.handler.logout(request, null, authentication);
-		String id = ((LogoutRequest) request.getAttribute(LogoutRequest.class.getName())).getID();
-		assertThat(id).isEqualTo(logoutRequest.getID());
-	}
-
-	@Test
-	public void handleWhenRedirectBindingThenValidatesSignatureParameter() {
-		RelyingPartyRegistration registration = registration().build();
-		LogoutRequest logoutRequest = TestOpenSamlObjects.assertingPartyLogoutRequest(registration);
-		Authentication authentication = authentication(registration);
-		MockHttpServletRequest request = redirect(logoutRequest, OpenSamlSigningUtils.sign(registration));
-		given(this.resolver.resolve(request, registration.getRegistrationId())).willReturn(registration);
-		this.handler.logout(request, null, authentication);
-		String id = ((LogoutRequest) request.getAttribute(LogoutRequest.class.getName())).getID();
-		assertThat(id).isEqualTo(logoutRequest.getID());
-	}
-
-	@Test
-	public void handleWhenInvalidIssuerThenInvalidSignatureError() {
-		RelyingPartyRegistration registration = registration().build();
-		LogoutRequest logoutRequest = TestOpenSamlObjects.assertingPartyLogoutRequest(registration);
-		logoutRequest.getIssuer().setValue("wrong");
-		sign(logoutRequest, registration);
-		Authentication authentication = authentication(registration);
-		MockHttpServletRequest request = post(logoutRequest);
-		given(this.resolver.resolve(request, registration.getRegistrationId())).willReturn(registration);
-		assertThatExceptionOfType(Saml2Exception.class)
-				.isThrownBy(() -> this.handler.logout(request, null, authentication))
-				.withMessageContaining(Saml2ErrorCodes.INVALID_SIGNATURE);
-	}
-
-	@Test
-	public void handleWhenMismatchedUserThenInvalidRequestError() {
-		RelyingPartyRegistration registration = registration().build();
-		LogoutRequest logoutRequest = TestOpenSamlObjects.assertingPartyLogoutRequest(registration);
-		logoutRequest.getNameID().setValue("wrong");
-		sign(logoutRequest, registration);
-		Authentication authentication = authentication(registration);
-		MockHttpServletRequest request = post(logoutRequest);
-		given(this.resolver.resolve(request, registration.getRegistrationId())).willReturn(registration);
-		assertThatExceptionOfType(Saml2Exception.class)
-				.isThrownBy(() -> this.handler.logout(request, null, authentication))
-				.withMessageContaining(Saml2ErrorCodes.INVALID_REQUEST);
-	}
-
-	@Test
-	public void handleWhenMissingUserThenSubjectNotFoundError() {
-		RelyingPartyRegistration registration = registration().build();
-		LogoutRequest logoutRequest = TestOpenSamlObjects.assertingPartyLogoutRequest(registration);
-		logoutRequest.setNameID(null);
-		sign(logoutRequest, registration);
-		Authentication authentication = authentication(registration);
-		MockHttpServletRequest request = post(logoutRequest);
-		given(this.resolver.resolve(request, registration.getRegistrationId())).willReturn(registration);
-		assertThatExceptionOfType(Saml2Exception.class)
-				.isThrownBy(() -> this.handler.logout(request, null, authentication))
-				.withMessageContaining(Saml2ErrorCodes.SUBJECT_NOT_FOUND);
-	}
-
-	@Test
-	public void handleWhenMismatchedDestinationThenInvalidDestinationError() {
-		RelyingPartyRegistration registration = registration().build();
-		LogoutRequest logoutRequest = TestOpenSamlObjects.assertingPartyLogoutRequest(registration);
-		logoutRequest.setDestination("wrong");
-		sign(logoutRequest, registration);
-		Authentication authentication = authentication(registration);
-		MockHttpServletRequest request = post(logoutRequest);
-		given(this.resolver.resolve(request, registration.getRegistrationId())).willReturn(registration);
-		assertThatExceptionOfType(Saml2Exception.class)
-				.isThrownBy(() -> this.handler.logout(request, null, authentication))
-				.withMessageContaining(Saml2ErrorCodes.INVALID_DESTINATION);
-	}
-
-	private RelyingPartyRegistration.Builder registration() {
-		return signing(verifying(TestRelyingPartyRegistrations.noCredentials()));
-	}
-
-	private RelyingPartyRegistration.Builder verifying(RelyingPartyRegistration.Builder builder) {
-		return builder.assertingPartyDetails((party) -> party
-				.verificationX509Credentials((c) -> c.add(TestSaml2X509Credentials.relyingPartyVerifyingCredential())));
-	}
-
-	private RelyingPartyRegistration.Builder signing(RelyingPartyRegistration.Builder builder) {
-		return builder.signingX509Credentials((c) -> c.add(TestSaml2X509Credentials.assertingPartySigningCredential()));
-	}
-
-	private Authentication authentication(RelyingPartyRegistration registration) {
-		return new Saml2Authentication(new DefaultSaml2AuthenticatedPrincipal("user", new HashMap<>()), "response",
-				new ArrayList<>(), registration.getRegistrationId());
-	}
-
-	private MockHttpServletRequest post(LogoutRequest logoutRequest) {
-		MockHttpServletRequest request = new MockHttpServletRequest();
-		request.setMethod("POST");
-		request.setParameter("SAMLRequest",
-				Saml2Utils.samlEncode(serialize(logoutRequest).getBytes(StandardCharsets.UTF_8)));
-		return request;
-	}
-
-	private MockHttpServletRequest redirect(LogoutRequest logoutRequest, QueryParametersPartial partial) {
-		String serialized = Saml2Utils.samlEncode(Saml2Utils.samlDeflate(serialize(logoutRequest)));
-		Map<String, String> parameters = partial.param("SAMLRequest", serialized).parameters();
-		MockHttpServletRequest request = new MockHttpServletRequest();
-		request.setParameters(parameters);
-		request.setMethod("GET");
-		return request;
-	}
-
-	private void sign(LogoutRequest logoutRequest, RelyingPartyRegistration registration) {
-		TestOpenSamlObjects.signed(logoutRequest, registration.getSigningX509Credentials().iterator().next(),
-				registration.getAssertingPartyDetails().getEntityId());
-	}
-
-	private String serialize(XMLObject object) {
-		return OpenSamlSigningUtils.serialize(object);
-	}
-
-}

+ 0 - 112
saml2/saml2-service-provider/core/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSamlLogoutRequestResolverTests.java

@@ -1,112 +0,0 @@
-/*
- * Copyright 2002-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.provider.service.web.authentication.logout;
-
-import java.io.ByteArrayInputStream;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.HashMap;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.junit.Test;
-import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
-import org.opensaml.saml.saml2.core.LogoutRequest;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-import org.springframework.mock.web.MockHttpServletRequest;
-import org.springframework.security.saml2.Saml2Exception;
-import org.springframework.security.saml2.provider.service.authentication.DefaultSaml2AuthenticatedPrincipal;
-import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
-import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutRequest;
-import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
-import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
-import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations;
-import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.BDDMockito.given;
-import static org.mockito.BDDMockito.mock;
-
-/**
- * Tests for {@link OpenSamlLogoutRequestResolver}
- *
- * @author Josh Cummings
- */
-public class OpenSamlLogoutRequestResolverTests {
-
-	private final RelyingPartyRegistrationResolver resolver = mock(RelyingPartyRegistrationResolver.class);
-
-	private final OpenSamlLogoutRequestResolver logoutResolver = new OpenSamlLogoutRequestResolver(this.resolver);
-
-	@Test
-	public void resolveRedirectWhenAuthenticatedThenIncludesName() {
-		RelyingPartyRegistration registration = TestRelyingPartyRegistrations.full().build();
-		Saml2Authentication authentication = authentication(registration);
-		HttpServletRequest request = new MockHttpServletRequest();
-		given(this.resolver.resolve(request, registration.getRegistrationId())).willReturn(registration);
-		Saml2LogoutRequest saml2LogoutRequest = this.logoutResolver.resolveLogoutRequest(request, authentication)
-				.logoutRequest();
-		assertThat(saml2LogoutRequest.getParameter("SigAlg")).isNotNull();
-		assertThat(saml2LogoutRequest.getParameter("Signature")).isNotNull();
-		Saml2MessageBinding binding = registration.getAssertingPartyDetails().getSingleLogoutServiceBinding();
-		LogoutRequest logoutRequest = getLogoutRequest(saml2LogoutRequest.getSamlRequest(), binding);
-		assertThat(logoutRequest.getNameID().getValue()).isEqualTo(authentication.getName());
-	}
-
-	@Test
-	public void resolvePostWhenAuthenticatedThenIncludesName() {
-		RelyingPartyRegistration registration = TestRelyingPartyRegistrations.full()
-				.assertingPartyDetails((party) -> party.singleLogoutServiceBinding(Saml2MessageBinding.POST)).build();
-		Saml2Authentication authentication = authentication(registration);
-		HttpServletRequest request = new MockHttpServletRequest();
-		given(this.resolver.resolve(request, registration.getRegistrationId())).willReturn(registration);
-		Saml2LogoutRequest saml2LogoutRequest = this.logoutResolver.resolveLogoutRequest(request, authentication)
-				.logoutRequest();
-		assertThat(saml2LogoutRequest.getParameter("SigAlg")).isNull();
-		assertThat(saml2LogoutRequest.getParameter("Signature")).isNull();
-		Saml2MessageBinding binding = registration.getAssertingPartyDetails().getSingleLogoutServiceBinding();
-		LogoutRequest logoutRequest = getLogoutRequest(saml2LogoutRequest.getSamlRequest(), binding);
-		assertThat(logoutRequest.getNameID().getValue()).isEqualTo(authentication.getName());
-	}
-
-	private Saml2Authentication authentication(RelyingPartyRegistration registration) {
-		return new Saml2Authentication(new DefaultSaml2AuthenticatedPrincipal("user", new HashMap<>()), "response",
-				new ArrayList<>(), registration.getRegistrationId());
-	}
-
-	private LogoutRequest getLogoutRequest(String samlRequest, Saml2MessageBinding binding) {
-		if (binding == Saml2MessageBinding.REDIRECT) {
-			samlRequest = Saml2Utils.samlInflate(Saml2Utils.samlDecode(samlRequest));
-		}
-		else {
-			samlRequest = new String(Saml2Utils.samlDecode(samlRequest), StandardCharsets.UTF_8);
-		}
-		try {
-			Document document = XMLObjectProviderRegistrySupport.getParserPool()
-					.parse(new ByteArrayInputStream(samlRequest.getBytes(StandardCharsets.UTF_8)));
-			Element element = document.getDocumentElement();
-			return (LogoutRequest) XMLObjectProviderRegistrySupport.getUnmarshallerFactory().getUnmarshaller(element)
-					.unmarshall(element);
-		}
-		catch (Exception ex) {
-			throw new Saml2Exception(ex);
-		}
-	}
-
-}

+ 0 - 189
saml2/saml2-service-provider/core/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSamlLogoutResponseHandlerTests.java

@@ -1,189 +0,0 @@
-/*
- * Copyright 2002-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.provider.service.web.authentication.logout;
-
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.opensaml.core.xml.XMLObject;
-import org.opensaml.saml.saml2.core.LogoutResponse;
-import org.opensaml.saml.saml2.core.StatusCode;
-
-import org.springframework.mock.web.MockHttpServletRequest;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.saml2.Saml2Exception;
-import org.springframework.security.saml2.core.Saml2ErrorCodes;
-import org.springframework.security.saml2.core.TestSaml2X509Credentials;
-import org.springframework.security.saml2.provider.service.authentication.DefaultSaml2AuthenticatedPrincipal;
-import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
-import org.springframework.security.saml2.provider.service.authentication.TestOpenSamlObjects;
-import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutRequest;
-import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
-import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations;
-import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver;
-import org.springframework.security.saml2.provider.service.web.authentication.logout.OpenSamlSigningUtils.QueryParametersPartial;
-
-import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.BDDMockito.given;
-import static org.mockito.BDDMockito.mock;
-
-/**
- * Tests for {@link OpenSamlLogoutResponseHandler}
- *
- * @author Josh Cummings
- */
-public class OpenSamlLogoutResponseHandlerTests {
-
-	private final RelyingPartyRegistrationResolver resolver = mock(RelyingPartyRegistrationResolver.class);
-
-	private final Saml2LogoutRequestRepository repository = mock(Saml2LogoutRequestRepository.class);
-
-	private final OpenSamlLogoutResponseHandler handler = new OpenSamlLogoutResponseHandler(this.resolver);
-
-	@Before
-	public void setUp() {
-		this.handler.setLogoutRequestRepository(this.repository);
-	}
-
-	@Test
-	public void handleWhenAuthenticatedThenHandles() {
-		RelyingPartyRegistration registration = signing(verifying(registration())).build();
-		Saml2LogoutRequest logoutRequest = Saml2LogoutRequest.withRelyingPartyRegistration(registration).id("id")
-				.build();
-		given(this.repository.removeLogoutRequest(any(), any())).willReturn(logoutRequest);
-		LogoutResponse logoutResponse = TestOpenSamlObjects.assertingPartyLogoutResponse(registration);
-		sign(logoutResponse, registration);
-		Authentication authentication = authentication(registration);
-		MockHttpServletRequest request = post(logoutResponse);
-		given(this.resolver.resolve(request, registration.getRegistrationId())).willReturn(registration);
-		this.handler.logout(request, null, authentication);
-	}
-
-	@Test
-	public void handleWhenRedirectBindingThenValidatesSignatureParameter() {
-		RelyingPartyRegistration registration = signing(verifying(registration())).build();
-		Saml2LogoutRequest logoutRequest = Saml2LogoutRequest.withRelyingPartyRegistration(registration).id("id")
-				.build();
-		given(this.repository.removeLogoutRequest(any(), any())).willReturn(logoutRequest);
-		LogoutResponse logoutResponse = TestOpenSamlObjects.assertingPartyLogoutResponse(registration);
-		Authentication authentication = authentication(registration);
-		MockHttpServletRequest request = redirect(logoutResponse, OpenSamlSigningUtils.sign(registration));
-		given(this.resolver.resolve(request, registration.getRegistrationId())).willReturn(registration);
-		this.handler.logout(request, null, authentication);
-	}
-
-	@Test
-	public void handleWhenInvalidIssuerThenInvalidSignatureError() {
-		RelyingPartyRegistration registration = registration().build();
-		Saml2LogoutRequest logoutRequest = Saml2LogoutRequest.withRelyingPartyRegistration(registration).id("id")
-				.build();
-		given(this.repository.removeLogoutRequest(any(), any())).willReturn(logoutRequest);
-		LogoutResponse logoutResponse = TestOpenSamlObjects.assertingPartyLogoutResponse(registration);
-		logoutResponse.getIssuer().setValue("wrong");
-		sign(logoutResponse, registration);
-		Authentication authentication = authentication(registration);
-		MockHttpServletRequest request = post(logoutResponse);
-		given(this.resolver.resolve(request, registration.getRegistrationId())).willReturn(registration);
-		assertThatExceptionOfType(Saml2Exception.class)
-				.isThrownBy(() -> this.handler.logout(request, null, authentication))
-				.withMessageContaining(Saml2ErrorCodes.INVALID_SIGNATURE);
-	}
-
-	@Test
-	public void handleWhenMismatchedDestinationThenInvalidDestinationError() {
-		RelyingPartyRegistration registration = registration().build();
-		Saml2LogoutRequest logoutRequest = Saml2LogoutRequest.withRelyingPartyRegistration(registration).id("id")
-				.build();
-		given(this.repository.removeLogoutRequest(any(), any())).willReturn(logoutRequest);
-		LogoutResponse logoutResponse = TestOpenSamlObjects.assertingPartyLogoutResponse(registration);
-		logoutResponse.setDestination("wrong");
-		sign(logoutResponse, registration);
-		Authentication authentication = authentication(registration);
-		MockHttpServletRequest request = post(logoutResponse);
-		given(this.resolver.resolve(request, registration.getRegistrationId())).willReturn(registration);
-		assertThatExceptionOfType(Saml2Exception.class)
-				.isThrownBy(() -> this.handler.logout(request, null, authentication))
-				.withMessageContaining(Saml2ErrorCodes.INVALID_DESTINATION);
-	}
-
-	@Test
-	public void handleWhenStatusNotSuccessThenInvalidResponseError() {
-		RelyingPartyRegistration registration = registration().build();
-		Saml2LogoutRequest logoutRequest = Saml2LogoutRequest.withRelyingPartyRegistration(registration).id("id")
-				.build();
-		given(this.repository.removeLogoutRequest(any(), any())).willReturn(logoutRequest);
-		LogoutResponse logoutResponse = TestOpenSamlObjects.assertingPartyLogoutResponse(registration);
-		logoutResponse.getStatus().getStatusCode().setValue(StatusCode.UNKNOWN_PRINCIPAL);
-		sign(logoutResponse, registration);
-		Authentication authentication = authentication(registration);
-		MockHttpServletRequest request = post(logoutResponse);
-		given(this.resolver.resolve(request, registration.getRegistrationId())).willReturn(registration);
-		assertThatExceptionOfType(Saml2Exception.class)
-				.isThrownBy(() -> this.handler.logout(request, null, authentication))
-				.withMessageContaining(Saml2ErrorCodes.INVALID_RESPONSE);
-	}
-
-	private RelyingPartyRegistration.Builder registration() {
-		return signing(verifying(TestRelyingPartyRegistrations.noCredentials()));
-	}
-
-	private RelyingPartyRegistration.Builder verifying(RelyingPartyRegistration.Builder builder) {
-		return builder.assertingPartyDetails((party) -> party
-				.verificationX509Credentials((c) -> c.add(TestSaml2X509Credentials.relyingPartyVerifyingCredential())));
-	}
-
-	private RelyingPartyRegistration.Builder signing(RelyingPartyRegistration.Builder builder) {
-		return builder.signingX509Credentials((c) -> c.add(TestSaml2X509Credentials.assertingPartySigningCredential()));
-	}
-
-	private Authentication authentication(RelyingPartyRegistration registration) {
-		return new Saml2Authentication(new DefaultSaml2AuthenticatedPrincipal("user", new HashMap<>()), "response",
-				new ArrayList<>(), registration.getRegistrationId());
-	}
-
-	private MockHttpServletRequest post(LogoutResponse logoutResponse) {
-		MockHttpServletRequest request = new MockHttpServletRequest();
-		request.setMethod("POST");
-		request.setParameter("SAMLResponse",
-				Saml2Utils.samlEncode(serialize(logoutResponse).getBytes(StandardCharsets.UTF_8)));
-		return request;
-	}
-
-	private MockHttpServletRequest redirect(LogoutResponse logoutResponse, QueryParametersPartial partial) {
-		String serialized = Saml2Utils.samlEncode(Saml2Utils.samlDeflate(serialize(logoutResponse)));
-		Map<String, String> parameters = partial.param("SAMLResponse", serialized).parameters();
-		MockHttpServletRequest request = new MockHttpServletRequest();
-		request.setParameters(parameters);
-		request.setMethod("GET");
-		return request;
-	}
-
-	private void sign(LogoutResponse logoutResponse, RelyingPartyRegistration registration) {
-		TestOpenSamlObjects.signed(logoutResponse, registration.getSigningX509Credentials().iterator().next(),
-				registration.getAssertingPartyDetails().getEntityId());
-	}
-
-	private String serialize(XMLObject object) {
-		return OpenSamlSigningUtils.serialize(object);
-	}
-
-}

+ 0 - 119
saml2/saml2-service-provider/core/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSamlLogoutResponseResolverTests.java

@@ -1,119 +0,0 @@
-/*
- * Copyright 2002-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.provider.service.web.authentication.logout;
-
-import java.io.ByteArrayInputStream;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.HashMap;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.junit.Test;
-import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
-import org.opensaml.saml.saml2.core.LogoutRequest;
-import org.opensaml.saml.saml2.core.LogoutResponse;
-import org.opensaml.saml.saml2.core.StatusCode;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-import org.springframework.mock.web.MockHttpServletRequest;
-import org.springframework.security.saml2.Saml2Exception;
-import org.springframework.security.saml2.provider.service.authentication.DefaultSaml2AuthenticatedPrincipal;
-import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
-import org.springframework.security.saml2.provider.service.authentication.TestOpenSamlObjects;
-import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutResponse;
-import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
-import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
-import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations;
-import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.BDDMockito.given;
-import static org.mockito.BDDMockito.mock;
-
-/**
- * Tests for {@link OpenSamlLogoutResponseResolver}
- *
- * @author Josh Cummings
- */
-public class OpenSamlLogoutResponseResolverTests {
-
-	private final RelyingPartyRegistrationResolver resolver = mock(RelyingPartyRegistrationResolver.class);
-
-	private final OpenSamlLogoutResponseResolver logoutResolver = new OpenSamlLogoutResponseResolver(this.resolver);
-
-	@Test
-	public void resolveRedirectWhenAuthenticatedThenSuccess() {
-		RelyingPartyRegistration registration = TestRelyingPartyRegistrations.full().build();
-		Saml2Authentication authentication = authentication(registration);
-		HttpServletRequest request = new MockHttpServletRequest();
-		LogoutRequest logoutRequest = TestOpenSamlObjects.assertingPartyLogoutRequest(registration);
-		request.setAttribute(LogoutRequest.class.getName(), logoutRequest);
-		given(this.resolver.resolve(request, registration.getRegistrationId())).willReturn(registration);
-		Saml2LogoutResponse saml2LogoutResponse = this.logoutResolver.resolveLogoutResponse(request, authentication)
-				.logoutResponse();
-		assertThat(saml2LogoutResponse.getParameter("SigAlg")).isNotNull();
-		assertThat(saml2LogoutResponse.getParameter("Signature")).isNotNull();
-		Saml2MessageBinding binding = registration.getAssertingPartyDetails().getSingleLogoutServiceBinding();
-		LogoutResponse logoutResponse = getLogoutResponse(saml2LogoutResponse.getSamlResponse(), binding);
-		assertThat(logoutResponse.getStatus().getStatusCode().getValue()).isEqualTo(StatusCode.SUCCESS);
-	}
-
-	@Test
-	public void resolvePostWhenAuthenticatedThenSuccess() {
-		RelyingPartyRegistration registration = TestRelyingPartyRegistrations.full()
-				.assertingPartyDetails((party) -> party.singleLogoutServiceBinding(Saml2MessageBinding.POST)).build();
-		Saml2Authentication authentication = authentication(registration);
-		HttpServletRequest request = new MockHttpServletRequest();
-		LogoutRequest logoutRequest = TestOpenSamlObjects.assertingPartyLogoutRequest(registration);
-		request.setAttribute(LogoutRequest.class.getName(), logoutRequest);
-		given(this.resolver.resolve(request, registration.getRegistrationId())).willReturn(registration);
-		Saml2LogoutResponse saml2LogoutResponse = this.logoutResolver.resolveLogoutResponse(request, authentication)
-				.logoutResponse();
-		assertThat(saml2LogoutResponse.getParameter("SigAlg")).isNull();
-		assertThat(saml2LogoutResponse.getParameter("Signature")).isNull();
-		Saml2MessageBinding binding = registration.getAssertingPartyDetails().getSingleLogoutServiceBinding();
-		LogoutResponse logoutResponse = getLogoutResponse(saml2LogoutResponse.getSamlResponse(), binding);
-		assertThat(logoutResponse.getStatus().getStatusCode().getValue()).isEqualTo(StatusCode.SUCCESS);
-	}
-
-	private Saml2Authentication authentication(RelyingPartyRegistration registration) {
-		return new Saml2Authentication(new DefaultSaml2AuthenticatedPrincipal("user", new HashMap<>()), "response",
-				new ArrayList<>(), registration.getRegistrationId());
-	}
-
-	private LogoutResponse getLogoutResponse(String saml2Response, Saml2MessageBinding binding) {
-		if (binding == Saml2MessageBinding.REDIRECT) {
-			saml2Response = Saml2Utils.samlInflate(Saml2Utils.samlDecode(saml2Response));
-		}
-		else {
-			saml2Response = new String(Saml2Utils.samlDecode(saml2Response), StandardCharsets.UTF_8);
-		}
-		try {
-			Document document = XMLObjectProviderRegistrySupport.getParserPool()
-					.parse(new ByteArrayInputStream(saml2Response.getBytes(StandardCharsets.UTF_8)));
-			Element element = document.getDocumentElement();
-			return (LogoutResponse) XMLObjectProviderRegistrySupport.getUnmarshallerFactory().getUnmarshaller(element)
-					.unmarshall(element);
-		}
-		catch (Exception ex) {
-			throw new Saml2Exception(ex);
-		}
-	}
-
-}

+ 0 - 116
saml2/saml2-service-provider/core/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutRequestFilterTests.java

@@ -1,116 +0,0 @@
-/*
- * Copyright 2002-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.provider.service.web.authentication.logout;
-
-import org.junit.After;
-import org.junit.Test;
-
-import org.springframework.mock.web.MockFilterChain;
-import org.springframework.mock.web.MockHttpServletRequest;
-import org.springframework.mock.web.MockHttpServletResponse;
-import org.springframework.security.authentication.TestingAuthenticationToken;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.web.authentication.logout.LogoutHandler;
-import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
-
-import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
-import static org.mockito.BDDMockito.mock;
-import static org.mockito.BDDMockito.verify;
-import static org.mockito.BDDMockito.willThrow;
-import static org.mockito.Mockito.verifyNoInteractions;
-
-public class Saml2LogoutRequestFilterTests {
-
-	private final LogoutHandler handler = mock(LogoutHandler.class);
-
-	private final LogoutSuccessHandler successHandler = mock(LogoutSuccessHandler.class);
-
-	private final Saml2LogoutRequestFilter filter = new Saml2LogoutRequestFilter(this.successHandler, this.handler);
-
-	@After
-	public void tearDown() {
-		SecurityContextHolder.clearContext();
-	}
-
-	@Test
-	public void doFilterWhenSamlRequestMatchesThenLogout() throws Exception {
-		Authentication authentication = new TestingAuthenticationToken("user", "password");
-		SecurityContextHolder.getContext().setAuthentication(authentication);
-		MockHttpServletRequest request = new MockHttpServletRequest("POST", "/logout/saml2/slo");
-		request.setServletPath("/logout/saml2/slo");
-		request.setParameter("SAMLRequest", "request");
-		MockHttpServletResponse response = new MockHttpServletResponse();
-		this.filter.doFilterInternal(request, response, new MockFilterChain());
-		verify(this.handler).logout(request, response, authentication);
-		verify(this.successHandler).onLogoutSuccess(request, response, authentication);
-	}
-
-	@Test
-	public void doFilterWhenSamlResponseMatchesThenLogout() throws Exception {
-		Authentication authentication = new TestingAuthenticationToken("user", "password");
-		SecurityContextHolder.getContext().setAuthentication(authentication);
-		MockHttpServletRequest request = new MockHttpServletRequest("POST", "/logout/saml2/slo");
-		request.setServletPath("/logout/saml2/slo");
-		request.setParameter("SAMLRequest", "request");
-		MockHttpServletResponse response = new MockHttpServletResponse();
-		this.filter.doFilterInternal(request, response, new MockFilterChain());
-		verify(this.handler).logout(request, response, authentication);
-		verify(this.successHandler).onLogoutSuccess(request, response, authentication);
-	}
-
-	@Test
-	public void doFilterWhenRequestMismatchesThenNoLogout() throws Exception {
-		Authentication authentication = new TestingAuthenticationToken("user", "password");
-		SecurityContextHolder.getContext().setAuthentication(authentication);
-		MockHttpServletRequest request = new MockHttpServletRequest("POST", "/logout");
-		request.setServletPath("/logout");
-		request.setParameter("SAMLRequest", "request");
-		MockHttpServletResponse response = new MockHttpServletResponse();
-		this.filter.doFilterInternal(request, response, new MockFilterChain());
-		verifyNoInteractions(this.handler);
-		verifyNoInteractions(this.successHandler);
-	}
-
-	@Test
-	public void doFilterWhenNoSamlRequestOrResponseThenNoLogout() throws Exception {
-		Authentication authentication = new TestingAuthenticationToken("user", "password");
-		SecurityContextHolder.getContext().setAuthentication(authentication);
-		MockHttpServletRequest request = new MockHttpServletRequest("POST", "/logout/saml2/slo");
-		request.setServletPath("/logout/saml2/slo");
-		MockHttpServletResponse response = new MockHttpServletResponse();
-		this.filter.doFilterInternal(request, response, new MockFilterChain());
-		verifyNoInteractions(this.handler);
-		verifyNoInteractions(this.successHandler);
-	}
-
-	@Test
-	public void doFilterWhenLogoutHandlerFailsThenNoSuccessHandler() {
-		Authentication authentication = new TestingAuthenticationToken("user", "password");
-		SecurityContextHolder.getContext().setAuthentication(authentication);
-		MockHttpServletRequest request = new MockHttpServletRequest("POST", "/logout/saml2/slo");
-		request.setServletPath("/logout/saml2/slo");
-		request.setParameter("SAMLRequest", "request");
-		MockHttpServletResponse response = new MockHttpServletResponse();
-		willThrow(RuntimeException.class).given(this.handler).logout(request, response, authentication);
-		assertThatExceptionOfType(RuntimeException.class)
-				.isThrownBy(() -> this.filter.doFilterInternal(request, response, new MockFilterChain()));
-		verify(this.handler).logout(request, response, authentication);
-		verifyNoInteractions(this.successHandler);
-	}
-
-}

+ 0 - 111
saml2/saml2-service-provider/core/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutRequestSuccessHandlerTests.java

@@ -1,111 +0,0 @@
-/*
- * Copyright 2002-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.provider.service.web.authentication.logout;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import org.springframework.mock.web.MockHttpServletRequest;
-import org.springframework.mock.web.MockHttpServletResponse;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.saml2.provider.service.authentication.DefaultSaml2AuthenticatedPrincipal;
-import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
-import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutRequest;
-import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
-import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
-import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations;
-import org.springframework.security.saml2.provider.service.web.authentication.logout.Saml2LogoutRequestResolver.Saml2LogoutRequestBuilder;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.BDDMockito.RETURNS_SELF;
-import static org.mockito.BDDMockito.given;
-import static org.mockito.BDDMockito.mock;
-import static org.mockito.BDDMockito.willReturn;
-
-/**
- * Tests for {@link Saml2LogoutRequestSuccessHandler}
- *
- * @author Josh Cummings
- */
-public class Saml2LogoutRequestSuccessHandlerTests {
-
-	private final Saml2LogoutRequestResolver resolver = mock(Saml2LogoutRequestResolver.class);
-
-	private final Saml2LogoutRequestRepository repository = mock(Saml2LogoutRequestRepository.class);
-
-	private final Saml2LogoutRequestSuccessHandler handler = new Saml2LogoutRequestSuccessHandler(this.resolver);
-
-	@Before
-	public void setUp() {
-		this.handler.setLogoutRequestRepository(this.repository);
-	}
-
-	@After
-	public void tearDown() {
-		SecurityContextHolder.clearContext();
-	}
-
-	@Test
-	public void doFilterWhenRedirectThenRedirectsToAssertingParty() throws Exception {
-		RelyingPartyRegistration registration = TestRelyingPartyRegistrations.full().build();
-		Authentication authentication = authentication(registration);
-		SecurityContextHolder.getContext().setAuthentication(authentication);
-		Saml2LogoutRequest logoutRequest = Saml2LogoutRequest.withRelyingPartyRegistration(registration)
-				.samlRequest("request").build();
-		MockHttpServletRequest request = new MockHttpServletRequest("POST", "/saml2/logout");
-		request.setServletPath("/saml2/logout");
-		MockHttpServletResponse response = new MockHttpServletResponse();
-		Saml2LogoutRequestBuilder<?> partial = mock(Saml2LogoutRequestBuilder.class, RETURNS_SELF);
-		given(partial.logoutRequest()).willReturn(logoutRequest);
-		willReturn(partial).given(this.resolver).resolveLogoutRequest(request, authentication);
-		this.handler.onLogoutSuccess(request, response, authentication);
-		String content = response.getHeader("Location");
-		assertThat(content).contains("SAMLRequest");
-		assertThat(content).startsWith(registration.getAssertingPartyDetails().getSingleLogoutServiceLocation());
-	}
-
-	@Test
-	public void doFilterWhenPostThenPostsToAssertingParty() throws Exception {
-		RelyingPartyRegistration registration = TestRelyingPartyRegistrations.full()
-				.assertingPartyDetails((party) -> party.singleLogoutServiceBinding(Saml2MessageBinding.POST)).build();
-		Authentication authentication = authentication(registration);
-		SecurityContextHolder.getContext().setAuthentication(authentication);
-		Saml2LogoutRequest logoutRequest = Saml2LogoutRequest.withRelyingPartyRegistration(registration)
-				.samlRequest("request").build();
-		MockHttpServletRequest request = new MockHttpServletRequest("POST", "/saml2/logout");
-		request.setServletPath("/saml2/logout");
-		MockHttpServletResponse response = new MockHttpServletResponse();
-		Saml2LogoutRequestBuilder<?> partial = mock(Saml2LogoutRequestBuilder.class, RETURNS_SELF);
-		given(partial.logoutRequest()).willReturn(logoutRequest);
-		willReturn(partial).given(this.resolver).resolveLogoutRequest(request, authentication);
-		this.handler.onLogoutSuccess(request, response, authentication);
-		String content = response.getContentAsString();
-		assertThat(content).contains("SAMLRequest");
-		assertThat(content).contains(registration.getAssertingPartyDetails().getSingleLogoutServiceLocation());
-	}
-
-	private Saml2Authentication authentication(RelyingPartyRegistration registration) {
-		return new Saml2Authentication(new DefaultSaml2AuthenticatedPrincipal("user", new HashMap<>()), "response",
-				new ArrayList<>(), registration.getRegistrationId());
-	}
-
-}

+ 0 - 122
saml2/saml2-service-provider/core/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutResponseFilterTests.java

@@ -1,122 +0,0 @@
-/*
- * Copyright 2002-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.provider.service.web.authentication.logout;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import org.springframework.mock.web.MockFilterChain;
-import org.springframework.mock.web.MockHttpServletRequest;
-import org.springframework.mock.web.MockHttpServletResponse;
-import org.springframework.security.authentication.TestingAuthenticationToken;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.web.authentication.logout.LogoutHandler;
-import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
-
-import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
-import static org.mockito.BDDMockito.mock;
-import static org.mockito.BDDMockito.verify;
-import static org.mockito.BDDMockito.willThrow;
-import static org.mockito.Mockito.verifyNoInteractions;
-
-public class Saml2LogoutResponseFilterTests {
-
-	private final LogoutHandler handler = mock(LogoutHandler.class);
-
-	private final LogoutSuccessHandler successHandler = mock(LogoutSuccessHandler.class);
-
-	private final Saml2LogoutResponseFilter filter = new Saml2LogoutResponseFilter(this.handler);
-
-	@Before
-	public void setUp() {
-		this.filter.setLogoutSuccessHandler(this.successHandler);
-	}
-
-	@After
-	public void tearDown() {
-		SecurityContextHolder.clearContext();
-	}
-
-	@Test
-	public void doFilterWhenSamlRequestMatchesThenLogout() throws Exception {
-		Authentication authentication = new TestingAuthenticationToken("user", "password");
-		SecurityContextHolder.getContext().setAuthentication(authentication);
-		MockHttpServletRequest request = new MockHttpServletRequest("POST", "/logout/saml2/slo");
-		request.setServletPath("/logout/saml2/slo");
-		request.setParameter("SAMLResponse", "response");
-		MockHttpServletResponse response = new MockHttpServletResponse();
-		this.filter.doFilterInternal(request, response, new MockFilterChain());
-		verify(this.handler).logout(request, response, authentication);
-		verify(this.successHandler).onLogoutSuccess(request, response, authentication);
-	}
-
-	@Test
-	public void doFilterWhenSamlResponseMatchesThenLogout() throws Exception {
-		Authentication authentication = new TestingAuthenticationToken("user", "password");
-		SecurityContextHolder.getContext().setAuthentication(authentication);
-		MockHttpServletRequest request = new MockHttpServletRequest("POST", "/logout/saml2/slo");
-		request.setServletPath("/logout/saml2/slo");
-		request.setParameter("SAMLResponse", "response");
-		MockHttpServletResponse response = new MockHttpServletResponse();
-		this.filter.doFilterInternal(request, response, new MockFilterChain());
-		verify(this.handler).logout(request, response, authentication);
-		verify(this.successHandler).onLogoutSuccess(request, response, authentication);
-	}
-
-	@Test
-	public void doFilterWhenRequestMismatchesThenNoLogout() throws Exception {
-		Authentication authentication = new TestingAuthenticationToken("user", "password");
-		SecurityContextHolder.getContext().setAuthentication(authentication);
-		MockHttpServletRequest request = new MockHttpServletRequest("POST", "/logout");
-		request.setServletPath("/logout");
-		request.setParameter("SAMLResponse", "response");
-		MockHttpServletResponse response = new MockHttpServletResponse();
-		this.filter.doFilterInternal(request, response, new MockFilterChain());
-		verifyNoInteractions(this.handler);
-		verifyNoInteractions(this.successHandler);
-	}
-
-	@Test
-	public void doFilterWhenNoSamlRequestOrResponseThenNoLogout() throws Exception {
-		Authentication authentication = new TestingAuthenticationToken("user", "password");
-		SecurityContextHolder.getContext().setAuthentication(authentication);
-		MockHttpServletRequest request = new MockHttpServletRequest("POST", "/logout/saml2/slo");
-		request.setServletPath("/logout/saml2");
-		MockHttpServletResponse response = new MockHttpServletResponse();
-		this.filter.doFilterInternal(request, response, new MockFilterChain());
-		verifyNoInteractions(this.handler);
-		verifyNoInteractions(this.successHandler);
-	}
-
-	@Test
-	public void doFilterWhenLogoutHandlerFailsThenNoSuccessHandler() {
-		Authentication authentication = new TestingAuthenticationToken("user", "password");
-		SecurityContextHolder.getContext().setAuthentication(authentication);
-		MockHttpServletRequest request = new MockHttpServletRequest("POST", "/logout/saml2/slo");
-		request.setServletPath("/logout/saml2/slo");
-		request.setParameter("SAMLResponse", "response");
-		MockHttpServletResponse response = new MockHttpServletResponse();
-		willThrow(RuntimeException.class).given(this.handler).logout(request, response, authentication);
-		assertThatExceptionOfType(RuntimeException.class)
-				.isThrownBy(() -> this.filter.doFilterInternal(request, response, new MockFilterChain()));
-		verify(this.handler).logout(request, response, authentication);
-		verifyNoInteractions(this.successHandler);
-	}
-
-}

+ 0 - 95
saml2/saml2-service-provider/core/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutResponseSuccessHandlerTests.java

@@ -1,95 +0,0 @@
-/*
- * Copyright 2002-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.provider.service.web.authentication.logout;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-
-import org.junit.Test;
-
-import org.springframework.mock.web.MockHttpServletRequest;
-import org.springframework.mock.web.MockHttpServletResponse;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.saml2.provider.service.authentication.DefaultSaml2AuthenticatedPrincipal;
-import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
-import org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutResponse;
-import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
-import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
-import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations;
-import org.springframework.security.saml2.provider.service.web.authentication.logout.Saml2LogoutResponseResolver.Saml2LogoutResponseBuilder;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.BDDMockito.RETURNS_SELF;
-import static org.mockito.BDDMockito.given;
-import static org.mockito.BDDMockito.mock;
-import static org.mockito.BDDMockito.willReturn;
-
-/**
- * Tests for {@link Saml2LogoutResponseSuccessHandler}
- *
- * @author Josh Cummings
- */
-public class Saml2LogoutResponseSuccessHandlerTests {
-
-	private final Saml2LogoutResponseResolver resolver = mock(Saml2LogoutResponseResolver.class);
-
-	private final Saml2LogoutResponseSuccessHandler handler = new Saml2LogoutResponseSuccessHandler(this.resolver);
-
-	@Test
-	public void doFilterWhenRedirectThenRedirectsToAssertingParty() throws Exception {
-		RelyingPartyRegistration registration = TestRelyingPartyRegistrations.full().build();
-		Authentication authentication = authentication(registration);
-		Saml2LogoutResponse logoutResponse = Saml2LogoutResponse.withRelyingPartyRegistration(registration)
-				.samlResponse("response").build();
-		MockHttpServletRequest request = new MockHttpServletRequest();
-		request.setAttribute(Saml2RequestAttributeNames.LOGOUT_REQUEST_ID, "id");
-		MockHttpServletResponse response = new MockHttpServletResponse();
-		Saml2LogoutResponseBuilder<?> partial = mock(Saml2LogoutResponseBuilder.class, RETURNS_SELF);
-		given(partial.logoutResponse()).willReturn(logoutResponse);
-		willReturn(partial).given(this.resolver).resolveLogoutResponse(request, authentication);
-		this.handler.onLogoutSuccess(request, response, authentication);
-		String content = response.getHeader("Location");
-		assertThat(content).contains("SAMLResponse");
-		assertThat(content)
-				.startsWith(registration.getAssertingPartyDetails().getSingleLogoutServiceResponseLocation());
-	}
-
-	@Test
-	public void doFilterWhenPostThenPostsToAssertingParty() throws Exception {
-		RelyingPartyRegistration registration = TestRelyingPartyRegistrations.full()
-				.assertingPartyDetails((party) -> party.singleLogoutServiceBinding(Saml2MessageBinding.POST)).build();
-		Authentication authentication = authentication(registration);
-		Saml2LogoutResponse logoutResponse = Saml2LogoutResponse.withRelyingPartyRegistration(registration)
-				.samlResponse("response").build();
-		MockHttpServletRequest request = new MockHttpServletRequest();
-		request.setAttribute(Saml2RequestAttributeNames.LOGOUT_REQUEST_ID, "id");
-		MockHttpServletResponse response = new MockHttpServletResponse();
-		Saml2LogoutResponseBuilder<?> partial = mock(Saml2LogoutResponseBuilder.class, RETURNS_SELF);
-		given(partial.logoutResponse()).willReturn(logoutResponse);
-		willReturn(partial).given(this.resolver).resolveLogoutResponse(request, authentication);
-		this.handler.onLogoutSuccess(request, response, authentication);
-		String content = response.getContentAsString();
-		assertThat(content).contains("SAMLResponse");
-		assertThat(content).contains(registration.getAssertingPartyDetails().getSingleLogoutServiceResponseLocation());
-	}
-
-	private Saml2Authentication authentication(RelyingPartyRegistration registration) {
-		return new Saml2Authentication(new DefaultSaml2AuthenticatedPrincipal("user", new HashMap<>()), "response",
-				new ArrayList<>(), registration.getRegistrationId());
-	}
-
-}

+ 0 - 91
saml2/saml2-service-provider/opensaml3/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSaml3LogoutRequestResolver.java

@@ -1,91 +0,0 @@
-/*
- * Copyright 2002-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.provider.service.web.authentication.logout;
-
-import java.time.Clock;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.joda.time.DateTime;
-
-import org.springframework.security.core.Authentication;
-import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
-import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
-import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver;
-import org.springframework.security.saml2.provider.service.web.authentication.logout.OpenSamlLogoutRequestResolver.OpenSamlLogoutRequestBuilder;
-import org.springframework.util.Assert;
-
-/**
- * A {@link Saml2LogoutRequestResolver} for resolving SAML 2.0 Logout Requests with
- * OpenSAML 3
- *
- * @author Josh Cummings
- * @since 5.5
- * @deprecated Because OpenSAML 3 has reached End-of-Life, please update to
- * {@code OpenSaml4LogoutRequestResolver}
- */
-public class OpenSaml3LogoutRequestResolver implements Saml2LogoutRequestResolver {
-
-	private final OpenSamlLogoutRequestResolver logoutRequestResolver;
-
-	private Clock clock = Clock.systemUTC();
-
-	/**
-	 * Construct a {@link OpenSaml3LogoutRequestResolver} with the provided parameters
-	 * @param relyingPartyRegistrationResolver a strategy for resolving a
-	 * {@link RelyingPartyRegistration}
-	 */
-	public OpenSaml3LogoutRequestResolver(RelyingPartyRegistrationResolver relyingPartyRegistrationResolver) {
-		this.logoutRequestResolver = new OpenSamlLogoutRequestResolver(relyingPartyRegistrationResolver);
-	}
-
-	/**
-	 * Prepare to create, sign, and serialize a SAML 2.0 Logout Request.
-	 *
-	 * By default, includes a {@code NameID} based on the {@link Authentication} instance
-	 * as well as the {@code Destination} and {@code Issuer} based on the
-	 * {@link RelyingPartyRegistration} derived from the {@link Authentication}. The
-	 * request also contains its issued {@link DateTime}.
-	 *
-	 * The {@link Authentication} must be of type {@link Saml2Authentication} in order to
-	 * look up the {@link RelyingPartyRegistration} that holds the signing key.
-	 * @param request the HTTP request
-	 * @param authentication the current principal details
-	 * @return a builder, useful for overriding any aspects of the SAML 2.0 Logout Request
-	 * that the resolver supplied
-	 */
-	@Override
-	public Saml2LogoutRequestBuilder<?> resolveLogoutRequest(HttpServletRequest request,
-			Authentication authentication) {
-		OpenSamlLogoutRequestBuilder builder = this.logoutRequestResolver.resolveLogoutRequest(request, authentication);
-		if (builder == null) {
-			return null;
-		}
-		return builder
-				.logoutRequest((logoutRequest) -> logoutRequest.setIssueInstant(new DateTime(this.clock.millis())));
-	}
-
-	/**
-	 * Use this {@link Clock} for generating the issued {@link DateTime}
-	 * @param clock the {@link Clock} to use
-	 */
-	public void setClock(Clock clock) {
-		Assert.notNull(clock, "clock must not be null");
-		this.clock = clock;
-	}
-
-}

+ 0 - 89
saml2/saml2-service-provider/opensaml3/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSaml3LogoutResponseResolver.java

@@ -1,89 +0,0 @@
-/*
- * Copyright 2002-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.provider.service.web.authentication.logout;
-
-import java.time.Clock;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.joda.time.DateTime;
-
-import org.springframework.security.core.Authentication;
-import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
-import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
-import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver;
-import org.springframework.security.saml2.provider.service.web.authentication.logout.OpenSamlLogoutResponseResolver.OpenSamlLogoutResponseBuilder;
-import org.springframework.util.Assert;
-
-/**
- * A {@link Saml2LogoutResponseResolver} for resolving SAML 2.0 Logout Responses with
- * OpenSAML 3
- *
- * @author Josh Cummings
- * @since 5.5
- * @deprecated Because OpenSAML 3 has reached End-of-Life, please update to
- * {@code OpenSaml4LogoutResponseResolver}
- */
-public class OpenSaml3LogoutResponseResolver implements Saml2LogoutResponseResolver {
-
-	private final OpenSamlLogoutResponseResolver logoutResponseResolver;
-
-	private Clock clock = Clock.systemUTC();
-
-	/**
-	 * Construct a {@link OpenSaml3LogoutResponseResolver} with the provided parameters
-	 * @param relyingPartyRegistrationResolver a strategy for resolving a
-	 * {@link RelyingPartyRegistration}
-	 */
-	public OpenSaml3LogoutResponseResolver(RelyingPartyRegistrationResolver relyingPartyRegistrationResolver) {
-		this.logoutResponseResolver = new OpenSamlLogoutResponseResolver(relyingPartyRegistrationResolver);
-	}
-
-	/**
-	 * Prepare to create, sign, and serialize a SAML 2.0 Logout Response.
-	 *
-	 * By default, includes a {@code RelayState} based on the {@link HttpServletRequest}
-	 * as well as the {@code Destination} and {@code Issuer} based on the
-	 * {@link RelyingPartyRegistration} derived from the {@link Authentication}. The
-	 * logout response also includes an issued {@link DateTime} and is marked as
-	 * {@code SUCCESS}.
-	 *
-	 * The {@link Authentication} must be of type {@link Saml2Authentication} in order to
-	 * look up the {@link RelyingPartyRegistration} that holds the signing key.
-	 * @param request the HTTP request
-	 * @param authentication the current principal details
-	 * @return a builder, useful for overriding any aspects of the SAML 2.0 Logout Request
-	 * that the resolver supplied
-	 */
-	@Override
-	public Saml2LogoutResponseBuilder<?> resolveLogoutResponse(HttpServletRequest request,
-			Authentication authentication) {
-		OpenSamlLogoutResponseBuilder builder = this.logoutResponseResolver.resolveLogoutResponse(request,
-				authentication);
-		if (builder == null) {
-			return null;
-		}
-		return builder
-				.logoutResponse((logoutResponse) -> logoutResponse.setIssueInstant(new DateTime(this.clock.millis())));
-	}
-
-	public void setClock(Clock clock) {
-		Assert.notNull(clock, "clock must not be null");
-		this.clock = clock;
-	}
-
-}

+ 0 - 87
saml2/saml2-service-provider/opensaml4/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSaml4LogoutRequestResolver.java

@@ -1,87 +0,0 @@
-/*
- * Copyright 2002-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.provider.service.web.authentication.logout;
-
-import java.time.Clock;
-import java.time.Instant;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.springframework.security.core.Authentication;
-import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
-import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
-import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver;
-import org.springframework.security.saml2.provider.service.web.authentication.logout.OpenSamlLogoutRequestResolver.OpenSamlLogoutRequestBuilder;
-import org.springframework.util.Assert;
-
-/**
- * A {@link Saml2LogoutRequestResolver} for resolving SAML 2.0 Logout Requests with
- * OpenSAML 4
- *
- * @author Josh Cummings
- * @since 5.5
- */
-public class OpenSaml4LogoutRequestResolver implements Saml2LogoutRequestResolver {
-
-	private final OpenSamlLogoutRequestResolver logoutRequestResolver;
-
-	private Clock clock = Clock.systemUTC();
-
-	/**
-	 * Construct a {@link OpenSaml4LogoutRequestResolver} with the provided parameters
-	 * @param relyingPartyRegistrationResolver a strategy for resolving a
-	 * {@link RelyingPartyRegistration}
-	 */
-	public OpenSaml4LogoutRequestResolver(RelyingPartyRegistrationResolver relyingPartyRegistrationResolver) {
-		this.logoutRequestResolver = new OpenSamlLogoutRequestResolver(relyingPartyRegistrationResolver);
-	}
-
-	/**
-	 * Prepare to create, sign, and serialize a SAML 2.0 Logout Request.
-	 *
-	 * By default, includes a {@code NameID} based on the {@link Authentication} instance
-	 * as well as the {@code Destination} and {@code Issuer} based on the
-	 * {@link RelyingPartyRegistration} derived from the {@link Authentication}. The
-	 * request also contains its issued {@link Instant}.
-	 *
-	 * The {@link Authentication} must be of type {@link Saml2Authentication} in order to
-	 * look up the {@link RelyingPartyRegistration} that holds the signing key.
-	 * @param request the HTTP request
-	 * @param authentication the current principal details
-	 * @return a builder, useful for overriding any aspects of the SAML 2.0 Logout Request
-	 * that the resolver supplied
-	 */
-	@Override
-	public Saml2LogoutRequestBuilder<?> resolveLogoutRequest(HttpServletRequest request,
-			Authentication authentication) {
-		OpenSamlLogoutRequestBuilder builder = this.logoutRequestResolver.resolveLogoutRequest(request, authentication);
-		if (builder == null) {
-			return null;
-		}
-		return builder.logoutRequest((logoutRequest) -> logoutRequest.setIssueInstant(Instant.now(this.clock)));
-	}
-
-	/**
-	 * Use this {@link Clock} for determining the issued {@link Instant}
-	 * @param clock the {@link Clock} to use
-	 */
-	public void setClock(Clock clock) {
-		Assert.notNull(clock, "clock must not be null");
-		this.clock = clock;
-	}
-
-}

+ 0 - 85
saml2/saml2-service-provider/opensaml4/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSaml4LogoutResponseResolver.java

@@ -1,85 +0,0 @@
-/*
- * Copyright 2002-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.security.saml2.provider.service.web.authentication.logout;
-
-import java.time.Clock;
-import java.time.Instant;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.springframework.security.core.Authentication;
-import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
-import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
-import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver;
-import org.springframework.security.saml2.provider.service.web.authentication.logout.OpenSamlLogoutResponseResolver.OpenSamlLogoutResponseBuilder;
-import org.springframework.util.Assert;
-
-/**
- * A {@link Saml2LogoutResponseResolver} for resolving SAML 2.0 Logout Responses with
- * OpenSAML 4
- *
- * @author Josh Cummings
- * @since 5.5
- */
-public class OpenSaml4LogoutResponseResolver implements Saml2LogoutResponseResolver {
-
-	private final OpenSamlLogoutResponseResolver logoutResponseResolver;
-
-	private Clock clock = Clock.systemUTC();
-
-	/**
-	 * Construct a {@link OpenSaml4LogoutResponseResolver} with the provided parameters
-	 * @param relyingPartyRegistrationResolver the strategy for resolving a
-	 * {@link RelyingPartyRegistration}
-	 */
-	public OpenSaml4LogoutResponseResolver(RelyingPartyRegistrationResolver relyingPartyRegistrationResolver) {
-		this.logoutResponseResolver = new OpenSamlLogoutResponseResolver(relyingPartyRegistrationResolver);
-	}
-
-	/**
-	 * Prepare to create, sign, and serialize a SAML 2.0 Logout Response.
-	 *
-	 * By default, includes a {@code RelayState} based on the {@link HttpServletRequest}
-	 * as well as the {@code Destination} and {@code Issuer} based on the
-	 * {@link RelyingPartyRegistration} derived from the {@link Authentication}. The
-	 * logout response also includes an issued {@link Instant} and is marked as
-	 * {@code SUCCESS}.
-	 *
-	 * The {@link Authentication} must be of type {@link Saml2Authentication} in order to
-	 * look up the {@link RelyingPartyRegistration} that holds the signing key.
-	 * @param request the HTTP request
-	 * @param authentication the current principal details
-	 * @return a builder, useful for overriding any aspects of the SAML 2.0 Logout Request
-	 * that the resolver supplied
-	 */
-	@Override
-	public Saml2LogoutResponseBuilder<?> resolveLogoutResponse(HttpServletRequest request,
-			Authentication authentication) {
-		OpenSamlLogoutResponseBuilder builder = this.logoutResponseResolver.resolveLogoutResponse(request,
-				authentication);
-		if (builder == null) {
-			return null;
-		}
-		return builder.logoutResponse((logoutResponse) -> logoutResponse.setIssueInstant(Instant.now(this.clock)));
-	}
-
-	public void setClock(Clock clock) {
-		Assert.notNull(clock, "clock must not be null");
-		this.clock = clock;
-	}
-
-}