add SAML authentication request support to login configurer

Closes gh-8873
This commit is contained in:
Houssem BELHADJ AHMED 2022-06-05 16:36:42 +02:00 committed by Josh Cummings
parent 33104269d6
commit f4049c18b1
4 changed files with 64 additions and 5 deletions

View File

@ -109,7 +109,7 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
private String loginPage;
private String authenticationRequestUri = "/saml2/authenticate/{registrationId}";
private String authenticationRequestUri = Saml2AuthenticationRequestResolver.DEFAULT_AUTHENTICATION_REQUEST_URI;
private Saml2AuthenticationRequestResolver authenticationRequestResolver;
@ -186,6 +186,24 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
return this;
}
/**
* Customize the URL that the SAML Authentication Request will be sent to.
* @param authenticationRequestUri the URI to use for the SAML 2.0 Authentication
* Request
* @return the {@link Saml2LoginConfigurer} for further configuration
* @since 6.0
*/
public Saml2LoginConfigurer<B> authenticationRequestUri(String authenticationRequestUri) {
// OpenSAML 3 is no longer supported by spring security
if (version().startsWith("3")) {
return this;
}
Assert.state(authenticationRequestUri.contains("{registrationId}"),
"authenticationRequestUri must contain {registrationId} path variable");
this.authenticationRequestUri = authenticationRequestUri;
return this;
}
/**
* Specifies the URL to validate the credentials. If specified a custom URL, consider
* specifying a custom {@link AuthenticationConverter} via
@ -307,7 +325,11 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
return bean;
}
if (version().startsWith("4")) {
return new OpenSaml4AuthenticationRequestResolver(relyingPartyRegistrationResolver(http));
OpenSaml4AuthenticationRequestResolver openSaml4AuthenticationRequestResolver = new OpenSaml4AuthenticationRequestResolver(
relyingPartyRegistrationResolver(http));
openSaml4AuthenticationRequestResolver
.setRequestMatcher(new AntPathRequestMatcher(this.authenticationRequestUri));
return openSaml4AuthenticationRequestResolver;
}
return new OpenSaml3AuthenticationRequestResolver(relyingPartyRegistrationResolver(http));
}

View File

@ -297,6 +297,17 @@ public class Saml2LoginConfigurerTests {
verify(repository).removeAuthenticationRequest(any(HttpServletRequest.class), any(HttpServletResponse.class));
}
@Test
public void authenticationRequestWhenCustomAuthenticationRequestUriRepositoryThenUses() throws Exception {
this.spring.register(CustomAuthenticationRequestUriCustomAuthenticationConverter.class).autowire();
MockHttpServletRequestBuilder request = get("/custom/auth/registration-id");
this.mvc.perform(request).andExpect(status().isFound());
Saml2AuthenticationRequestRepository<AbstractSaml2AuthenticationRequest> repository = this.spring.getContext()
.getBean(Saml2AuthenticationRequestRepository.class);
verify(repository).saveAuthenticationRequest(any(AbstractSaml2AuthenticationRequest.class),
any(HttpServletRequest.class), any(HttpServletResponse.class));
}
@Test
public void saml2LoginWhenLoginProcessingUrlWithoutRegistrationIdAndDefaultAuthenticationConverterThenValidates() {
assertThatExceptionOfType(BeanCreationException.class)
@ -601,6 +612,30 @@ public class Saml2LoginConfigurerTests {
}
@EnableWebSecurity
@Import(Saml2LoginConfigBeans.class)
static class CustomAuthenticationRequestUriCustomAuthenticationConverter {
private final Saml2AuthenticationRequestRepository<AbstractSaml2AuthenticationRequest> repository = mock(
Saml2AuthenticationRequestRepository.class);
@Bean
Saml2AuthenticationRequestRepository<AbstractSaml2AuthenticationRequest> authenticationRequestRepository() {
return this.repository;
}
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeRequests((authz) -> authz.anyRequest().authenticated())
.saml2Login((saml2) -> saml2.authenticationRequestUri("/custom/auth/{registrationId}"));
// @formatter:on
return http.build();
}
}
@EnableWebSecurity
@Import(Saml2LoginConfigBeans.class)
static class CustomLoginProcessingUrlCustomAuthenticationConverter {

View File

@ -59,9 +59,6 @@ class OpenSamlAuthenticationRequestResolver {
static {
OpenSamlInitializationService.initialize();
}
private final RequestMatcher requestMatcher = new AntPathRequestMatcher("/saml2/authenticate/{registrationId}");
private final RelyingPartyRegistrationResolver relyingPartyRegistrationResolver;
private final AuthnRequestBuilder authnRequestBuilder;
@ -72,6 +69,9 @@ class OpenSamlAuthenticationRequestResolver {
private final NameIDBuilder nameIdBuilder;
private RequestMatcher requestMatcher = new AntPathRequestMatcher(
Saml2AuthenticationRequestResolver.DEFAULT_AUTHENTICATION_REQUEST_URI);
private Converter<HttpServletRequest, String> relayStateResolver = (request) -> UUID.randomUUID().toString();
/**

View File

@ -29,6 +29,8 @@ import org.springframework.security.saml2.provider.service.authentication.Abstra
*/
public interface Saml2AuthenticationRequestResolver {
String DEFAULT_AUTHENTICATION_REQUEST_URI = "/saml2/authenticate/{registrationId}";
<T extends AbstractSaml2AuthenticationRequest> T resolve(HttpServletRequest request);
}