Add SecurityContextHolderStrategy Java Configuration for Saml2
Issue gh-11061
This commit is contained in:
parent
e90a11b1c0
commit
19181a5afd
|
@ -243,6 +243,7 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|||
relyingPartyRegistrationRepository(http);
|
||||
this.saml2WebSsoAuthenticationFilter = new Saml2WebSsoAuthenticationFilter(getAuthenticationConverter(http),
|
||||
this.loginProcessingUrl);
|
||||
this.saml2WebSsoAuthenticationFilter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
|
||||
setAuthenticationRequestRepository(http, this.saml2WebSsoAuthenticationFilter);
|
||||
setAuthenticationFilter(this.saml2WebSsoAuthenticationFilter);
|
||||
super.loginProcessingUrl(this.loginProcessingUrl);
|
||||
|
|
|
@ -31,7 +31,7 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
|||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||
import org.springframework.security.config.annotation.web.configurers.LogoutConfigurer;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal;
|
||||
import org.springframework.security.saml2.provider.service.authentication.logout.OpenSamlLogoutRequestValidator;
|
||||
import org.springframework.security.saml2.provider.service.authentication.logout.OpenSamlLogoutResponseValidator;
|
||||
|
@ -248,6 +248,7 @@ public final class Saml2LogoutConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
Saml2LogoutRequestFilter filter = new Saml2LogoutRequestFilter(registrations,
|
||||
this.logoutRequestConfigurer.logoutRequestValidator(), logoutResponseResolver, logoutHandlers);
|
||||
filter.setLogoutRequestMatcher(createLogoutRequestMatcher());
|
||||
filter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
|
||||
return postProcess(filter);
|
||||
}
|
||||
|
||||
|
@ -271,7 +272,7 @@ public final class Saml2LogoutConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
|
||||
private RequestMatcher createLogoutMatcher() {
|
||||
RequestMatcher logout = new AntPathRequestMatcher(this.logoutUrl, "POST");
|
||||
RequestMatcher saml2 = new Saml2RequestMatcher();
|
||||
RequestMatcher saml2 = new Saml2RequestMatcher(getSecurityContextHolderStrategy());
|
||||
return new AndRequestMatcher(logout, saml2);
|
||||
}
|
||||
|
||||
|
@ -464,9 +465,15 @@ public final class Saml2LogoutConfigurer<H extends HttpSecurityBuilder<H>>
|
|||
|
||||
private static class Saml2RequestMatcher implements RequestMatcher {
|
||||
|
||||
private final SecurityContextHolderStrategy securityContextHolderStrategy;
|
||||
|
||||
Saml2RequestMatcher(SecurityContextHolderStrategy securityContextHolderStrategy) {
|
||||
this.securityContextHolderStrategy = securityContextHolderStrategy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(HttpServletRequest request) {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
Authentication authentication = this.securityContextHolderStrategy.getContext().getAuthentication();
|
||||
if (authentication == null) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ import org.springframework.mock.web.MockHttpSession;
|
|||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.AuthenticationServiceException;
|
||||
import org.springframework.security.config.Customizer;
|
||||
import org.springframework.security.config.annotation.SecurityContextChangedListenerConfig;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.test.SpringTestContext;
|
||||
|
@ -53,6 +54,8 @@ import org.springframework.security.core.Authentication;
|
|||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContextChangedListener;
|
||||
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||
import org.springframework.security.saml2.core.Saml2ErrorCodes;
|
||||
import org.springframework.security.saml2.core.Saml2Utils;
|
||||
import org.springframework.security.saml2.core.TestSaml2X509Credentials;
|
||||
|
@ -91,10 +94,13 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.springframework.security.config.Customizer.withDefaults;
|
||||
import static org.springframework.security.config.annotation.SecurityContextChangedListenerArgumentMatchers.setAuthentication;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
|
@ -162,6 +168,26 @@ public class Saml2LoginConfigurerTests {
|
|||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saml2LoginWhenCustomSecurityContextHolderStrategyThenUses() throws Exception {
|
||||
this.spring
|
||||
.register(Saml2LoginConfig.class, SecurityContextChangedListenerConfig.class, ResourceController.class)
|
||||
.autowire();
|
||||
// @formatter:off
|
||||
MockHttpSession session = (MockHttpSession) this.mvc
|
||||
.perform(post("/login/saml2/sso/registration-id")
|
||||
.param("SAMLResponse", SIGNED_RESPONSE))
|
||||
.andExpect(redirectedUrl("/")).andReturn().getRequest().getSession(false);
|
||||
this.mvc.perform(get("/").session(session))
|
||||
.andExpect(content().string("test@saml.user"));
|
||||
// @formatter:on
|
||||
SecurityContextHolderStrategy strategy = this.spring.getContext().getBean(SecurityContextHolderStrategy.class);
|
||||
verify(strategy, atLeastOnce()).getContext();
|
||||
SecurityContextChangedListener listener = this.spring.getContext()
|
||||
.getBean(SecurityContextChangedListener.class);
|
||||
verify(listener, times(2)).securityContextChanged(setAuthentication(Saml2Authentication.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saml2LoginWhenConfiguringAuthenticationManagerThenTheManagerIsUsed() throws Exception {
|
||||
// setup application context
|
||||
|
|
|
@ -43,11 +43,13 @@ import org.springframework.mock.web.MockHttpServletResponse;
|
|||
import org.springframework.mock.web.MockHttpSession;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
import org.springframework.security.config.annotation.SecurityContextChangedListenerConfig;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.test.SpringTestContext;
|
||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||
import org.springframework.security.saml2.core.Saml2Utils;
|
||||
import org.springframework.security.saml2.core.Saml2X509Credential;
|
||||
import org.springframework.security.saml2.core.TestSaml2X509Credentials;
|
||||
|
@ -271,6 +273,24 @@ public class Saml2LogoutConfigurerTests {
|
|||
verify(getBean(LogoutHandler.class)).logout(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saml2LogoutRequestWhenCustomSecurityContextHolderStrategyThenUses() throws Exception {
|
||||
this.spring.register(Saml2LogoutDefaultsConfig.class, SecurityContextChangedListenerConfig.class).autowire();
|
||||
DefaultSaml2AuthenticatedPrincipal principal = new DefaultSaml2AuthenticatedPrincipal("user",
|
||||
Collections.emptyMap());
|
||||
principal.setRelyingPartyRegistrationId("get");
|
||||
Saml2Authentication user = new Saml2Authentication(principal, "response",
|
||||
AuthorityUtils.createAuthorityList("ROLE_USER"));
|
||||
MvcResult result = this.mvc.perform(get("/logout/saml2/slo").param("SAMLRequest", this.apLogoutRequest)
|
||||
.param("RelayState", this.apLogoutRequestRelayState).param("SigAlg", this.apLogoutRequestSigAlg)
|
||||
.param("Signature", this.apLogoutRequestSignature).with(samlQueryString()).with(authentication(user)))
|
||||
.andExpect(status().isFound()).andReturn();
|
||||
String location = result.getResponse().getHeader("Location");
|
||||
assertThat(location).startsWith("https://ap.example.org/logout/saml2/response");
|
||||
verify(getBean(LogoutHandler.class)).logout(any(), any(), any());
|
||||
verify(getBean(SecurityContextHolderStrategy.class), atLeastOnce()).getContext();
|
||||
}
|
||||
|
||||
// gh-11235
|
||||
@Test
|
||||
public void saml2LogoutRequestWhenLowercaseEncodingThenLogsOutAndSendsLogoutResponse() throws Exception {
|
||||
|
|
Loading…
Reference in New Issue