add SAML authentication request support to login configurer
Closes gh-8873
This commit is contained in:
parent
33104269d6
commit
f4049c18b1
|
@ -109,7 +109,7 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
||||||
|
|
||||||
private String loginPage;
|
private String loginPage;
|
||||||
|
|
||||||
private String authenticationRequestUri = "/saml2/authenticate/{registrationId}";
|
private String authenticationRequestUri = Saml2AuthenticationRequestResolver.DEFAULT_AUTHENTICATION_REQUEST_URI;
|
||||||
|
|
||||||
private Saml2AuthenticationRequestResolver authenticationRequestResolver;
|
private Saml2AuthenticationRequestResolver authenticationRequestResolver;
|
||||||
|
|
||||||
|
@ -186,6 +186,24 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
||||||
return this;
|
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
|
* Specifies the URL to validate the credentials. If specified a custom URL, consider
|
||||||
* specifying a custom {@link AuthenticationConverter} via
|
* specifying a custom {@link AuthenticationConverter} via
|
||||||
|
@ -307,7 +325,11 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
||||||
return bean;
|
return bean;
|
||||||
}
|
}
|
||||||
if (version().startsWith("4")) {
|
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));
|
return new OpenSaml3AuthenticationRequestResolver(relyingPartyRegistrationResolver(http));
|
||||||
}
|
}
|
||||||
|
|
|
@ -297,6 +297,17 @@ public class Saml2LoginConfigurerTests {
|
||||||
verify(repository).removeAuthenticationRequest(any(HttpServletRequest.class), any(HttpServletResponse.class));
|
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
|
@Test
|
||||||
public void saml2LoginWhenLoginProcessingUrlWithoutRegistrationIdAndDefaultAuthenticationConverterThenValidates() {
|
public void saml2LoginWhenLoginProcessingUrlWithoutRegistrationIdAndDefaultAuthenticationConverterThenValidates() {
|
||||||
assertThatExceptionOfType(BeanCreationException.class)
|
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
|
@EnableWebSecurity
|
||||||
@Import(Saml2LoginConfigBeans.class)
|
@Import(Saml2LoginConfigBeans.class)
|
||||||
static class CustomLoginProcessingUrlCustomAuthenticationConverter {
|
static class CustomLoginProcessingUrlCustomAuthenticationConverter {
|
||||||
|
|
|
@ -59,9 +59,6 @@ class OpenSamlAuthenticationRequestResolver {
|
||||||
static {
|
static {
|
||||||
OpenSamlInitializationService.initialize();
|
OpenSamlInitializationService.initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
private final RequestMatcher requestMatcher = new AntPathRequestMatcher("/saml2/authenticate/{registrationId}");
|
|
||||||
|
|
||||||
private final RelyingPartyRegistrationResolver relyingPartyRegistrationResolver;
|
private final RelyingPartyRegistrationResolver relyingPartyRegistrationResolver;
|
||||||
|
|
||||||
private final AuthnRequestBuilder authnRequestBuilder;
|
private final AuthnRequestBuilder authnRequestBuilder;
|
||||||
|
@ -72,6 +69,9 @@ class OpenSamlAuthenticationRequestResolver {
|
||||||
|
|
||||||
private final NameIDBuilder nameIdBuilder;
|
private final NameIDBuilder nameIdBuilder;
|
||||||
|
|
||||||
|
private RequestMatcher requestMatcher = new AntPathRequestMatcher(
|
||||||
|
Saml2AuthenticationRequestResolver.DEFAULT_AUTHENTICATION_REQUEST_URI);
|
||||||
|
|
||||||
private Converter<HttpServletRequest, String> relayStateResolver = (request) -> UUID.randomUUID().toString();
|
private Converter<HttpServletRequest, String> relayStateResolver = (request) -> UUID.randomUUID().toString();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -29,6 +29,8 @@ import org.springframework.security.saml2.provider.service.authentication.Abstra
|
||||||
*/
|
*/
|
||||||
public interface Saml2AuthenticationRequestResolver {
|
public interface Saml2AuthenticationRequestResolver {
|
||||||
|
|
||||||
|
String DEFAULT_AUTHENTICATION_REQUEST_URI = "/saml2/authenticate/{registrationId}";
|
||||||
|
|
||||||
<T extends AbstractSaml2AuthenticationRequest> T resolve(HttpServletRequest request);
|
<T extends AbstractSaml2AuthenticationRequest> T resolve(HttpServletRequest request);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue