Skip to content

Commit 6f52bab

Browse files
committed
Add Saml2LogoutConfigurer
Closes gh-9497
1 parent d19ff12 commit 6f52bab

File tree

5 files changed

+1314
-119
lines changed

5 files changed

+1314
-119
lines changed

config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer;
6565
import org.springframework.security.config.annotation.web.configurers.openid.OpenIDLoginConfigurer;
6666
import org.springframework.security.config.annotation.web.configurers.saml2.Saml2LoginConfigurer;
67+
import org.springframework.security.config.annotation.web.configurers.saml2.Saml2LogoutConfigurer;
6768
import org.springframework.security.core.Authentication;
6869
import org.springframework.security.core.context.SecurityContext;
6970
import org.springframework.security.core.context.SecurityContextHolder;
@@ -2121,6 +2122,142 @@ public HttpSecurity saml2Login(Customizer<Saml2LoginConfigurer<HttpSecurity>> sa
21212122
return HttpSecurity.this;
21222123
}
21232124

2125+
/**
2126+
* Configures logout support for an SAML 2.0 Relying Party. <br>
2127+
* <br>
2128+
*
2129+
* Implements the <b>Single Logout Profile, using POST and REDIRECT bindings</b>, as
2130+
* documented in the
2131+
* <a target="_blank" href="https://docs.oasis-open.org/security/saml/">SAML V2.0
2132+
* Core,Profiles and Bindings</a> specifications. <br>
2133+
* <br>
2134+
*
2135+
* As a prerequisite to using this feature, is that you have a SAML v2.0 Asserting
2136+
* Party to sent a logout request to. The representation of the relying party and the
2137+
* asserting party is contained within {@link RelyingPartyRegistration}. <br>
2138+
* <br>
2139+
*
2140+
* {@link RelyingPartyRegistration}(s) are composed within a
2141+
* {@link RelyingPartyRegistrationRepository}, which is <b>required</b> and must be
2142+
* registered with the {@link ApplicationContext} or configured via
2143+
* <code>saml2Logout().relyingPartyRegistrationRepository(..)</code>. <br>
2144+
* <br>
2145+
*
2146+
* The default configuration provides an auto-generated logout endpoint at
2147+
* <code>&quot;/saml2/logout&quot;</code> and redirects to <code>/login?logout</code>
2148+
* when logout completes. <br>
2149+
* <br>
2150+
*
2151+
* <p>
2152+
* <h2>Example Configuration</h2>
2153+
*
2154+
* The following example shows the minimal configuration required, using SimpleSamlPhp
2155+
* as the asserting party.
2156+
*
2157+
* <pre>
2158+
* &#064;EnableWebSecurity
2159+
* &#064;Configuration
2160+
* public class Saml2LogoutSecurityConfig {
2161+
* &#064;Bean
2162+
* public SecurityFilterChain web(HttpSecurity http) throws Exception {
2163+
* http
2164+
* .authorizeRequests((authorize) -> authorize
2165+
* .anyRequest().authenticated()
2166+
* )
2167+
* .saml2Login(withDefaults())
2168+
* .saml2Logout(withDefaults());
2169+
* return http.build();
2170+
* }
2171+
*
2172+
* &#064;Bean
2173+
* public RelyingPartyRegistrationRepository relyingPartyRegistrationRepository() {
2174+
* RelyingPartyRegistration registration = RelyingPartyRegistrations
2175+
* .withMetadataLocation("https://ap.example.org/metadata")
2176+
* .registrationId("simple")
2177+
* .build();
2178+
* return new InMemoryRelyingPartyRegistrationRepository(registration);
2179+
* }
2180+
* }
2181+
* </pre>
2182+
*
2183+
* <p>
2184+
* @return the {@link Saml2LoginConfigurer} for further customizations
2185+
* @throws Exception
2186+
* @since 5.5
2187+
*/
2188+
public HttpSecurity saml2Logout(Customizer<Saml2LogoutConfigurer<HttpSecurity>> saml2LogoutCustomizer)
2189+
throws Exception {
2190+
saml2LogoutCustomizer.customize(getOrApply(new Saml2LogoutConfigurer<>(getContext())));
2191+
return HttpSecurity.this;
2192+
}
2193+
2194+
/**
2195+
* Configures logout support for an SAML 2.0 Relying Party. <br>
2196+
* <br>
2197+
*
2198+
* Implements the <b>Single Logout Profile, using POST and REDIRECT bindings</b>, as
2199+
* documented in the
2200+
* <a target="_blank" href="https://docs.oasis-open.org/security/saml/">SAML V2.0
2201+
* Core,Profiles and Bindings</a> specifications. <br>
2202+
* <br>
2203+
*
2204+
* As a prerequisite to using this feature, is that you have a SAML v2.0 Asserting
2205+
* Party to sent a logout request to. The representation of the relying party and the
2206+
* asserting party is contained within {@link RelyingPartyRegistration}. <br>
2207+
* <br>
2208+
*
2209+
* {@link RelyingPartyRegistration}(s) are composed within a
2210+
* {@link RelyingPartyRegistrationRepository}, which is <b>required</b> and must be
2211+
* registered with the {@link ApplicationContext} or configured via
2212+
* <code>saml2Logout().relyingPartyRegistrationRepository(..)</code>. <br>
2213+
* <br>
2214+
*
2215+
* The default configuration provides an auto-generated logout endpoint at
2216+
* <code>&quot;/saml2/logout&quot;</code> and redirects to <code>/login?logout</code>
2217+
* when logout completes. <br>
2218+
* <br>
2219+
*
2220+
* <p>
2221+
* <h2>Example Configuration</h2>
2222+
*
2223+
* The following example shows the minimal configuration required, using SimpleSamlPhp
2224+
* as the asserting party.
2225+
*
2226+
* <pre>
2227+
* &#064;EnableWebSecurity
2228+
* &#064;Configuration
2229+
* public class Saml2LogoutSecurityConfig {
2230+
* &#064;Bean
2231+
* public SecurityFilterChain web(HttpSecurity http) throws Exception {
2232+
* http
2233+
* .authorizeRequests((authorize) -> authorize
2234+
* .anyRequest().authenticated()
2235+
* )
2236+
* .saml2Login(withDefaults())
2237+
* .saml2Logout(withDefaults());
2238+
* return http.build();
2239+
* }
2240+
*
2241+
* &#064;Bean
2242+
* public RelyingPartyRegistrationRepository relyingPartyRegistrationRepository() {
2243+
* RelyingPartyRegistration registration = RelyingPartyRegistrations
2244+
* .withMetadataLocation("https://ap.example.org/metadata")
2245+
* .registrationId("simple")
2246+
* .build();
2247+
* return new InMemoryRelyingPartyRegistrationRepository(registration);
2248+
* }
2249+
* }
2250+
* </pre>
2251+
*
2252+
* <p>
2253+
* @return the {@link Saml2LoginConfigurer} for further customizations
2254+
* @throws Exception
2255+
* @since 5.5
2256+
*/
2257+
public Saml2LogoutConfigurer<HttpSecurity> saml2Logout() throws Exception {
2258+
return getOrApply(new Saml2LogoutConfigurer<>(getContext()));
2259+
}
2260+
21242261
/**
21252262
* Configures authentication support using an OAuth 2.0 and/or OpenID Connect 1.0
21262263
* Provider. <br>

config/src/main/java/org/springframework/security/config/annotation/web/configurers/saml2/Saml2LoginConfigurer.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,10 @@ public void init(B http) throws Exception {
221221
// Setup auto-redirect to provider login page
222222
// when only 1 IDP is configured
223223
this.updateAuthenticationDefaults();
224+
Saml2LogoutConfigurer<B> logoutConfigurer = http.getConfigurer(Saml2LogoutConfigurer.class);
225+
if (logoutConfigurer != null && !logoutConfigurer.isCustomLogoutSuccess()) {
226+
logoutConfigurer.logoutSuccessUrl("/login?logout");
227+
}
224228
this.updateAccessDefaults(http);
225229
String loginUrl = providerUrlMap.entrySet().iterator().next().getKey();
226230
final LoginUrlAuthenticationEntryPoint entryPoint = new LoginUrlAuthenticationEntryPoint(loginUrl);

0 commit comments

Comments
 (0)