Skip to content

Consider customization of Saml2LogoutRequestValidatorParametersResolver #16954

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -109,6 +109,7 @@
*
* @author Josh Cummings
* @author Ngoc Nhan
* @author Evgeniy Cheban
* @since 5.6
* @see Saml2LogoutConfigurer
*/
@@ -262,12 +263,25 @@ private Saml2LogoutRequestFilter createLogoutRequestProcessingFilter(
LogoutHandler[] logoutHandlers = this.logoutHandlers.toArray(new LogoutHandler[0]);
Saml2LogoutResponseResolver logoutResponseResolver = createSaml2LogoutResponseResolver(registrations);
Saml2LogoutRequestFilter filter = new Saml2LogoutRequestFilter(
createSaml2LogoutResponseParametersResolver(registrations),
getLogoutRequestParametersResolver(registrations),
this.logoutRequestConfigurer.logoutRequestValidator(), logoutResponseResolver, logoutHandlers);
filter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
return postProcess(filter);
}

private Saml2LogoutRequestValidatorParametersResolver getLogoutRequestParametersResolver(
RelyingPartyRegistrationRepository registrations) {
if (this.logoutRequestConfigurer.logoutRequestParametersResolver != null) {
return this.logoutRequestConfigurer.logoutRequestParametersResolver;
}
Saml2LogoutRequestValidatorParametersResolver logoutRequestResolver = getBeanOrNull(
Saml2LogoutRequestValidatorParametersResolver.class);
if (logoutRequestResolver != null) {
return logoutRequestResolver;
}
return createSaml2LogoutResponseParametersResolver(registrations);
}

private Saml2LogoutRequestValidatorParametersResolver createSaml2LogoutResponseParametersResolver(
RelyingPartyRegistrationRepository registrations) {
RequestMatcher requestMatcher = createLogoutRequestMatcher();
@@ -352,6 +366,8 @@ public final class LogoutRequestConfigurer {

private Saml2LogoutRequestResolver logoutRequestResolver;

private Saml2LogoutRequestValidatorParametersResolver logoutRequestParametersResolver;

private Saml2LogoutRequestRepository logoutRequestRepository = new HttpSessionLogoutRequestRepository();

LogoutRequestConfigurer() {
@@ -394,6 +410,20 @@ public LogoutRequestConfigurer logoutRequestResolver(Saml2LogoutRequestResolver
return this;
}

/**
* Use this {@link Saml2LogoutRequestValidatorParametersResolver} for resolving
* logout request and associated validation parameters.
* @param logoutRequestParametersResolver the
* {@link Saml2LogoutRequestValidatorParametersResolver} to use
* @return the {@link LogoutRequestConfigurer} for further customizations
* @since 6.5
*/
public LogoutRequestConfigurer logoutRequestParametersResolver(
Saml2LogoutRequestValidatorParametersResolver logoutRequestParametersResolver) {
this.logoutRequestParametersResolver = logoutRequestParametersResolver;
return this;
}

/**
* Use this {@link Saml2LogoutRequestRepository} for storing logout requests
* @param logoutRequestRepository the {@link Saml2LogoutRequestRepository} to use
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@@ -22,16 +22,20 @@ import org.springframework.security.saml2.provider.service.authentication.logout
import org.springframework.security.saml2.provider.service.web.authentication.logout.HttpSessionLogoutRequestRepository
import org.springframework.security.saml2.provider.service.web.authentication.logout.Saml2LogoutRequestRepository
import org.springframework.security.saml2.provider.service.web.authentication.logout.Saml2LogoutRequestResolver
import org.springframework.security.saml2.provider.service.web.authentication.logout.Saml2LogoutRequestValidatorParametersResolver

/**
* A Kotlin DSL to configure SAML 2.0 Logout Request components using idiomatic Kotlin code.
*
* @author Josh Cummings
* @author Evgeniy Cheban
* @since 6.3
* @property logoutUrl The URL by which the asserting party can send a SAML 2.0 Logout Request.
* The Asserting Party should use whatever HTTP method specified in {@link RelyingPartyRegistration#getSingleLogoutServiceBindings()}.
* @property logoutRequestValidator the [Saml2LogoutRequestValidator] to use for validating incoming {@code LogoutRequest}s.
* @property logoutRequestResolver the [Saml2LogoutRequestResolver] to use for generating outgoing {@code LogoutRequest}s.
* @property logoutRequestParametersResolver the [Saml2LogoutRequestValidatorParametersResolver] to use for resolving logout
* request and associated validation parameters.
* @property logoutRequestRepository the [Saml2LogoutRequestRepository] to use for storing outgoing {@code LogoutRequest}s for
* linking to the corresponding {@code LogoutResponse} from the asserting party
*/
@@ -40,13 +44,15 @@ class LogoutRequestDsl {
var logoutUrl = "/logout/saml2/slo"
var logoutRequestValidator: Saml2LogoutRequestValidator? = null
var logoutRequestResolver: Saml2LogoutRequestResolver? = null
var logoutRequestParametersResolver: Saml2LogoutRequestValidatorParametersResolver? = null
var logoutRequestRepository: Saml2LogoutRequestRepository = HttpSessionLogoutRequestRepository()

internal fun get(): (Saml2LogoutConfigurer<HttpSecurity>.LogoutRequestConfigurer) -> Unit {
return { logoutRequest ->
logoutUrl.also { logoutRequest.logoutUrl(logoutUrl) }
logoutRequestValidator?.also { logoutRequest.logoutRequestValidator(logoutRequestValidator) }
logoutRequestResolver?.also { logoutRequest.logoutRequestResolver(logoutRequestResolver) }
logoutRequestParametersResolver?.also { logoutRequest.logoutRequestParametersResolver(logoutRequestParametersResolver) }
logoutRequestRepository.also { logoutRequest.logoutRequestRepository(logoutRequestRepository) }
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2025 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.
@@ -70,6 +70,7 @@
import org.springframework.security.saml2.provider.service.web.authentication.logout.Saml2LogoutRequestFilter;
import org.springframework.security.saml2.provider.service.web.authentication.logout.Saml2LogoutRequestRepository;
import org.springframework.security.saml2.provider.service.web.authentication.logout.Saml2LogoutRequestResolver;
import org.springframework.security.saml2.provider.service.web.authentication.logout.Saml2LogoutRequestValidatorParametersResolver;
import org.springframework.security.saml2.provider.service.web.authentication.logout.Saml2LogoutResponseFilter;
import org.springframework.security.saml2.provider.service.web.authentication.logout.Saml2LogoutResponseResolver;
import org.springframework.security.web.SecurityFilterChain;
@@ -542,6 +543,22 @@ public void saml2LogoutWhenLogoutFilterPostProcessedThenUses() {

}

@Test
public void saml2LogoutWhenCustomLogoutRequestParametersResolverBeanThenUses() throws Exception {
this.spring.register(Saml2DefaultsWithLogoutRequestParametersResolverBeanConfig.class).autowire();
this.mvc.perform(post("/logout").with(authentication(this.user)).with(csrf()));
verify(Saml2DefaultsWithLogoutRequestParametersResolverBeanConfig.logoutRequestParametersResolver)
.resolve(any(), eq(this.user));
}

@Test
public void saml2LogoutWhenCustomLogoutRequestParametersResolverSetThenUses() throws Exception {
this.spring.register(Saml2DefaultsWithLogoutRequestParametersResolverSetConfig.class).autowire();
this.mvc.perform(post("/logout").with(authentication(this.user)).with(csrf()));
verify(Saml2DefaultsWithLogoutRequestParametersResolverSetConfig.logoutRequestParametersResolver).resolve(any(),
eq(this.user));
}

private <T> T getBean(Class<T> clazz) {
return this.spring.getContext().getBean(clazz);
}
@@ -723,6 +740,55 @@ Saml2LogoutResponseResolver logoutResponseResolver() {

}

@Configuration
@EnableWebSecurity
@Import(Saml2LoginConfigBeans.class)
static class Saml2DefaultsWithLogoutRequestParametersResolverBeanConfig {

static Saml2LogoutRequestValidatorParametersResolver logoutRequestParametersResolver = mock(
Saml2LogoutRequestValidatorParametersResolver.class);

@Bean
SecurityFilterChain web(HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeRequests((authorize) -> authorize.anyRequest().authenticated())
.saml2Login(withDefaults())
.saml2Logout(withDefaults());
return http.build();
// @formatter:on
}

@Bean
Saml2LogoutRequestValidatorParametersResolver logoutRequestParametersResolver() {
return logoutRequestParametersResolver;
}

}

@Configuration
@EnableWebSecurity
@Import(Saml2LoginConfigBeans.class)
static class Saml2DefaultsWithLogoutRequestParametersResolverSetConfig {

static Saml2LogoutRequestValidatorParametersResolver logoutRequestParametersResolver = mock(
Saml2LogoutRequestValidatorParametersResolver.class);

@Bean
SecurityFilterChain web(HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeRequests((authorize) -> authorize.anyRequest().authenticated())
.saml2Login(withDefaults())
.saml2Logout((logout) -> logout
.logoutRequest((logoutRequest) -> logoutRequest
.logoutRequestParametersResolver(logoutRequestParametersResolver)));
return http.build();
// @formatter:on
}

}

static class Saml2LoginConfigBeans {

@Bean