Skip to content

Commit

Permalink
Remove SAML Deprecations
Browse files Browse the repository at this point in the history
Closes gh-11077
  • Loading branch information
marcusdacoregio committed May 6, 2022
1 parent 195d767 commit 995b291
Show file tree
Hide file tree
Showing 39 changed files with 156 additions and 3,391 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,18 @@
import org.springframework.security.core.Authentication;
import org.springframework.security.saml2.provider.service.authentication.AbstractSaml2AuthenticationRequest;
import org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider;
import org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationRequestFactory;
import org.springframework.security.saml2.provider.service.authentication.OpenSamlAuthenticationProvider;
import org.springframework.security.saml2.provider.service.authentication.OpenSamlAuthenticationRequestFactory;
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationRequestFactory;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
import org.springframework.security.saml2.provider.service.servlet.filter.Saml2WebSsoAuthenticationFilter;
import org.springframework.security.saml2.provider.service.servlet.filter.Saml2WebSsoAuthenticationRequestFilter;
import org.springframework.security.saml2.provider.service.web.DefaultRelyingPartyRegistrationResolver;
import org.springframework.security.saml2.provider.service.web.DefaultSaml2AuthenticationRequestContextResolver;
import org.springframework.security.saml2.provider.service.web.HttpSessionSaml2AuthenticationRequestRepository;
import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver;
import org.springframework.security.saml2.provider.service.web.Saml2AuthenticationRequestContextResolver;
import org.springframework.security.saml2.provider.service.web.Saml2AuthenticationRequestRepository;
import org.springframework.security.saml2.provider.service.web.Saml2AuthenticationTokenConverter;
import org.springframework.security.saml2.provider.service.web.authentication.OpenSaml3AuthenticationRequestResolver;
import org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver;
import org.springframework.security.saml2.provider.service.web.authentication.Saml2AuthenticationRequestResolver;
import org.springframework.security.web.authentication.AuthenticationConverter;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
Expand Down Expand Up @@ -87,7 +84,6 @@
*
* <ul>
* <li>{@link RelyingPartyRegistrationRepository} (required)</li>
* <li>{@link Saml2AuthenticationRequestFactory} (optional)</li>
* </ul>
*
* <h2>Shared Objects Used</h2>
Expand All @@ -96,7 +92,6 @@
*
* <ul>
* <li>{@link RelyingPartyRegistrationRepository} (required)</li>
* <li>{@link Saml2AuthenticationRequestFactory} (optional)</li>
* <li>{@link DefaultLoginPageGeneratingFilter} - if {@link #loginPage(String)} is not
* configured and {@code DefaultLoginPageGeneratingFilter} is available, than a default
* login page will be made available</li>
Expand Down Expand Up @@ -300,42 +295,21 @@ private void setAuthenticationRequestRepository(B http,

private Saml2WebSsoAuthenticationRequestFilter getAuthenticationRequestFilter(B http) {
Saml2AuthenticationRequestResolver authenticationRequestResolver = getAuthenticationRequestResolver(http);
if (authenticationRequestResolver != null) {
return new Saml2WebSsoAuthenticationRequestFilter(authenticationRequestResolver);
}
return new Saml2WebSsoAuthenticationRequestFilter(getAuthenticationRequestContextResolver(http),
getAuthenticationRequestFactory(http));
return new Saml2WebSsoAuthenticationRequestFilter(authenticationRequestResolver);
}

private Saml2AuthenticationRequestResolver getAuthenticationRequestResolver(B http) {
if (this.authenticationRequestResolver != null) {
return this.authenticationRequestResolver;
}
return getBeanOrNull(http, Saml2AuthenticationRequestResolver.class);
}

private Saml2AuthenticationRequestFactory getAuthenticationRequestFactory(B http) {
Saml2AuthenticationRequestFactory resolver = getSharedOrBean(http, Saml2AuthenticationRequestFactory.class);
if (resolver != null) {
return resolver;
Saml2AuthenticationRequestResolver bean = getBeanOrNull(http, Saml2AuthenticationRequestResolver.class);
if (bean != null) {
return bean;
}
if (version().startsWith("4")) {
return new OpenSaml4AuthenticationRequestFactory();
}
else {
return new OpenSamlAuthenticationRequestFactory();
}
}

private Saml2AuthenticationRequestContextResolver getAuthenticationRequestContextResolver(B http) {
Saml2AuthenticationRequestContextResolver resolver = getBeanOrNull(http,
Saml2AuthenticationRequestContextResolver.class);
if (resolver != null) {
return resolver;
return new OpenSaml4AuthenticationRequestResolver(relyingPartyRegistrationResolver(http));
}
RelyingPartyRegistrationResolver registrationResolver = new DefaultRelyingPartyRegistrationResolver(
this.relyingPartyRegistrationRepository);
return new DefaultSaml2AuthenticationRequestContextResolver(registrationResolver);
return new OpenSaml3AuthenticationRequestResolver(relyingPartyRegistrationResolver(http));
}

private AuthenticationConverter getAuthenticationConverter(B http) {
Expand All @@ -348,8 +322,7 @@ private AuthenticationConverter getAuthenticationConverter(B http) {
Assert.state(this.loginProcessingUrl.contains("{registrationId}"),
"loginProcessingUrl must contain {registrationId} path variable");
return new Saml2AuthenticationTokenConverter(
(RelyingPartyRegistrationResolver) new DefaultRelyingPartyRegistrationResolver(
this.relyingPartyRegistrationRepository));
new DefaultRelyingPartyRegistrationResolver(this.relyingPartyRegistrationRepository));
}
return authenticationConverterBean;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import java.io.IOException;
import java.net.URLDecoder;
import java.time.Duration;
import java.time.Instant;
import java.util.Base64;
import java.util.Collection;
import java.util.Collections;
Expand All @@ -34,7 +33,6 @@
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.opensaml.saml.saml2.core.Assertion;
import org.opensaml.saml.saml2.core.AuthnRequest;

import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down Expand Up @@ -68,23 +66,17 @@
import org.springframework.security.saml2.core.TestSaml2X509Credentials;
import org.springframework.security.saml2.provider.service.authentication.AbstractSaml2AuthenticationRequest;
import org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationProvider;
import org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationRequestFactory;
import org.springframework.security.saml2.provider.service.authentication.OpenSamlAuthenticationProvider;
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal;
import org.springframework.security.saml2.provider.service.authentication.Saml2Authentication;
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException;
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationRequestContext;
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationRequestFactory;
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationToken;
import org.springframework.security.saml2.provider.service.authentication.TestOpenSamlObjects;
import org.springframework.security.saml2.provider.service.authentication.TestSaml2AuthenticationRequestContexts;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations;
import org.springframework.security.saml2.provider.service.servlet.filter.Saml2WebSsoAuthenticationFilter;
import org.springframework.security.saml2.provider.service.web.DefaultRelyingPartyRegistrationResolver;
import org.springframework.security.saml2.provider.service.web.RelyingPartyRegistrationResolver;
import org.springframework.security.saml2.provider.service.web.Saml2AuthenticationRequestContextResolver;
import org.springframework.security.saml2.provider.service.web.Saml2AuthenticationRequestRepository;
import org.springframework.security.saml2.provider.service.web.Saml2AuthenticationTokenConverter;
import org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver;
Expand Down Expand Up @@ -113,7 +105,6 @@
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.springframework.security.config.Customizer.withDefaults;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
Expand Down Expand Up @@ -211,30 +202,6 @@ public void saml2LoginWhenConfiguringAuthenticationDefaultsUsingCustomizerThenTh
validateSaml2WebSsoAuthenticationFilterConfiguration();
}

@Test
public void saml2LoginWhenCustomAuthenticationRequestContextResolverThenUses() throws Exception {
this.spring.register(CustomAuthenticationRequestContextResolver.class).autowire();
Saml2AuthenticationRequestContext context = TestSaml2AuthenticationRequestContexts
.authenticationRequestContext().build();
Saml2AuthenticationRequestContextResolver resolver = this.spring.getContext()
.getBean(Saml2AuthenticationRequestContextResolver.class);
given(resolver.resolve(any(HttpServletRequest.class))).willReturn(context);
this.mvc.perform(get("/saml2/authenticate/registration-id")).andExpect(status().isFound());
verify(resolver).resolve(any(HttpServletRequest.class));
}

@Test
public void authenticationRequestWhenAuthnRequestContextConverterThenUses() throws Exception {
this.spring.register(CustomAuthenticationRequestContextConverterResolver.class).autowire();

MvcResult result = this.mvc.perform(get("/saml2/authenticate/registration-id")).andReturn();
UriComponents components = UriComponentsBuilder.fromHttpUrl(result.getResponse().getRedirectedUrl()).build();
String samlRequest = components.getQueryParams().getFirst("SAMLRequest");
String decoded = URLDecoder.decode(samlRequest, "UTF-8");
String inflated = Saml2Utils.samlInflate(Saml2Utils.samlDecode(decoded));
assertThat(inflated).contains("ForceAuthn=\"true\"");
}

@Test
public void authenticationRequestWhenAuthenticationRequestResolverBeanThenUses() throws Exception {
this.spring.register(CustomAuthenticationRequestResolverBean.class).autowire();
Expand All @@ -257,19 +224,6 @@ public void authenticationRequestWhenAuthenticationRequestResolverDslThenUses()
assertThat(inflated).contains("ForceAuthn=\"true\"");
}

@Test
public void authenticationRequestWhenAuthenticationRequestResolverAndFactoryThenResolverTakesPrecedence()
throws Exception {
this.spring.register(CustomAuthenticationRequestResolverPrecedence.class).autowire();
MvcResult result = this.mvc.perform(get("/saml2/authenticate/registration-id")).andReturn();
UriComponents components = UriComponentsBuilder.fromHttpUrl(result.getResponse().getRedirectedUrl()).build();
String samlRequest = components.getQueryParams().getFirst("SAMLRequest");
String decoded = URLDecoder.decode(samlRequest, "UTF-8");
String inflated = Saml2Utils.samlInflate(Saml2Utils.samlDecode(decoded));
assertThat(inflated).contains("ForceAuthn=\"true\"");
verifyNoInteractions(this.spring.getContext().getBean(Saml2AuthenticationRequestFactory.class));
}

@Test
public void authenticateWhenCustomAuthenticationConverterThenUses() throws Exception {
this.spring.register(CustomAuthenticationConverter.class).autowire();
Expand Down Expand Up @@ -513,61 +467,6 @@ protected void configure(HttpSecurity http) throws Exception {

}

@EnableWebSecurity
@Import(Saml2LoginConfigBeans.class)
static class CustomAuthenticationRequestContextResolver extends WebSecurityConfigurerAdapter {

private final Saml2AuthenticationRequestContextResolver resolver = mock(
Saml2AuthenticationRequestContextResolver.class);

@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeRequests((authz) -> authz
.anyRequest().authenticated()
)
.saml2Login(withDefaults());
// @formatter:on
}

@Bean
Saml2AuthenticationRequestContextResolver resolver() {
return this.resolver;
}

}

@EnableWebSecurity
@Import(Saml2LoginConfigBeans.class)
static class CustomAuthenticationRequestContextConverterResolver extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeRequests((authz) -> authz
.anyRequest().authenticated()
)
.saml2Login((saml2) -> {
});
// @formatter:on
}

@Bean
Saml2AuthenticationRequestFactory authenticationRequestFactory() {
OpenSaml4AuthenticationRequestFactory authenticationRequestFactory = new OpenSaml4AuthenticationRequestFactory();
authenticationRequestFactory.setAuthenticationRequestContextConverter((context) -> {
AuthnRequest authnRequest = TestOpenSamlObjects.authnRequest();
authnRequest.setIssueInstant(Instant.now());
authnRequest.setForceAuthn(true);
return authnRequest;
});
return authenticationRequestFactory;
}

}

@EnableWebSecurity
@Import(Saml2LoginConfigBeans.class)
static class CustomAuthenticationRequestResolverBean {
Expand Down Expand Up @@ -630,41 +529,6 @@ Saml2AuthenticationRequestResolver authenticationRequestResolver(

}

@EnableWebSecurity
@Import(Saml2LoginConfigBeans.class)
static class CustomAuthenticationRequestResolverPrecedence {

@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeRequests((authz) -> authz
.anyRequest().authenticated()
)
.saml2Login(Customizer.withDefaults());
// @formatter:on

return http.build();
}

@Bean
Saml2AuthenticationRequestFactory authenticationRequestFactory() {
return mock(Saml2AuthenticationRequestFactory.class);
}

@Bean
Saml2AuthenticationRequestResolver authenticationRequestResolver(
RelyingPartyRegistrationRepository registrations) {
RelyingPartyRegistrationResolver registrationResolver = new DefaultRelyingPartyRegistrationResolver(
registrations);
OpenSaml4AuthenticationRequestResolver delegate = new OpenSaml4AuthenticationRequestResolver(
registrationResolver);
delegate.setAuthnRequestCustomizer((parameters) -> parameters.getAuthnRequest().setForceAuthn(true));
return delegate;
}

}

@EnableWebSecurity
@Import(Saml2LoginConfigBeans.class)
static class CustomAuthenticationConverter extends WebSecurityConfigurerAdapter {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2022 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.
Expand All @@ -23,8 +23,7 @@
import java.security.cert.X509Certificate;

import org.springframework.security.converter.RsaKeyConverters;
import org.springframework.security.saml2.credentials.Saml2X509Credential;
import org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType;
import org.springframework.security.saml2.core.Saml2X509Credential;

/**
* Preconfigured SAML credentials for SAML integration tests.
Expand Down Expand Up @@ -61,7 +60,8 @@ static Saml2X509Credential verificationCertificate() {
+ "lx13Y1YlQ4/tlpgTgfIJxKV6nyPiLoK0nywbMd+vpAirDt2Oc+hk\n"
+ "-----END CERTIFICATE-----";
// @formatter:on
return new Saml2X509Credential(x509Certificate(certificate), Saml2X509CredentialType.VERIFICATION);
return new Saml2X509Credential(x509Certificate(certificate),
Saml2X509Credential.Saml2X509CredentialType.VERIFICATION);
}

static X509Certificate x509Certificate(String source) {
Expand Down Expand Up @@ -114,7 +114,8 @@ static Saml2X509Credential signingCredential() {
// @formatter:on
PrivateKey pk = RsaKeyConverters.pkcs8().convert(new ByteArrayInputStream(key.getBytes()));
X509Certificate cert = x509Certificate(certificate);
return new Saml2X509Credential(pk, cert, Saml2X509CredentialType.SIGNING, Saml2X509CredentialType.DECRYPTION);
return new Saml2X509Credential(pk, cert, Saml2X509Credential.Saml2X509CredentialType.SIGNING,
Saml2X509Credential.Saml2X509CredentialType.DECRYPTION);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException;
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationToken;
import org.springframework.security.saml2.provider.service.authentication.Saml2RedirectAuthenticationRequest;
import org.springframework.security.saml2.provider.service.authentication.TestSaml2AuthenticationRequestContexts;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations;
Expand Down Expand Up @@ -231,8 +230,7 @@ public void authenticationRequestWhenCustomAuthenticationRequestContextResolverT
.configLocations(this.xml("WithCustomRelyingPartyRepository-WithCustomAuthenticationRequestResolver"))
.autowire();
Saml2RedirectAuthenticationRequest request = Saml2RedirectAuthenticationRequest
.withAuthenticationRequestContext(
TestSaml2AuthenticationRequestContexts.authenticationRequestContext().build())
.withRelyingPartyRegistration(TestRelyingPartyRegistrations.noCredentials().build())
.samlRequest("request").authenticationRequestUri(IDP_SSO_URL).build();
given(this.authenticationRequestResolver.resolve(any(HttpServletRequest.class))).willReturn(request);
this.mvc.perform(get("/saml2/authenticate/registration-id")).andExpect(status().isFound());
Expand Down
Loading

0 comments on commit 995b291

Please sign in to comment.