Remove SAML Deprecations

Closes gh-11077
This commit is contained in:
Marcus Da Coregio 2022-04-08 09:33:20 -03:00 committed by Marcus Hert Da Coregio
parent 195d767d98
commit 995b2918bb
39 changed files with 157 additions and 3392 deletions

View File

@ -33,21 +33,18 @@ import org.springframework.security.config.annotation.web.configurers.CsrfConfig
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;
@ -87,7 +84,6 @@ import org.springframework.util.StringUtils;
*
* <ul>
* <li>{@link RelyingPartyRegistrationRepository} (required)</li>
* <li>{@link Saml2AuthenticationRequestFactory} (optional)</li>
* </ul>
*
* <h2>Shared Objects Used</h2>
@ -96,7 +92,6 @@ import org.springframework.util.StringUtils;
*
* <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>
@ -300,42 +295,21 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
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();
return new OpenSaml4AuthenticationRequestResolver(relyingPartyRegistrationResolver(http));
}
else {
return new OpenSamlAuthenticationRequestFactory();
}
}
private Saml2AuthenticationRequestContextResolver getAuthenticationRequestContextResolver(B http) {
Saml2AuthenticationRequestContextResolver resolver = getBeanOrNull(http,
Saml2AuthenticationRequestContextResolver.class);
if (resolver != null) {
return resolver;
}
RelyingPartyRegistrationResolver registrationResolver = new DefaultRelyingPartyRegistrationResolver(
this.relyingPartyRegistrationRepository);
return new DefaultSaml2AuthenticationRequestContextResolver(registrationResolver);
return new OpenSaml3AuthenticationRequestResolver(relyingPartyRegistrationResolver(http));
}
private AuthenticationConverter getAuthenticationConverter(B http) {
@ -348,8 +322,7 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
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;
}

View File

@ -19,7 +19,6 @@ package org.springframework.security.config.annotation.web.configurers.saml2;
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;
@ -34,7 +33,6 @@ import org.junit.jupiter.api.Test;
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;
@ -68,23 +66,17 @@ import org.springframework.security.saml2.core.Saml2Utils;
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;
@ -113,7 +105,6 @@ import static org.mockito.ArgumentMatchers.anyString;
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;
@ -211,30 +202,6 @@ public class Saml2LoginConfigurerTests {
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();
@ -257,19 +224,6 @@ public class Saml2LoginConfigurerTests {
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();
@ -513,61 +467,6 @@ public class Saml2LoginConfigurerTests {
}
@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 {
@ -630,41 +529,6 @@ public class Saml2LoginConfigurerTests {
}
@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 {

View File

@ -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.
@ -23,8 +23,7 @@ import java.security.cert.CertificateFactory;
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.
@ -61,7 +60,8 @@ public final class TestSaml2Credentials {
+ "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) {
@ -114,7 +114,8 @@ public final class TestSaml2Credentials {
// @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);
}
}

View File

@ -40,7 +40,6 @@ import org.springframework.security.saml2.provider.service.authentication.Saml2A
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;
@ -231,8 +230,7 @@ public class Saml2LoginBeanDefinitionParserTests {
.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());

View File

@ -34,8 +34,7 @@ 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.saml2.credentials.Saml2X509Credential
import org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType.VERIFICATION
import org.springframework.security.saml2.core.Saml2X509Credential
import org.springframework.security.saml2.provider.service.registration.InMemoryRelyingPartyRegistrationRepository
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository
@ -101,10 +100,14 @@ class Saml2DslTests {
relyingPartyRegistrationRepository =
InMemoryRelyingPartyRegistrationRepository(
RelyingPartyRegistration.withRegistrationId("samlId")
.assertionConsumerServiceUrlTemplate("{baseUrl}" + Saml2WebSsoAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI)
.credentials { c -> c.add(Saml2X509Credential(loadCert("rod.cer"), VERIFICATION)) }
.providerDetails { c -> c.webSsoUrl("ssoUrl") }
.providerDetails { c -> c.entityId("entityId") }
.assertionConsumerServiceLocation("{baseUrl}" + Saml2WebSsoAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI)
.assertingPartyDetails { a -> a
.verificationX509Credentials { c -> c
.add(Saml2X509Credential(loadCert("rod.cer"), Saml2X509Credential.Saml2X509CredentialType.VERIFICATION))
}
}
.assertingPartyDetails { c -> c.singleSignOnServiceLocation("ssoUrl") }
.assertingPartyDetails { c -> c.entityId("entityId") }
.build()
)
}

View File

@ -1,208 +0,0 @@
/*
* Copyright 2002-2020 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.saml2.credentials;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.Set;
import org.springframework.util.Assert;
/**
* Saml2X509Credential is meant to hold an X509 certificate, or an X509 certificate and a
* private key. Per:
* https://www.oasis-open.org/committees/download.php/8958/sstc-saml-implementation-guidelines-draft-01.pdf
* Line: 584, Section 4.3 Credentials Used for both signing, signature verification and
* encryption/decryption
*
* @since 5.2
* @deprecated Use {@link org.springframework.security.saml2.core.Saml2X509Credential}
* instead
*/
@Deprecated
public class Saml2X509Credential {
private final PrivateKey privateKey;
private final X509Certificate certificate;
private final Set<Saml2X509CredentialType> credentialTypes;
/**
* Creates a Saml2X509Credentials representing Identity Provider credentials for
* verification, encryption or both.
* @param certificate an IDP X509Certificate, cannot be null
* @param types credential types, must be one of
* {@link Saml2X509CredentialType#VERIFICATION} or
* {@link Saml2X509CredentialType#ENCRYPTION} or both.
*/
public Saml2X509Credential(X509Certificate certificate, Saml2X509CredentialType... types) {
this(null, false, certificate, types);
validateUsages(types, Saml2X509CredentialType.VERIFICATION, Saml2X509CredentialType.ENCRYPTION);
}
/**
* Creates a Saml2X509Credentials representing Service Provider credentials for
* signing, decryption or both.
* @param privateKey a private key used for signing or decryption, cannot be null
* @param certificate an SP X509Certificate shared with identity providers, cannot be
* null
* @param types credential types, must be one of
* {@link Saml2X509CredentialType#SIGNING} or
* {@link Saml2X509CredentialType#DECRYPTION} or both.
*/
public Saml2X509Credential(PrivateKey privateKey, X509Certificate certificate, Saml2X509CredentialType... types) {
this(privateKey, true, certificate, types);
validateUsages(types, Saml2X509CredentialType.SIGNING, Saml2X509CredentialType.DECRYPTION);
}
public Saml2X509Credential(PrivateKey privateKey, X509Certificate certificate, Set<Saml2X509CredentialType> types) {
Assert.notNull(certificate, "certificate cannot be null");
Assert.notEmpty(types, "credentialTypes cannot be empty");
this.privateKey = privateKey;
this.certificate = certificate;
this.credentialTypes = types;
}
private Saml2X509Credential(PrivateKey privateKey, boolean keyRequired, X509Certificate certificate,
Saml2X509CredentialType... types) {
Assert.notNull(certificate, "certificate cannot be null");
Assert.notEmpty(types, "credentials types cannot be empty");
if (keyRequired) {
Assert.notNull(privateKey, "privateKey cannot be null");
}
this.privateKey = privateKey;
this.certificate = certificate;
this.credentialTypes = new LinkedHashSet<>(Arrays.asList(types));
}
/**
* Returns true if the credential has a private key and can be used for signing, the
* types will contain {@link Saml2X509CredentialType#SIGNING}.
* @return true if the credential is a {@link Saml2X509CredentialType#SIGNING} type
*/
public boolean isSigningCredential() {
return getCredentialTypes().contains(Saml2X509CredentialType.SIGNING);
}
/**
* Returns true if the credential has a private key and can be used for decryption,
* the types will contain {@link Saml2X509CredentialType#DECRYPTION}.
* @return true if the credential is a {@link Saml2X509CredentialType#DECRYPTION} type
*/
public boolean isDecryptionCredential() {
return getCredentialTypes().contains(Saml2X509CredentialType.DECRYPTION);
}
/**
* Returns true if the credential has a certificate and can be used for signature
* verification, the types will contain {@link Saml2X509CredentialType#VERIFICATION}.
* @return true if the credential is a {@link Saml2X509CredentialType#VERIFICATION}
* type
*/
public boolean isSignatureVerficationCredential() {
return getCredentialTypes().contains(Saml2X509CredentialType.VERIFICATION);
}
/**
* Returns true if the credential has a certificate and can be used for signature
* verification, the types will contain {@link Saml2X509CredentialType#VERIFICATION}.
* @return true if the credential is a {@link Saml2X509CredentialType#VERIFICATION}
* type
*/
public boolean isEncryptionCredential() {
return getCredentialTypes().contains(Saml2X509CredentialType.ENCRYPTION);
}
/**
* Returns the credential types for this credential.
* @return a set of credential types/usages that this credential can be used for
*/
protected Set<Saml2X509CredentialType> getCredentialTypes() {
return this.credentialTypes;
}
/**
* Returns the private key, or null if this credential type doesn't require one.
* @return the private key, or null
* @see #Saml2X509Credential(PrivateKey, X509Certificate, Saml2X509CredentialType...)
*/
public PrivateKey getPrivateKey() {
return this.privateKey;
}
/**
* Returns the X509 certificate for ths credential. Cannot be null
* @return the X509 certificate
*/
public X509Certificate getCertificate() {
return this.certificate;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Saml2X509Credential that = (Saml2X509Credential) o;
return Objects.equals(this.privateKey, that.privateKey) && this.certificate.equals(that.certificate)
&& this.credentialTypes.equals(that.credentialTypes);
}
@Override
public int hashCode() {
return Objects.hash(this.privateKey, this.certificate, this.credentialTypes);
}
private void validateUsages(Saml2X509CredentialType[] usages, Saml2X509CredentialType... validUsages) {
for (Saml2X509CredentialType usage : usages) {
boolean valid = false;
for (Saml2X509CredentialType validUsage : validUsages) {
if (usage == validUsage) {
valid = true;
break;
}
}
Assert.state(valid, () -> usage + " is not a valid usage for this credential");
}
}
/**
* @deprecated Use
* {@link org.springframework.security.saml2.core.Saml2X509Credential.Saml2X509CredentialType}
* instead
*/
@Deprecated
public enum Saml2X509CredentialType {
VERIFICATION,
ENCRYPTION,
SIGNING,
DECRYPTION,
}
}

View File

@ -33,8 +33,8 @@ import org.springframework.util.Assert;
* (line 2031)
*
* @since 5.3
* @see Saml2AuthenticationRequestFactory#createPostAuthenticationRequest(Saml2AuthenticationRequestContext)
* @see Saml2AuthenticationRequestFactory#createRedirectAuthenticationRequest(Saml2AuthenticationRequestContext)
* @see Saml2PostAuthenticationRequest
* @see Saml2RedirectAuthenticationRequest
*/
public abstract class AbstractSaml2AuthenticationRequest implements Serializable {

View File

@ -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.
@ -80,69 +80,6 @@ public class Saml2AuthenticationException extends AuthenticationException {
this.error = error;
}
/**
* Constructs a {@code Saml2AuthenticationException} using the provided parameters.
* @param error the
* {@link org.springframework.security.saml2.provider.service.authentication.Saml2Error
* SAML 2.0 Error}
* @deprecated Use
* {@link org.springframework.security.saml2.provider.service.authentication.Saml2Error}
* constructor instead
*/
@Deprecated
public Saml2AuthenticationException(
org.springframework.security.saml2.provider.service.authentication.Saml2Error error) {
this(error, error.getDescription());
}
/**
* Constructs a {@code Saml2AuthenticationException} using the provided parameters.
* @param error the
* {@link org.springframework.security.saml2.provider.service.authentication.Saml2Error
* SAML 2.0 Error}
* @param cause the root cause
* @deprecated Use
* {@link org.springframework.security.saml2.provider.service.authentication.Saml2Error}
* constructor instead
*/
@Deprecated
public Saml2AuthenticationException(
org.springframework.security.saml2.provider.service.authentication.Saml2Error error, Throwable cause) {
this(error, cause.getMessage(), cause);
}
/**
* Constructs a {@code Saml2AuthenticationException} using the provided parameters.
* @param error the {@link Saml2Error SAML 2.0 Error}
* @param message the detail message
* @deprecated Use {@link Saml2Error} constructor instead
*/
@Deprecated
public Saml2AuthenticationException(
org.springframework.security.saml2.provider.service.authentication.Saml2Error error, String message) {
this(error, message, null);
}
/**
* Constructs a {@code Saml2AuthenticationException} using the provided parameters.
* @param error the
* {@link org.springframework.security.saml2.provider.service.authentication.Saml2Error
* SAML 2.0 Error}
* @param message the detail message
* @param cause the root cause
* @deprecated Use
* {@link org.springframework.security.saml2.provider.service.authentication.Saml2Error}
* constructor instead
*/
@Deprecated
public Saml2AuthenticationException(
org.springframework.security.saml2.provider.service.authentication.Saml2Error error, String message,
Throwable cause) {
super(message, cause);
Assert.notNull(error, "error cannot be null");
this.error = new Saml2Error(error.getErrorCode(), error.getDescription());
}
/**
* Get the associated {@link Saml2Error}
* @return the associated {@link Saml2Error}
@ -151,17 +88,6 @@ public class Saml2AuthenticationException extends AuthenticationException {
return this.error;
}
/**
* Returns the {@link Saml2Error SAML 2.0 Error}.
* @return the {@link Saml2Error}
* @deprecated Use {@link #getSaml2Error()} instead
*/
@Deprecated
public org.springframework.security.saml2.provider.service.authentication.Saml2Error getError() {
return new org.springframework.security.saml2.provider.service.authentication.Saml2Error(
this.error.getErrorCode(), this.error.getDescription());
}
@Override
public String toString() {
final StringBuffer sb = new StringBuffer("Saml2AuthenticationException{");

View File

@ -1,199 +0,0 @@
/*
* Copyright 2002-2020 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.saml2.provider.service.authentication;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Consumer;
import org.springframework.security.saml2.credentials.Saml2X509Credential;
import org.springframework.util.Assert;
/**
* Data holder for information required to send an {@code AuthNRequest} from the service
* provider to the identity provider
* https://www.oasis-open.org/committees/download.php/35711/sstc-saml-core-errata-2.0-wd-06-diff.pdf
* (line 2031)
*
* @since 5.2
* @deprecated use {@link Saml2AuthenticationRequestContext}
*/
@Deprecated
public final class Saml2AuthenticationRequest {
private final String issuer;
private final List<Saml2X509Credential> credentials;
private final String destination;
private final String assertionConsumerServiceUrl;
private Saml2AuthenticationRequest(String issuer, String destination, String assertionConsumerServiceUrl,
List<Saml2X509Credential> credentials) {
Assert.hasText(issuer, "issuer cannot be null");
Assert.hasText(destination, "destination cannot be null");
Assert.hasText(assertionConsumerServiceUrl, "spAssertionConsumerServiceUrl cannot be null");
this.issuer = issuer;
this.destination = destination;
this.assertionConsumerServiceUrl = assertionConsumerServiceUrl;
this.credentials = new LinkedList<>();
for (Saml2X509Credential c : credentials) {
if (c.isSigningCredential()) {
this.credentials.add(c);
}
}
}
/**
* returns the issuer, the local SP entity ID, for this authentication request. This
* property should be used to populate the {@code AuthNRequest.Issuer} XML element.
* This value typically is a URI, but can be an arbitrary string.
* @return issuer
*/
public String getIssuer() {
return this.issuer;
}
/**
* returns the destination, the WEB Single Sign On URI, for this authentication
* request. This property populates the {@code AuthNRequest#Destination} XML
* attribute.
* @return destination
*/
public String getDestination() {
return this.destination;
}
/**
* Returns the desired {@code AssertionConsumerServiceUrl} that this SP wishes to
* receive the assertion on. The IDP may or may not honor this request. This property
* populates the {@code AuthNRequest#AssertionConsumerServiceURL} XML attribute.
* @return the AssertionConsumerServiceURL value
*/
public String getAssertionConsumerServiceUrl() {
return this.assertionConsumerServiceUrl;
}
/**
* Returns a list of credentials that can be used to sign the {@code AuthNRequest}
* object
* @return signing credentials
*/
public List<Saml2X509Credential> getCredentials() {
return this.credentials;
}
/**
* A builder for {@link Saml2AuthenticationRequest}.
* @return a {@link Builder} for constructing a {@link Saml2AuthenticationRequest}
*/
public static Builder builder() {
return new Builder();
}
/**
* A builder for {@link Saml2AuthenticationRequest}.
* @param context a context object to copy values from. returns a builder object
* @return a {@link Builder} for constructing a {@link Saml2AuthenticationRequest}
*/
public static Builder withAuthenticationRequestContext(Saml2AuthenticationRequestContext context) {
return new Builder().assertionConsumerServiceUrl(context.getAssertionConsumerServiceUrl())
.issuer(context.getIssuer()).destination(context.getDestination())
.credentials((c) -> c.addAll(context.getRelyingPartyRegistration().getCredentials()));
}
/**
* A builder for {@link Saml2AuthenticationRequest}.
*/
public static final class Builder {
private String issuer;
private List<Saml2X509Credential> credentials = new LinkedList<>();
private String destination;
private String assertionConsumerServiceUrl;
private Builder() {
}
/**
* Sets the issuer for the authentication request.
* @param issuer - a required value
* @return this {@code Builder}
*/
public Builder issuer(String issuer) {
this.issuer = issuer;
return this;
}
/**
* Modifies the collection of {@link Saml2X509Credential} credentials used in
* communication between IDP and SP, specifically signing the authentication
* request. For example: <code>
* Saml2X509Credential credential = ...;
* return Saml2AuthenticationRequest.withLocalSpEntityId("id")
* .credentials((c) -&gt; c.add(credential))
* ...
* .build();
* </code>
* @param credentials - a consumer that can modify the collection of credentials
* @return this object
*/
public Builder credentials(Consumer<Collection<Saml2X509Credential>> credentials) {
credentials.accept(this.credentials);
return this;
}
/**
* Sets the Destination for the authentication request. Typically the
* {@code Service Provider EntityID}
* @param destination - a required value
* @return this {@code Builder}
*/
public Builder destination(String destination) {
this.destination = destination;
return this;
}
/**
* Sets the {@code assertionConsumerServiceURL} for the authentication request.
* Typically the {@code Service Provider EntityID}
* @param assertionConsumerServiceUrl - a required value
* @return this {@code Builder}
*/
public Builder assertionConsumerServiceUrl(String assertionConsumerServiceUrl) {
this.assertionConsumerServiceUrl = assertionConsumerServiceUrl;
return this;
}
/**
* Creates a {@link Saml2AuthenticationRequest} object.
* @return the Saml2AuthenticationRequest object
* @throws IllegalArgumentException if a required property is not set
*/
public Saml2AuthenticationRequest build() {
return new Saml2AuthenticationRequest(this.issuer, this.destination, this.assertionConsumerServiceUrl,
this.credentials);
}
}
}

View File

@ -1,183 +0,0 @@
/*
* 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.saml2.provider.service.authentication;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
import org.springframework.util.Assert;
/**
* Data holder for information required to create an {@code AuthNRequest} to be sent from
* the service provider to the identity provider <a href=
* "https://www.oasis-open.org/committees/download.php/35711/sstc-saml-core-errata-2.0-wd-06-diff.pdf">
* Assertions and Protocols for SAML 2 (line 2031)</a>
*
* @since 5.3
* @see Saml2AuthenticationRequestFactory#createPostAuthenticationRequest(Saml2AuthenticationRequestContext)
* @see Saml2AuthenticationRequestFactory#createRedirectAuthenticationRequest(Saml2AuthenticationRequestContext)
* @deprecated Use
* {@link org.springframework.security.saml2.provider.service.web.authentication.Saml2AuthenticationRequestResolver}
* instead
*/
@Deprecated
public class Saml2AuthenticationRequestContext {
private final RelyingPartyRegistration relyingPartyRegistration;
private final String issuer;
private final String assertionConsumerServiceUrl;
private final String relayState;
protected Saml2AuthenticationRequestContext(RelyingPartyRegistration relyingPartyRegistration, String issuer,
String assertionConsumerServiceUrl, String relayState) {
Assert.hasText(issuer, "issuer cannot be null or empty");
Assert.notNull(relyingPartyRegistration, "relyingPartyRegistration cannot be null");
Assert.hasText(assertionConsumerServiceUrl, "spAssertionConsumerServiceUrl cannot be null or empty");
this.issuer = issuer;
this.relyingPartyRegistration = relyingPartyRegistration;
this.assertionConsumerServiceUrl = assertionConsumerServiceUrl;
this.relayState = relayState;
}
/**
* Returns the {@link RelyingPartyRegistration} configuration for which the
* AuthNRequest is intended for.
* @return the {@link RelyingPartyRegistration} configuration
*/
public RelyingPartyRegistration getRelyingPartyRegistration() {
return this.relyingPartyRegistration;
}
/**
* Returns the {@code Issuer} value to be used in the {@code AuthNRequest} object.
* This property should be used to populate the {@code AuthNRequest.Issuer} XML
* element. This value typically is a URI, but can be an arbitrary string.
* @return the Issuer value
*/
public String getIssuer() {
return this.issuer;
}
/**
* Returns the desired {@code AssertionConsumerServiceUrl} that this SP wishes to
* receive the assertion on. The IDP may or may not honor this request. This property
* populates the {@code AuthNRequest.AssertionConsumerServiceURL} XML attribute.
* @return the AssertionConsumerServiceURL value
*/
public String getAssertionConsumerServiceUrl() {
return this.assertionConsumerServiceUrl;
}
/**
* Returns the RelayState value, if present in the parameters
* @return the RelayState value, or null if not available
*/
public String getRelayState() {
return this.relayState;
}
/**
* Returns the {@code Destination}, the WEB Single Sign On URI, for this
* authentication request. This property can also populate the
* {@code AuthNRequest.Destination} XML attribute.
* @return the Destination value
*/
public String getDestination() {
return this.getRelyingPartyRegistration().getAssertingPartyDetails().getSingleSignOnServiceLocation();
}
/**
* A builder for {@link Saml2AuthenticationRequestContext}.
* @return a builder object
*/
public static Builder builder() {
return new Builder();
}
/**
* A builder for {@link Saml2AuthenticationRequestContext}.
*/
public static final class Builder {
private String issuer;
private String assertionConsumerServiceUrl;
private String relayState;
private RelyingPartyRegistration relyingPartyRegistration;
private Builder() {
}
/**
* Sets the issuer for the authentication request.
* @param issuer - a required value
* @return this {@code Builder}
*/
public Builder issuer(String issuer) {
this.issuer = issuer;
return this;
}
/**
* Sets the {@link RelyingPartyRegistration} used to build the authentication
* request.
* @param relyingPartyRegistration - a required value
* @return this {@code Builder}
*/
public Builder relyingPartyRegistration(RelyingPartyRegistration relyingPartyRegistration) {
this.relyingPartyRegistration = relyingPartyRegistration;
return this;
}
/**
* Sets the {@code assertionConsumerServiceURL} for the authentication request.
* Typically the {@code Service Provider EntityID}
* @param assertionConsumerServiceUrl - a required value
* @return this {@code Builder}
*/
public Builder assertionConsumerServiceUrl(String assertionConsumerServiceUrl) {
this.assertionConsumerServiceUrl = assertionConsumerServiceUrl;
return this;
}
/**
* Sets the {@code RelayState} parameter that will accompany this AuthNRequest
* @param relayState the relay state value, unencoded. if null or empty, the
* parameter will be removed from the map.
* @return this object
*/
public Builder relayState(String relayState) {
this.relayState = relayState;
return this;
}
/**
* Creates a {@link Saml2AuthenticationRequestContext} object.
* @return the Saml2AuthenticationRequest object
* @throws IllegalArgumentException if a required property is not set
*/
public Saml2AuthenticationRequestContext build() {
return new Saml2AuthenticationRequestContext(this.relyingPartyRegistration, this.issuer,
this.assertionConsumerServiceUrl, this.relayState);
}
}
}

View File

@ -1,120 +0,0 @@
/*
* Copyright 2002-2020 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.saml2.provider.service.authentication;
import java.nio.charset.StandardCharsets;
import org.springframework.security.saml2.Saml2Exception;
import org.springframework.security.saml2.core.Saml2X509Credential.Saml2X509CredentialType;
import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
/**
* Component that generates AuthenticationRequest, <code>samlp:AuthnRequestType</code>
* XML, and accompanying signature data. as defined by
* https://www.oasis-open.org/committees/download.php/35711/sstc-saml-core-errata-2.0-wd-06-diff.pdf
* Page 50, Line 2147
*
* @since 5.2
* @deprecated As of 5.7.0, use
* {@link org.springframework.security.saml2.provider.service.web.authentication.Saml2AuthenticationRequestResolver}
* instead
*/
@Deprecated
public interface Saml2AuthenticationRequestFactory {
/**
* Creates an authentication request from the Service Provider, sp, to the Identity
* Provider, idp. The authentication result is an XML string that may be signed,
* encrypted, both or neither. This method only returns the {@code SAMLRequest} string
* for the request, and for a complete set of data parameters please use
* {@link #createRedirectAuthenticationRequest(Saml2AuthenticationRequestContext)} or
* {@link #createPostAuthenticationRequest(Saml2AuthenticationRequestContext)}
* @param request information about the identity provider, the recipient of this
* authentication request and accompanying data
* @return XML data in the format of a String. This data may be signed, encrypted,
* both signed and encrypted with the signature embedded in the XML or neither signed
* and encrypted
* @throws Saml2Exception when a SAML library exception occurs
* @since 5.2
* @deprecated please use
* {@link #createRedirectAuthenticationRequest(Saml2AuthenticationRequestContext)} or
* {@link #createPostAuthenticationRequest(Saml2AuthenticationRequestContext)} This
* method will be removed in future versions of Spring Security
*/
@Deprecated
String createAuthenticationRequest(Saml2AuthenticationRequest request);
/**
* Creates all the necessary AuthNRequest parameters for a REDIRECT binding. If the
* {@link Saml2AuthenticationRequestContext} doesn't contain any
* {@link Saml2X509CredentialType#SIGNING} credentials the result will not contain any
* signatures. The data set will be signed and encoded for REDIRECT binding including
* the DEFLATE encoding. It will contain the following parameters to be sent as part
* of the query string: {@code SAMLRequest, RelayState, SigAlg, Signature}. <i>The
* default implementation, for sake of backwards compatibility, of this method returns
* the SAMLRequest message with an XML signature embedded, that should only be used
* for the{@link Saml2MessageBinding#POST} binding, but works over
* {@link Saml2MessageBinding#POST} with most providers.</i>
* @param context - information about the identity provider, the recipient of this
* authentication request and accompanying data
* @return a {@link Saml2RedirectAuthenticationRequest} object with applicable http
* parameters necessary to make the AuthNRequest over a POST or REDIRECT binding. All
* parameters will be SAML encoded/deflated, but escaped, ie URI encoded or encoded
* for Form Data.
* @throws Saml2Exception when a SAML library exception occurs
* @since 5.3
*/
default Saml2RedirectAuthenticationRequest createRedirectAuthenticationRequest(
Saml2AuthenticationRequestContext context) {
// backwards compatible with 5.2.x settings
Saml2AuthenticationRequest.Builder resultBuilder = Saml2AuthenticationRequest
.withAuthenticationRequestContext(context);
String samlRequest = createAuthenticationRequest(resultBuilder.build());
samlRequest = Saml2Utils.samlEncode(Saml2Utils.samlDeflate(samlRequest));
return Saml2RedirectAuthenticationRequest.withAuthenticationRequestContext(context).samlRequest(samlRequest)
.build();
}
/**
* Creates all the necessary AuthNRequest parameters for a POST binding. If the
* {@link Saml2AuthenticationRequestContext} doesn't contain any
* {@link Saml2X509CredentialType#SIGNING} credentials the result will not contain any
* signatures. The data set will be signed and encoded for POST binding and if
* applicable signed with XML signatures. will contain the following parameters to be
* sent as part of the form data: {@code SAMLRequest, RelayState}. <i>The default
* implementation of this method returns the SAMLRequest message with an XML signature
* embedded, that should only be used for the {@link Saml2MessageBinding#POST}
* binding.</i>
* @param context - information about the identity provider, the recipient of this
* authentication request and accompanying data
* @return a {@link Saml2PostAuthenticationRequest} object with applicable http
* parameters necessary to make the AuthNRequest over a POST binding. All parameters
* will be SAML encoded but not escaped for Form Data.
* @throws Saml2Exception when a SAML library exception occurs
* @since 5.3
*/
default Saml2PostAuthenticationRequest createPostAuthenticationRequest(Saml2AuthenticationRequestContext context) {
// backwards compatible with 5.2.x settings
Saml2AuthenticationRequest.Builder resultBuilder = Saml2AuthenticationRequest
.withAuthenticationRequestContext(context);
String samlRequest = createAuthenticationRequest(resultBuilder.build());
samlRequest = Saml2Utils.samlEncode(samlRequest.getBytes(StandardCharsets.UTF_8));
return Saml2PostAuthenticationRequest.withAuthenticationRequestContext(context).samlRequest(samlRequest)
.build();
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@ -17,10 +17,8 @@
package org.springframework.security.saml2.provider.service.authentication;
import java.util.Collections;
import java.util.List;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.saml2.credentials.Saml2X509Credential;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
import org.springframework.util.Assert;
@ -81,31 +79,6 @@ public class Saml2AuthenticationToken extends AbstractAuthenticationToken {
this(relyingPartyRegistration, saml2Response, null);
}
/**
* Creates an authentication token from an incoming SAML 2 Response object
* @param saml2Response inflated and decoded XML representation of the SAML 2 Response
* @param recipientUri the URL that the SAML 2 Response was received at. Used for
* validation
* @param idpEntityId the entity ID of the asserting entity
* @param localSpEntityId the configured local SP, the relying party, entity ID
* @param credentials the credentials configured for signature verification and
* decryption
* @deprecated Use {@link #Saml2AuthenticationToken(RelyingPartyRegistration, String)}
* instead
*/
@Deprecated
public Saml2AuthenticationToken(String saml2Response, String recipientUri, String idpEntityId,
String localSpEntityId, List<Saml2X509Credential> credentials) {
super(null);
this.relyingPartyRegistration = RelyingPartyRegistration.withRegistrationId(idpEntityId)
.entityId(localSpEntityId).assertionConsumerServiceLocation(recipientUri)
.credentials((c) -> c.addAll(credentials)).assertingPartyDetails((assertingParty) -> assertingParty
.entityId(idpEntityId).singleSignOnServiceLocation(idpEntityId))
.build();
this.saml2Response = saml2Response;
this.authenticationRequest = null;
}
/**
* Returns the decoded and inflated SAML 2.0 Response XML object as a string
* @return decoded and inflated XML data as a {@link String}
@ -141,38 +114,6 @@ public class Saml2AuthenticationToken extends AbstractAuthenticationToken {
return this.saml2Response;
}
/**
* Returns the URI that the SAML 2 Response object came in on
* @return URI as a string
* @deprecated Use
* {@code getRelyingPartyRegistration().getAssertionConsumerServiceLocation()} instead
*/
@Deprecated
public String getRecipientUri() {
return this.relyingPartyRegistration.getAssertionConsumerServiceLocation();
}
/**
* Returns the configured entity ID of the receiving relying party, SP
* @return an entityID for the configured local relying party
* @deprecated Use {@code getRelyingPartyRegistration().getEntityId()} instead
*/
@Deprecated
public String getLocalSpEntityId() {
return this.relyingPartyRegistration.getEntityId();
}
/**
* Returns all the credentials associated with the relying party configuraiton
* @return all associated credentials
* @deprecated Get the credentials through {@link #getRelyingPartyRegistration()}
* instead
*/
@Deprecated
public List<Saml2X509Credential> getX509Credentials() {
return this.relyingPartyRegistration.getCredentials();
}
/**
* @return false
*/
@ -190,18 +131,6 @@ public class Saml2AuthenticationToken extends AbstractAuthenticationToken {
throw new IllegalArgumentException();
}
/**
* Returns the configured IDP, asserting party, entity ID
* @return a string representing the entity ID
* @deprecated Use
* {@code getRelyingPartyRegistration().getAssertingPartyDetails().getEntityId()}
* instead
*/
@Deprecated
public String getIdpEntityId() {
return this.relyingPartyRegistration.getAssertingPartyDetails().getEntityId();
}
/**
* Returns the authentication request sent to the assertion party or {@code null} if
* no authentication request is present

View File

@ -1,72 +0,0 @@
/*
* Copyright 2002-2020 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.saml2.provider.service.authentication;
import java.io.Serializable;
import org.springframework.security.core.SpringSecurityCoreVersion;
/**
* A representation of an SAML 2.0 Error.
*
* <p>
* At a minimum, an error response will contain an error code. The commonly used error
* code are defined in this class or a new codes can be defined in the future as arbitrary
* strings.
* </p>
*
* @since 5.2
* @deprecated Use {@link org.springframework.security.saml2.core.Saml2Error} instead
*/
@Deprecated
public class Saml2Error implements Serializable {
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
private final org.springframework.security.saml2.core.Saml2Error error;
/**
* Constructs a {@code Saml2Error} using the provided parameters.
* @param errorCode the error code
* @param description the error description
*/
public Saml2Error(String errorCode, String description) {
this.error = new org.springframework.security.saml2.core.Saml2Error(errorCode, description);
}
/**
* Returns the error code.
* @return the error code
*/
public final String getErrorCode() {
return this.error.getErrorCode();
}
/**
* Returns the error description.
* @return the error description
*/
public final String getDescription() {
return this.error.getDescription();
}
@Override
public String toString() {
return "[" + this.getErrorCode() + "] " + ((this.getDescription() != null) ? this.getDescription() : "");
}
}

View File

@ -1,107 +0,0 @@
/*
* Copyright 2002-2020 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.saml2.provider.service.authentication;
/**
* A list of SAML known 2 error codes used during SAML authentication.
*
* @since 5.2
* @deprecated Use {@link org.springframework.security.saml2.core.Saml2ErrorCodes} instead
*/
@Deprecated
public interface Saml2ErrorCodes {
/**
* SAML Data does not represent a SAML 2 Response object. A valid XML object was
* received, but that object was not a SAML 2 Response object of type
* {@code ResponseType} per specification
* https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf#page=46
*/
String UNKNOWN_RESPONSE_CLASS = org.springframework.security.saml2.core.Saml2ErrorCodes.UNKNOWN_RESPONSE_CLASS;
/**
* The response data is malformed or incomplete. An invalid XML object was received,
* and XML unmarshalling failed.
*/
String MALFORMED_RESPONSE_DATA = org.springframework.security.saml2.core.Saml2ErrorCodes.MALFORMED_RESPONSE_DATA;
/**
* Response destination does not match the request URL. A SAML 2 response object was
* received at a URL that did not match the URL stored in the {code Destination}
* attribute in the Response object.
* https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf#page=38
*/
String INVALID_DESTINATION = org.springframework.security.saml2.core.Saml2ErrorCodes.INVALID_DESTINATION;
/**
* The assertion was not valid. The assertion used for authentication failed
* validation. Details around the failure will be present in the error description.
*/
String INVALID_ASSERTION = org.springframework.security.saml2.core.Saml2ErrorCodes.INVALID_ASSERTION;
/**
* The signature of response or assertion was invalid. Either the response or the
* assertion was missing a signature or the signature could not be verified using the
* system's configured credentials. Most commonly the IDP's X509 certificate.
*/
String INVALID_SIGNATURE = org.springframework.security.saml2.core.Saml2ErrorCodes.INVALID_SIGNATURE;
/**
* The assertion did not contain a subject element. The subject element, type
* SubjectType, contains a {@code NameID} or an {@code EncryptedID} that is used to
* assign the authenticated principal an identifier, typically a username.
*
* https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf#page=18
*/
String SUBJECT_NOT_FOUND = org.springframework.security.saml2.core.Saml2ErrorCodes.SUBJECT_NOT_FOUND;
/**
* The subject did not contain a user identifier The assertion contained a subject
* element, but the subject element did not have a {@code NameID} or
* {@code EncryptedID} element
*
* https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf#page=18
*/
String USERNAME_NOT_FOUND = org.springframework.security.saml2.core.Saml2ErrorCodes.USERNAME_NOT_FOUND;
/**
* The system failed to decrypt an assertion or a name identifier. This error code
* will be thrown if the decryption of either a {@code EncryptedAssertion} or
* {@code EncryptedID} fails.
* https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf#page=17
*/
String DECRYPTION_ERROR = org.springframework.security.saml2.core.Saml2ErrorCodes.DECRYPTION_ERROR;
/**
* An Issuer element contained a value that didn't
* https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf#page=15
*/
String INVALID_ISSUER = org.springframework.security.saml2.core.Saml2ErrorCodes.INVALID_ISSUER;
/**
* An error happened during validation. Used when internal, non classified, errors are
* caught during the authentication process.
*/
String INTERNAL_VALIDATION_ERROR = org.springframework.security.saml2.core.Saml2ErrorCodes.INTERNAL_VALIDATION_ERROR;
/**
* The relying party registration was not found. The registration ID did not
* correspond to any relying party registration.
*/
String RELYING_PARTY_REGISTRATION_NOT_FOUND = org.springframework.security.saml2.core.Saml2ErrorCodes.RELYING_PARTY_REGISTRATION_NOT_FOUND;
}

View File

@ -26,7 +26,7 @@ import org.springframework.security.saml2.provider.service.registration.Saml2Mes
* (line 2031)
*
* @since 5.3
* @see Saml2AuthenticationRequestFactory
* @see org.springframework.security.saml2.provider.service.web.authentication.Saml2AuthenticationRequestResolver
*/
public class Saml2PostAuthenticationRequest extends AbstractSaml2AuthenticationRequest {
@ -42,19 +42,6 @@ public class Saml2PostAuthenticationRequest extends AbstractSaml2AuthenticationR
return Saml2MessageBinding.POST;
}
/**
* Constructs a {@link Builder} from a {@link Saml2AuthenticationRequestContext}
* object. By default the
* {@link Saml2PostAuthenticationRequest#getAuthenticationRequestUri()} will be set to
* the {@link Saml2AuthenticationRequestContext#getDestination()} value.
* @param context input providing {@code Destination}, {@code RelayState}, and
* {@code Issuer} objects.
* @return a modifiable builder object
*/
public static Builder withAuthenticationRequestContext(Saml2AuthenticationRequestContext context) {
return new Builder().authenticationRequestUri(context.getDestination()).relayState(context.getRelayState());
}
/**
* Constructs a {@link Builder} from a {@link RelyingPartyRegistration} object.
* @param registration a relying party registration

View File

@ -26,7 +26,7 @@ import org.springframework.security.saml2.provider.service.registration.Saml2Mes
* (line 2031)
*
* @since 5.3
* @see Saml2AuthenticationRequestFactory
* @see org.springframework.security.saml2.provider.service.web.authentication.Saml2AuthenticationRequestResolver
*/
public final class Saml2RedirectAuthenticationRequest extends AbstractSaml2AuthenticationRequest {
@ -65,19 +65,6 @@ public final class Saml2RedirectAuthenticationRequest extends AbstractSaml2Authe
return Saml2MessageBinding.REDIRECT;
}
/**
* Constructs a {@link Saml2RedirectAuthenticationRequest.Builder} from a
* {@link Saml2AuthenticationRequestContext} object. By default the
* {@link Saml2RedirectAuthenticationRequest#getAuthenticationRequestUri()} will be
* set to the {@link Saml2AuthenticationRequestContext#getDestination()} value.
* @param context input providing {@code Destination}, {@code RelayState}, and
* {@code Issuer} objects.
* @return a modifiable builder object
*/
public static Builder withAuthenticationRequestContext(Saml2AuthenticationRequestContext context) {
return new Builder().authenticationRequestUri(context.getDestination()).relayState(context.getRelayState());
}
/**
* Constructs a {@link Saml2PostAuthenticationRequest.Builder} from a
* {@link RelyingPartyRegistration} object.

View File

@ -16,17 +16,13 @@
package org.springframework.security.saml2.provider.service.registration;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import org.opensaml.xmlsec.signature.support.SignatureConstants;
@ -89,9 +85,7 @@ public final class RelyingPartyRegistration {
private final String nameIdFormat;
private final ProviderDetails providerDetails;
private final List<org.springframework.security.saml2.credentials.Saml2X509Credential> credentials;
private final AssertingPartyDetails assertingPartyDetails;
private final Collection<Saml2X509Credential> decryptionX509Credentials;
@ -100,8 +94,7 @@ public final class RelyingPartyRegistration {
private RelyingPartyRegistration(String registrationId, String entityId, String assertionConsumerServiceLocation,
Saml2MessageBinding assertionConsumerServiceBinding, String singleLogoutServiceLocation,
String singleLogoutServiceResponseLocation, Saml2MessageBinding singleLogoutServiceBinding,
ProviderDetails providerDetails, String nameIdFormat,
Collection<org.springframework.security.saml2.credentials.Saml2X509Credential> credentials,
AssertingPartyDetails assertingPartyDetails, String nameIdFormat,
Collection<Saml2X509Credential> decryptionX509Credentials,
Collection<Saml2X509Credential> signingX509Credentials) {
Assert.hasText(registrationId, "registrationId cannot be empty");
@ -110,13 +103,7 @@ public final class RelyingPartyRegistration {
Assert.notNull(assertionConsumerServiceBinding, "assertionConsumerServiceBinding cannot be null");
Assert.isTrue(singleLogoutServiceLocation == null || singleLogoutServiceBinding != null,
"singleLogoutServiceBinding cannot be null when singleLogoutServiceLocation is set");
Assert.notNull(providerDetails, "providerDetails cannot be null");
Assert.isTrue(
!credentials.isEmpty() || (decryptionX509Credentials.isEmpty() && signingX509Credentials.isEmpty()),
"credentials cannot be empty");
for (org.springframework.security.saml2.credentials.Saml2X509Credential c : credentials) {
Assert.notNull(c, "credentials cannot contain null elements");
}
Assert.notNull(assertingPartyDetails, "assertingPartyDetails cannot be null");
Assert.notNull(decryptionX509Credentials, "decryptionX509Credentials cannot be null");
for (Saml2X509Credential c : decryptionX509Credentials) {
Assert.notNull(c, "decryptionX509Credentials cannot contain null elements");
@ -136,8 +123,7 @@ public final class RelyingPartyRegistration {
this.singleLogoutServiceResponseLocation = singleLogoutServiceResponseLocation;
this.singleLogoutServiceBinding = singleLogoutServiceBinding;
this.nameIdFormat = nameIdFormat;
this.providerDetails = providerDetails;
this.credentials = Collections.unmodifiableList(new LinkedList<>(credentials));
this.assertingPartyDetails = assertingPartyDetails;
this.decryptionX509Credentials = Collections.unmodifiableList(new LinkedList<>(decryptionX509Credentials));
this.signingX509Credentials = Collections.unmodifiableList(new LinkedList<>(signingX509Credentials));
}
@ -278,139 +264,7 @@ public final class RelyingPartyRegistration {
* @since 5.4
*/
public AssertingPartyDetails getAssertingPartyDetails() {
return this.providerDetails.assertingPartyDetails;
}
/**
* Returns the entity ID of the IDP, the asserting party.
* @return entity ID of the asserting party
* @deprecated use {@link AssertingPartyDetails#getEntityId} from
* {@link #getAssertingPartyDetails}
*/
@Deprecated
public String getRemoteIdpEntityId() {
return this.providerDetails.getEntityId();
}
/**
* returns the URL template for which ACS URL authentication requests should contain
* Possible variables are {@code baseUrl}, {@code registrationId}, {@code baseScheme},
* {@code baseHost}, and {@code basePort}.
* @return string containing the ACS URL template, with or without variables present
* @deprecated Use {@link #getAssertionConsumerServiceLocation} instead
*/
@Deprecated
public String getAssertionConsumerServiceUrlTemplate() {
return this.assertionConsumerServiceLocation;
}
/**
* Contains the URL for which to send the SAML 2 Authentication Request to initiate a
* single sign on flow.
* @return a IDP URL that accepts REDIRECT or POST binding for authentication requests
* @deprecated use {@link AssertingPartyDetails#getSingleSignOnServiceLocation} from
* {@link #getAssertingPartyDetails}
*/
@Deprecated
public String getIdpWebSsoUrl() {
return this.getAssertingPartyDetails().getSingleSignOnServiceLocation();
}
/**
* Returns specific configuration around the Identity Provider SSO endpoint
* @return the IDP SSO endpoint configuration
* @since 5.3
* @deprecated Use {@link #getAssertingPartyDetails} instead
*/
@Deprecated
public ProviderDetails getProviderDetails() {
return this.providerDetails;
}
/**
* The local relying party, or Service Provider, can generate it's entity ID based on
* possible variables of {@code baseUrl}, {@code registrationId}, {@code baseScheme},
* {@code baseHost}, and {@code basePort}, for example
* {@code {baseUrl}/saml2/service-provider-metadata/{registrationId}}
* @return a string containing the entity ID or entity ID template
* @deprecated Use {@link #getEntityId} instead
*/
@Deprecated
public String getLocalEntityIdTemplate() {
return this.entityId;
}
/**
* Returns a list of configured credentials to be used in message exchanges between
* relying party, SP, and asserting party, IDP.
* @return a list of credentials
* @deprecated Instead of retrieving all credentials, use the appropriate method for
* obtaining the correct type
*/
@Deprecated
public List<org.springframework.security.saml2.credentials.Saml2X509Credential> getCredentials() {
return this.credentials;
}
/**
* @return a filtered list containing only credentials of type
* {@link org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType#VERIFICATION}.
* Returns an empty list of credentials are not found
* @deprecated Use {code #getAssertingPartyDetails().getSigningX509Credentials()}
* instead
*/
@Deprecated
public List<org.springframework.security.saml2.credentials.Saml2X509Credential> getVerificationCredentials() {
return filterCredentials(
org.springframework.security.saml2.credentials.Saml2X509Credential::isSignatureVerficationCredential);
}
/**
* @return a filtered list containing only credentials of type
* {@link org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType#SIGNING}.
* Returns an empty list of credentials are not found
* @deprecated Use {@link #getSigningX509Credentials()} instead
*/
@Deprecated
public List<org.springframework.security.saml2.credentials.Saml2X509Credential> getSigningCredentials() {
return filterCredentials(
org.springframework.security.saml2.credentials.Saml2X509Credential::isSigningCredential);
}
/**
* @return a filtered list containing only credentials of type
* {@link org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType#ENCRYPTION}.
* Returns an empty list of credentials are not found
* @deprecated Use {@link AssertingPartyDetails#getEncryptionX509Credentials()}
* instead
*/
@Deprecated
public List<org.springframework.security.saml2.credentials.Saml2X509Credential> getEncryptionCredentials() {
return filterCredentials(
org.springframework.security.saml2.credentials.Saml2X509Credential::isEncryptionCredential);
}
/**
* @return a filtered list containing only credentials of type
* {@link org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType#DECRYPTION}.
* Returns an empty list of credentials are not found
* @deprecated Use {@link #getDecryptionX509Credentials()} instead
*/
@Deprecated
public List<org.springframework.security.saml2.credentials.Saml2X509Credential> getDecryptionCredentials() {
return filterCredentials(
org.springframework.security.saml2.credentials.Saml2X509Credential::isDecryptionCredential);
}
private List<org.springframework.security.saml2.credentials.Saml2X509Credential> filterCredentials(
Function<org.springframework.security.saml2.credentials.Saml2X509Credential, Boolean> filter) {
List<org.springframework.security.saml2.credentials.Saml2X509Credential> result = new LinkedList<>();
for (org.springframework.security.saml2.credentials.Saml2X509Credential c : this.credentials) {
if (filter.apply(c)) {
result.add(c);
}
}
return result;
return this.assertingPartyDetails;
}
/**
@ -477,51 +331,6 @@ public final class RelyingPartyRegistration {
registration.getAssertingPartyDetails().getSingleLogoutServiceBinding()));
}
private static Saml2X509Credential fromDeprecated(
org.springframework.security.saml2.credentials.Saml2X509Credential credential) {
PrivateKey privateKey = credential.getPrivateKey();
X509Certificate certificate = credential.getCertificate();
Set<Saml2X509Credential.Saml2X509CredentialType> credentialTypes = new LinkedHashSet<>();
if (credential.isSigningCredential()) {
credentialTypes.add(Saml2X509Credential.Saml2X509CredentialType.SIGNING);
}
if (credential.isSignatureVerficationCredential()) {
credentialTypes.add(Saml2X509Credential.Saml2X509CredentialType.VERIFICATION);
}
if (credential.isEncryptionCredential()) {
credentialTypes.add(Saml2X509Credential.Saml2X509CredentialType.ENCRYPTION);
}
if (credential.isDecryptionCredential()) {
credentialTypes.add(Saml2X509Credential.Saml2X509CredentialType.DECRYPTION);
}
return new Saml2X509Credential(privateKey, certificate, credentialTypes);
}
private static org.springframework.security.saml2.credentials.Saml2X509Credential toDeprecated(
Saml2X509Credential credential) {
PrivateKey privateKey = credential.getPrivateKey();
X509Certificate certificate = credential.getCertificate();
Set<org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType> credentialTypes = new LinkedHashSet<>();
if (credential.isSigningCredential()) {
credentialTypes.add(
org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType.SIGNING);
}
if (credential.isVerificationCredential()) {
credentialTypes.add(
org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType.VERIFICATION);
}
if (credential.isEncryptionCredential()) {
credentialTypes.add(
org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType.ENCRYPTION);
}
if (credential.isDecryptionCredential()) {
credentialTypes.add(
org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType.DECRYPTION);
}
return new org.springframework.security.saml2.credentials.Saml2X509Credential(privateKey, certificate,
credentialTypes);
}
/**
* The configuration metadata of the Asserting party
*
@ -746,7 +555,7 @@ public final class RelyingPartyRegistration {
* Equivalent to the value found in the asserting party's &lt;EntityDescriptor
* EntityID="..."/&gt;
* @param entityId the asserting party's EntityID
* @return the {@link ProviderDetails.Builder} for further configuration
* @return the {@link AssertingPartyDetails.Builder} for further configuration
*/
public Builder entityId(String entityId) {
this.entityId = entityId;
@ -758,7 +567,7 @@ public final class RelyingPartyRegistration {
* preference that relying parties should sign the AuthnRequest before
* sending.
* @param wantAuthnRequestsSigned the WantAuthnRequestsSigned setting
* @return the {@link ProviderDetails.Builder} for further configuration
* @return the {@link AssertingPartyDetails.Builder} for further configuration
*/
public Builder wantAuthnRequestsSigned(boolean wantAuthnRequestsSigned) {
this.wantAuthnRequestsSigned = wantAuthnRequestsSigned;
@ -813,7 +622,7 @@ public final class RelyingPartyRegistration {
* Equivalent to the value found in &lt;SingleSignOnService
* Location="..."/&gt; in the asserting party's &lt;IDPSSODescriptor&gt;.
* @param singleSignOnServiceLocation the SingleSignOnService Location
* @return the {@link ProviderDetails.Builder} for further configuration
* @return the {@link AssertingPartyDetails.Builder} for further configuration
*/
public Builder singleSignOnServiceLocation(String singleSignOnServiceLocation) {
this.singleSignOnServiceLocation = singleSignOnServiceLocation;
@ -829,7 +638,7 @@ public final class RelyingPartyRegistration {
* Equivalent to the value found in &lt;SingleSignOnService Binding="..."/&gt;
* in the asserting party's &lt;IDPSSODescriptor&gt;.
* @param singleSignOnServiceBinding the SingleSignOnService Binding
* @return the {@link ProviderDetails.Builder} for further configuration
* @return the {@link AssertingPartyDetails.Builder} for further configuration
*/
public Builder singleSignOnServiceBinding(Saml2MessageBinding singleSignOnServiceBinding) {
this.singleSignOnServiceBinding = singleSignOnServiceBinding;
@ -910,126 +719,6 @@ public final class RelyingPartyRegistration {
}
/**
* Configuration for IDP SSO endpoint configuration
*
* @since 5.3
* @deprecated Use {@link AssertingPartyDetails} instead
*/
@Deprecated
public static final class ProviderDetails {
private final AssertingPartyDetails assertingPartyDetails;
private ProviderDetails(AssertingPartyDetails assertingPartyDetails) {
Assert.notNull("assertingPartyDetails cannot be null");
this.assertingPartyDetails = assertingPartyDetails;
}
/**
* Returns the entity ID of the Identity Provider
* @return the entity ID of the IDP
*/
public String getEntityId() {
return this.assertingPartyDetails.getEntityId();
}
/**
* Contains the URL for which to send the SAML 2 Authentication Request to
* initiate a single sign on flow.
* @return a IDP URL that accepts REDIRECT or POST binding for authentication
* requests
*/
public String getWebSsoUrl() {
return this.assertingPartyDetails.getSingleSignOnServiceLocation();
}
/**
* @return {@code true} if AuthNRequests from this relying party to the IDP should
* be signed {@code false} if no signature is required.
*/
public boolean isSignAuthNRequest() {
return this.assertingPartyDetails.getWantAuthnRequestsSigned();
}
/**
* @return the type of SAML 2 Binding the AuthNRequest should be sent on
*/
public Saml2MessageBinding getBinding() {
return this.assertingPartyDetails.getSingleSignOnServiceBinding();
}
/**
* Builder for IDP SSO endpoint configuration
*
* @since 5.3
* @deprecated Use {@link AssertingPartyDetails.Builder} instead
*/
@Deprecated
public static final class Builder {
private AssertingPartyDetails.Builder assertingPartyDetailsBuilder = new AssertingPartyDetails.Builder();
/**
* Set the asserting party's <a href=
* "https://www.oasis-open.org/committees/download.php/51890/SAML%20MD%20simplified%20overview.pdf#2.9%20EntityDescriptor">EntityID</a>.
* Equivalent to the value found in the asserting party's &lt;EntityDescriptor
* EntityID="..."/&gt;
* @param entityId the asserting party's EntityID
* @return the {@link Builder} for further configuration
* @since 5.4
*/
public Builder entityId(String entityId) {
this.assertingPartyDetailsBuilder.entityId(entityId);
return this;
}
/**
* Sets the {@code SSO URL} for the remote asserting party, the Identity
* Provider.
* @param url - a URL that accepts authentication requests via REDIRECT or
* POST bindings
* @return this object
*/
public Builder webSsoUrl(String url) {
this.assertingPartyDetailsBuilder.singleSignOnServiceLocation(url);
return this;
}
/**
* Set to true if the AuthNRequest message should be signed
* @param signAuthNRequest true if the message should be signed
* @return this object
*/
public Builder signAuthNRequest(boolean signAuthNRequest) {
this.assertingPartyDetailsBuilder.wantAuthnRequestsSigned(signAuthNRequest);
return this;
}
/**
* Sets the message binding to be used when sending an AuthNRequest message
* @param binding either {@link Saml2MessageBinding#POST} or
* {@link Saml2MessageBinding#REDIRECT}
* @return this object
*/
public Builder binding(Saml2MessageBinding binding) {
this.assertingPartyDetailsBuilder.singleSignOnServiceBinding(binding);
return this;
}
/**
* Creates an immutable ProviderDetails object representing the configuration
* for an Identity Provider, IDP
* @return immutable ProviderDetails object
*/
public ProviderDetails build() {
return new ProviderDetails(this.assertingPartyDetailsBuilder.build());
}
}
}
public static final class Builder {
private String registrationId;
@ -1052,9 +741,7 @@ public final class RelyingPartyRegistration {
private String nameIdFormat = null;
private ProviderDetails.Builder providerDetails = new ProviderDetails.Builder();
private Collection<org.springframework.security.saml2.credentials.Saml2X509Credential> credentials = new LinkedHashSet<>();
private AssertingPartyDetails.Builder assertingPartyDetailsBuilder = new AssertingPartyDetails.Builder();
private Builder(String registrationId) {
this.registrationId = registrationId;
@ -1225,104 +912,7 @@ public final class RelyingPartyRegistration {
* @since 5.4
*/
public Builder assertingPartyDetails(Consumer<AssertingPartyDetails.Builder> assertingPartyDetails) {
assertingPartyDetails.accept(this.providerDetails.assertingPartyDetailsBuilder);
return this;
}
/**
* Modifies the collection of {@link Saml2X509Credential} objects used in
* communication between IDP and SP For example: <code>
* Saml2X509Credential credential = ...;
* return RelyingPartyRegistration.withRegistrationId("id")
* .credentials((c) -&gt; c.add(credential))
* ...
* .build();
* </code>
* @param credentials - a consumer that can modify the collection of credentials
* @return this object
* @deprecated Use {@link #signingX509Credentials} or
* {@link #decryptionX509Credentials} instead for relying party keys or
* {@link AssertingPartyDetails.Builder#verificationX509Credentials} or
* {@link AssertingPartyDetails.Builder#encryptionX509Credentials} for asserting
* party keys
*/
@Deprecated
public Builder credentials(
Consumer<Collection<org.springframework.security.saml2.credentials.Saml2X509Credential>> credentials) {
credentials.accept(this.credentials);
return this;
}
/**
* <a href=
* "https://www.oasis-open.org/committees/download.php/51890/SAML%20MD%20simplified%20overview.pdf#2.3%20AttributeConsumingService">Assertion
* Consumer Service</a> URL template. It can contain variables {@code baseUrl},
* {@code registrationId}, {@code baseScheme}, {@code baseHost}, and
* {@code basePort}.
* @param assertionConsumerServiceUrlTemplate the Assertion Consumer Service URL
* template (i.e. "{baseUrl}/login/saml2/sso/{registrationId}".
* @return this object
* @deprecated Use {@link #assertionConsumerServiceLocation} instead.
*/
@Deprecated
public Builder assertionConsumerServiceUrlTemplate(String assertionConsumerServiceUrlTemplate) {
this.assertionConsumerServiceLocation = assertionConsumerServiceUrlTemplate;
return this;
}
/**
* Sets the {@code entityId} for the remote asserting party, the Identity
* Provider.
* @param entityId the IDP entityId
* @return this object
* @deprecated use
* {@code #assertingPartyDetails(Consumer<AssertingPartyDetails.Builder >)}
*/
@Deprecated
public Builder remoteIdpEntityId(String entityId) {
assertingPartyDetails((idp) -> idp.entityId(entityId));
return this;
}
/**
* Sets the {@code SSO URL} for the remote asserting party, the Identity Provider.
* @param url - a URL that accepts authentication requests via REDIRECT or POST
* bindings
* @return this object
* @deprecated use
* {@code #assertingPartyDetails(Consumer<AssertingPartyDetails.Builder >)}
*/
@Deprecated
public Builder idpWebSsoUrl(String url) {
assertingPartyDetails((config) -> config.singleSignOnServiceLocation(url));
return this;
}
/**
* Sets the local relying party, or Service Provider, entity Id template. can
* generate it's entity ID based on possible variables of {@code baseUrl},
* {@code registrationId}, {@code baseScheme}, {@code baseHost}, and
* {@code basePort}, for example
* {@code {baseUrl}/saml2/service-provider-metadata/{registrationId}}
* @param template the entity id
* @return a string containing the entity ID or entity ID template
* @deprecated Use {@link #entityId} instead
*/
@Deprecated
public Builder localEntityIdTemplate(String template) {
this.entityId = template;
return this;
}
/**
* Configures the IDP SSO endpoint
* @param providerDetails a consumer that configures the IDP SSO endpoint
* @return this object
* @deprecated Use {@link #assertingPartyDetails} instead
*/
@Deprecated
public Builder providerDetails(Consumer<ProviderDetails.Builder> providerDetails) {
providerDetails.accept(this.providerDetails);
assertingPartyDetails.accept(this.assertingPartyDetailsBuilder);
return this;
}
@ -1332,41 +922,13 @@ public final class RelyingPartyRegistration {
* @return a RelyingPartyRegistration instance
*/
public RelyingPartyRegistration build() {
for (org.springframework.security.saml2.credentials.Saml2X509Credential credential : this.credentials) {
Saml2X509Credential mapped = fromDeprecated(credential);
if (credential.isSigningCredential()) {
signingX509Credentials((c) -> c.add(mapped));
}
if (credential.isDecryptionCredential()) {
decryptionX509Credentials((c) -> c.add(mapped));
}
if (credential.isSignatureVerficationCredential()) {
this.providerDetails.assertingPartyDetailsBuilder.verificationX509Credentials((c) -> c.add(mapped));
}
if (credential.isEncryptionCredential()) {
this.providerDetails.assertingPartyDetailsBuilder.encryptionX509Credentials((c) -> c.add(mapped));
}
}
for (Saml2X509Credential credential : this.signingX509Credentials) {
this.credentials.add(toDeprecated(credential));
}
for (Saml2X509Credential credential : this.decryptionX509Credentials) {
this.credentials.add(toDeprecated(credential));
}
for (Saml2X509Credential credential : this.providerDetails.assertingPartyDetailsBuilder.verificationX509Credentials) {
this.credentials.add(toDeprecated(credential));
}
for (Saml2X509Credential credential : this.providerDetails.assertingPartyDetailsBuilder.encryptionX509Credentials) {
this.credentials.add(toDeprecated(credential));
}
if (this.singleLogoutServiceResponseLocation == null) {
this.singleLogoutServiceResponseLocation = this.singleLogoutServiceLocation;
}
return new RelyingPartyRegistration(this.registrationId, this.entityId,
this.assertionConsumerServiceLocation, this.assertionConsumerServiceBinding,
this.singleLogoutServiceLocation, this.singleLogoutServiceResponseLocation,
this.singleLogoutServiceBinding, this.providerDetails.build(), this.nameIdFormat, this.credentials,
this.singleLogoutServiceBinding, this.assertingPartyDetailsBuilder.build(), this.nameIdFormat,
this.decryptionX509Credentials, this.signingX509Credentials);
}

View File

@ -23,30 +23,17 @@ import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.opensaml.core.Version;
import org.springframework.http.MediaType;
import org.springframework.security.saml2.core.Saml2ParameterNames;
import org.springframework.security.saml2.provider.service.authentication.AbstractSaml2AuthenticationRequest;
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.Saml2PostAuthenticationRequest;
import org.springframework.security.saml2.provider.service.authentication.Saml2RedirectAuthenticationRequest;
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.Saml2MessageBinding;
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.authentication.Saml2AuthenticationRequestResolver;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher.MatchResult;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.HtmlUtils;
@ -82,53 +69,6 @@ public class Saml2WebSsoAuthenticationRequestFilter extends OncePerRequestFilter
private Saml2AuthenticationRequestRepository<AbstractSaml2AuthenticationRequest> authenticationRequestRepository = new HttpSessionSaml2AuthenticationRequestRepository();
/**
* Construct a {@link Saml2WebSsoAuthenticationRequestFilter} with the provided
* parameters
* @param relyingPartyRegistrationRepository a repository for relying party
* configurations
* @deprecated use the constructor that takes a
* {@link Saml2AuthenticationRequestFactory}
*/
@Deprecated
public Saml2WebSsoAuthenticationRequestFilter(
RelyingPartyRegistrationRepository relyingPartyRegistrationRepository) {
this(new DefaultSaml2AuthenticationRequestContextResolver(
(RelyingPartyRegistrationResolver) new DefaultRelyingPartyRegistrationResolver(
relyingPartyRegistrationRepository)),
requestFactory());
}
private static Saml2AuthenticationRequestFactory requestFactory() {
String opensamlClassName = "org.springframework.security.saml2.provider.service.authentication.OpenSamlAuthenticationRequestFactory";
if (Version.getVersion().startsWith("4")) {
opensamlClassName = "org.springframework.security.saml2.provider.service.authentication.OpenSaml4AuthenticationRequestFactory";
}
try {
return (Saml2AuthenticationRequestFactory) ClassUtils.forName(opensamlClassName, null)
.getDeclaredConstructor().newInstance();
}
catch (Exception ex) {
throw new IllegalStateException(ex);
}
}
/**
* Construct a {@link Saml2WebSsoAuthenticationRequestFilter} with the provided
* parameters
* @param authenticationRequestContextResolver a strategy for formulating a
* {@link Saml2AuthenticationRequestContext}
* @param authenticationRequestFactory strategy for formulating a
* &lt;saml2:AuthnRequest&gt;
* @since 5.4
*/
public Saml2WebSsoAuthenticationRequestFilter(
Saml2AuthenticationRequestContextResolver authenticationRequestContextResolver,
Saml2AuthenticationRequestFactory authenticationRequestFactory) {
this(new FactorySaml2AuthenticationRequestResolver(authenticationRequestContextResolver,
authenticationRequestFactory));
}
/**
* Construct a {@link Saml2WebSsoAuthenticationRequestFilter} with the strategy for
* resolving the {@code AuthnRequest}
@ -141,35 +81,6 @@ public class Saml2WebSsoAuthenticationRequestFilter extends OncePerRequestFilter
this.authenticationRequestResolver = authenticationRequestResolver;
}
/**
* Use the given {@link Saml2AuthenticationRequestFactory} for formulating the SAML
* 2.0 AuthnRequest
* @param authenticationRequestFactory the {@link Saml2AuthenticationRequestFactory}
* to use
* @deprecated use the constructor instead
*/
@Deprecated
public void setAuthenticationRequestFactory(Saml2AuthenticationRequestFactory authenticationRequestFactory) {
Assert.notNull(authenticationRequestFactory, "authenticationRequestFactory cannot be null");
Assert.isInstanceOf(FactorySaml2AuthenticationRequestResolver.class, this.authenticationRequestResolver,
"You cannot supply both a Saml2AuthenticationRequestResolver and a Saml2AuthenticationRequestFactory");
((FactorySaml2AuthenticationRequestResolver) this.authenticationRequestResolver).authenticationRequestFactory = authenticationRequestFactory;
}
/**
* Use the given {@link RequestMatcher} that activates this filter for a given request
* @param redirectMatcher the {@link RequestMatcher} to use
* @deprecated Configure the request matcher in an implementation of
* {@link Saml2AuthenticationRequestResolver} instead
*/
@Deprecated
public void setRedirectMatcher(RequestMatcher redirectMatcher) {
Assert.notNull(redirectMatcher, "redirectMatcher cannot be null");
Assert.isInstanceOf(FactorySaml2AuthenticationRequestResolver.class, this.authenticationRequestResolver,
"You cannot supply a Saml2AuthenticationRequestResolver and a redirect matcher");
((FactorySaml2AuthenticationRequestResolver) this.authenticationRequestResolver).redirectMatcher = redirectMatcher;
}
/**
* Use the given {@link Saml2AuthenticationRequestRepository} to save the
* authentication request
@ -270,41 +181,4 @@ public class Saml2WebSsoAuthenticationRequestFilter extends OncePerRequestFilter
return html.toString();
}
private static class FactorySaml2AuthenticationRequestResolver implements Saml2AuthenticationRequestResolver {
private final Saml2AuthenticationRequestContextResolver authenticationRequestContextResolver;
private RequestMatcher redirectMatcher = new AntPathRequestMatcher("/saml2/authenticate/{registrationId}");
private Saml2AuthenticationRequestFactory authenticationRequestFactory;
FactorySaml2AuthenticationRequestResolver(
Saml2AuthenticationRequestContextResolver authenticationRequestContextResolver,
Saml2AuthenticationRequestFactory authenticationRequestFactory) {
Assert.notNull(authenticationRequestContextResolver, "authenticationRequestContextResolver cannot be null");
Assert.notNull(authenticationRequestFactory, "authenticationRequestFactory cannot be null");
this.authenticationRequestContextResolver = authenticationRequestContextResolver;
this.authenticationRequestFactory = authenticationRequestFactory;
}
@Override
public AbstractSaml2AuthenticationRequest resolve(HttpServletRequest request) {
MatchResult matcher = this.redirectMatcher.matcher(request);
if (!matcher.isMatch()) {
return null;
}
Saml2AuthenticationRequestContext context = this.authenticationRequestContextResolver.resolve(request);
if (context == null) {
return null;
}
Saml2MessageBinding binding = context.getRelyingPartyRegistration().getAssertingPartyDetails()
.getSingleSignOnServiceBinding();
if (binding == Saml2MessageBinding.REDIRECT) {
return this.authenticationRequestFactory.createRedirectAuthenticationRequest(context);
}
return this.authenticationRequestFactory.createPostAuthenticationRequest(context);
}
}
}

View File

@ -1,90 +0,0 @@
/*
* 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.saml2.provider.service.web;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.convert.converter.Converter;
import org.springframework.security.saml2.core.Saml2ParameterNames;
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationRequestContext;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
import org.springframework.util.Assert;
/**
* The default implementation for {@link Saml2AuthenticationRequestContextResolver} which
* uses the current request and given relying party to formulate a
* {@link Saml2AuthenticationRequestContext}
*
* @author Shazin Sadakath
* @author Josh Cummings
* @since 5.4
* @deprecated Use
* {@link org.springframework.security.saml2.provider.service.web.authentication.Saml2AuthenticationRequestResolver}
* instead
*/
@Deprecated
public final class DefaultSaml2AuthenticationRequestContextResolver
implements Saml2AuthenticationRequestContextResolver {
private final Log logger = LogFactory.getLog(getClass());
private final Converter<HttpServletRequest, RelyingPartyRegistration> relyingPartyRegistrationResolver;
/**
* Construct a {@link DefaultSaml2AuthenticationRequestContextResolver}
* @param relyingPartyRegistrationResolver
* @deprecated Use
* {@link DefaultSaml2AuthenticationRequestContextResolver#DefaultSaml2AuthenticationRequestContextResolver(RelyingPartyRegistrationResolver)}
* instead
*/
@Deprecated
public DefaultSaml2AuthenticationRequestContextResolver(
Converter<HttpServletRequest, RelyingPartyRegistration> relyingPartyRegistrationResolver) {
this.relyingPartyRegistrationResolver = relyingPartyRegistrationResolver;
}
public DefaultSaml2AuthenticationRequestContextResolver(
RelyingPartyRegistrationResolver relyingPartyRegistrationResolver) {
this.relyingPartyRegistrationResolver = (request) -> relyingPartyRegistrationResolver.resolve(request, null);
}
@Override
public Saml2AuthenticationRequestContext resolve(HttpServletRequest request) {
Assert.notNull(request, "request cannot be null");
RelyingPartyRegistration relyingParty = this.relyingPartyRegistrationResolver.convert(request);
if (relyingParty == null) {
return null;
}
if (this.logger.isDebugEnabled()) {
this.logger.debug("Creating SAML 2.0 Authentication Request for Asserting Party ["
+ relyingParty.getRegistrationId() + "]");
}
return createRedirectAuthenticationRequestContext(request, relyingParty);
}
private Saml2AuthenticationRequestContext createRedirectAuthenticationRequestContext(HttpServletRequest request,
RelyingPartyRegistration relyingParty) {
return Saml2AuthenticationRequestContext.builder().issuer(relyingParty.getEntityId())
.relyingPartyRegistration(relyingParty)
.assertionConsumerServiceUrl(relyingParty.getAssertionConsumerServiceLocation())
.relayState(request.getParameter(Saml2ParameterNames.RELAY_STATE)).build();
}
}

View File

@ -1,46 +0,0 @@
/*
* 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.saml2.provider.service.web;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationRequestContext;
/**
* This {@code Saml2AuthenticationRequestContextResolver} formulates a
* <a href="https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf">SAML 2.0
* AuthnRequest</a> (line 1968)
*
* @author Shazin Sadakath
* @author Josh Cummings
* @since 5.4
* @deprecated Use
* {@link org.springframework.security.saml2.provider.service.web.authentication.Saml2AuthenticationRequestResolver}
* instead
*/
@Deprecated
public interface Saml2AuthenticationRequestContextResolver {
/**
* This {@code resolve} method is defined to create a
* {@link Saml2AuthenticationRequestContext}
* @param request the current request
* @return the created {@link Saml2AuthenticationRequestContext} for the request
*/
Saml2AuthenticationRequestContext resolve(HttpServletRequest request);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@ -54,25 +54,10 @@ public final class Saml2AuthenticationTokenConverter implements AuthenticationCo
private Function<HttpServletRequest, AbstractSaml2AuthenticationRequest> loader;
/**
* Constructs a {@link Saml2AuthenticationTokenConverter} given a strategy for
* resolving {@link RelyingPartyRegistration}s
* @param relyingPartyRegistrationResolver the strategy for resolving
* {@link RelyingPartyRegistration}s
* @deprecated Use
* {@link Saml2AuthenticationTokenConverter#Saml2AuthenticationTokenConverter(RelyingPartyRegistrationResolver)}
* instead
*/
@Deprecated
public Saml2AuthenticationTokenConverter(
Converter<HttpServletRequest, RelyingPartyRegistration> relyingPartyRegistrationResolver) {
Assert.notNull(relyingPartyRegistrationResolver, "relyingPartyRegistrationResolver cannot be null");
this.relyingPartyRegistrationResolver = relyingPartyRegistrationResolver;
this.loader = new HttpSessionSaml2AuthenticationRequestRepository()::loadAuthenticationRequest;
}
public Saml2AuthenticationTokenConverter(RelyingPartyRegistrationResolver relyingPartyRegistrationResolver) {
this(adaptToConverter(relyingPartyRegistrationResolver));
Assert.notNull(relyingPartyRegistrationResolver, "relyingPartyRegistrationResolver cannot be null");
this.relyingPartyRegistrationResolver = adaptToConverter(relyingPartyRegistrationResolver);
this.loader = new HttpSessionSaml2AuthenticationRequestRepository()::loadAuthenticationRequest;
}
private static Converter<HttpServletRequest, RelyingPartyRegistration> adaptToConverter(

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@ -25,7 +25,6 @@ import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.core.convert.converter.Converter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.security.saml2.provider.service.metadata.Saml2MetadataResolver;
@ -55,21 +54,6 @@ public final class Saml2MetadataFilter extends OncePerRequestFilter {
private RequestMatcher requestMatcher = new AntPathRequestMatcher(
"/saml2/service-provider-metadata/{registrationId}");
/**
* Construct a {@link Saml2MetadataFilter}
* @param relyingPartyRegistrationResolver
* @param saml2MetadataResolver
* @deprecated Use
* {@link Saml2MetadataFilter#Saml2MetadataFilter(RelyingPartyRegistrationResolver, Saml2MetadataResolver)}
* instead
*/
@Deprecated
public Saml2MetadataFilter(Converter<HttpServletRequest, RelyingPartyRegistration> relyingPartyRegistrationResolver,
Saml2MetadataResolver saml2MetadataResolver) {
this.relyingPartyRegistrationResolver = (request, id) -> relyingPartyRegistrationResolver.convert(request);
this.saml2MetadataResolver = saml2MetadataResolver;
}
public Saml2MetadataFilter(RelyingPartyRegistrationResolver relyingPartyRegistrationResolver,
Saml2MetadataResolver saml2MetadataResolver) {
Assert.notNull(relyingPartyRegistrationResolver, "relyingPartyRegistrationResolver cannot be null");

View File

@ -1,206 +0,0 @@
/*
* Copyright 2002-2021 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.saml2.provider.service.authentication;
import java.nio.charset.StandardCharsets;
import java.time.Clock;
import java.time.Instant;
import java.util.Map;
import java.util.UUID;
import org.joda.time.DateTime;
import org.opensaml.core.config.ConfigurationService;
import org.opensaml.core.xml.config.XMLObjectProviderRegistry;
import org.opensaml.saml.common.xml.SAMLConstants;
import org.opensaml.saml.saml2.core.AuthnRequest;
import org.opensaml.saml.saml2.core.Issuer;
import org.opensaml.saml.saml2.core.impl.AuthnRequestBuilder;
import org.opensaml.saml.saml2.core.impl.IssuerBuilder;
import org.springframework.core.convert.converter.Converter;
import org.springframework.security.saml2.core.OpenSamlInitializationService;
import org.springframework.security.saml2.core.Saml2ParameterNames;
import org.springframework.security.saml2.provider.service.authentication.OpenSamlSigningUtils.QueryParametersPartial;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* A {@link Saml2AuthenticationRequestFactory} that generates, signs, and serializes a
* SAML 2.0 AuthnRequest using OpenSAML 3
*
* @author Filip Hanik
* @author Josh Cummings
* @since 5.2
* @deprecated Because OpenSAML 3 has reached End-of-Life, please update to
* {@code OpenSaml4AuthenticationRequestFactory}
*/
public class OpenSamlAuthenticationRequestFactory implements Saml2AuthenticationRequestFactory {
static {
OpenSamlInitializationService.initialize();
}
private AuthnRequestBuilder authnRequestBuilder;
private IssuerBuilder issuerBuilder;
private Clock clock = Clock.systemUTC();
private Converter<Saml2AuthenticationRequestContext, Saml2MessageBinding> protocolBindingResolver = (context) -> {
if (context == null) {
return Saml2MessageBinding.POST;
}
return context.getRelyingPartyRegistration().getAssertionConsumerServiceBinding();
};
private Converter<Saml2AuthenticationRequestContext, AuthnRequest> authenticationRequestContextConverter;
/**
* Creates an {@link OpenSamlAuthenticationRequestFactory}
*/
public OpenSamlAuthenticationRequestFactory() {
this.authenticationRequestContextConverter = this::createAuthnRequest;
XMLObjectProviderRegistry registry = ConfigurationService.get(XMLObjectProviderRegistry.class);
this.authnRequestBuilder = (AuthnRequestBuilder) registry.getBuilderFactory()
.getBuilder(AuthnRequest.DEFAULT_ELEMENT_NAME);
this.issuerBuilder = (IssuerBuilder) registry.getBuilderFactory().getBuilder(Issuer.DEFAULT_ELEMENT_NAME);
}
@Override
@Deprecated
public String createAuthenticationRequest(Saml2AuthenticationRequest request) {
Saml2MessageBinding binding = this.protocolBindingResolver.convert(null);
RelyingPartyRegistration registration = RelyingPartyRegistration.withRegistrationId("noId")
.assertionConsumerServiceBinding(binding)
.assertionConsumerServiceLocation(request.getAssertionConsumerServiceUrl())
.entityId(request.getIssuer()).remoteIdpEntityId("noIssuer").idpWebSsoUrl("noUrl")
.credentials((credentials) -> credentials.addAll(request.getCredentials())).build();
Saml2AuthenticationRequestContext context = Saml2AuthenticationRequestContext.builder()
.relyingPartyRegistration(registration).issuer(request.getIssuer())
.assertionConsumerServiceUrl(request.getAssertionConsumerServiceUrl()).build();
AuthnRequest authnRequest = this.authenticationRequestContextConverter.convert(context);
return OpenSamlSigningUtils.serialize(OpenSamlSigningUtils.sign(authnRequest, registration));
}
@Override
public Saml2PostAuthenticationRequest createPostAuthenticationRequest(Saml2AuthenticationRequestContext context) {
AuthnRequest authnRequest = this.authenticationRequestContextConverter.convert(context);
RelyingPartyRegistration registration = context.getRelyingPartyRegistration();
if (registration.getAssertingPartyDetails().getWantAuthnRequestsSigned()) {
OpenSamlSigningUtils.sign(authnRequest, registration);
}
String xml = OpenSamlSigningUtils.serialize(authnRequest);
return Saml2PostAuthenticationRequest.withAuthenticationRequestContext(context)
.samlRequest(Saml2Utils.samlEncode(xml.getBytes(StandardCharsets.UTF_8))).build();
}
@Override
public Saml2RedirectAuthenticationRequest createRedirectAuthenticationRequest(
Saml2AuthenticationRequestContext context) {
AuthnRequest authnRequest = this.authenticationRequestContextConverter.convert(context);
RelyingPartyRegistration registration = context.getRelyingPartyRegistration();
String xml = OpenSamlSigningUtils.serialize(authnRequest);
Saml2RedirectAuthenticationRequest.Builder result = Saml2RedirectAuthenticationRequest
.withAuthenticationRequestContext(context);
String deflatedAndEncoded = Saml2Utils.samlEncode(Saml2Utils.samlDeflate(xml));
result.samlRequest(deflatedAndEncoded).relayState(context.getRelayState());
if (registration.getAssertingPartyDetails().getWantAuthnRequestsSigned()) {
QueryParametersPartial partial = OpenSamlSigningUtils.sign(registration)
.param(Saml2ParameterNames.SAML_REQUEST, deflatedAndEncoded);
if (StringUtils.hasText(context.getRelayState())) {
partial.param(Saml2ParameterNames.RELAY_STATE, context.getRelayState());
}
Map<String, String> parameters = partial.parameters();
return result.sigAlg(parameters.get(Saml2ParameterNames.SIG_ALG))
.signature(parameters.get(Saml2ParameterNames.SIGNATURE)).build();
}
return result.build();
}
private AuthnRequest createAuthnRequest(Saml2AuthenticationRequestContext context) {
String issuer = context.getIssuer();
String destination = context.getDestination();
String assertionConsumerServiceUrl = context.getAssertionConsumerServiceUrl();
Saml2MessageBinding protocolBinding = this.protocolBindingResolver.convert(context);
AuthnRequest auth = this.authnRequestBuilder.buildObject();
if (auth.getID() == null) {
auth.setID("ARQ" + UUID.randomUUID().toString().substring(1));
}
if (auth.getIssueInstant() == null) {
auth.setIssueInstant(new DateTime(this.clock.millis()));
}
if (auth.isForceAuthn() == null) {
auth.setForceAuthn(Boolean.FALSE);
}
if (auth.isPassive() == null) {
auth.setIsPassive(Boolean.FALSE);
}
if (auth.getProtocolBinding() == null) {
auth.setProtocolBinding(protocolBinding.getUrn());
}
Issuer iss = this.issuerBuilder.buildObject();
iss.setValue(issuer);
auth.setIssuer(iss);
auth.setDestination(destination);
auth.setAssertionConsumerServiceURL(assertionConsumerServiceUrl);
return auth;
}
/**
* Set the {@link AuthnRequest} post-processor resolver
* @param authenticationRequestContextConverter a strategy for creating an
* {@link AuthnRequest}
* @since 5.4
*/
public void setAuthenticationRequestContextConverter(
Converter<Saml2AuthenticationRequestContext, AuthnRequest> authenticationRequestContextConverter) {
Assert.notNull(authenticationRequestContextConverter, "authenticationRequestContextConverter cannot be null");
this.authenticationRequestContextConverter = authenticationRequestContextConverter;
}
/**
* ' Use this {@link Clock} with {@link Instant#now()} for generating timestamps
* @param clock the {@link Clock} to use
*/
public void setClock(Clock clock) {
Assert.notNull(clock, "clock cannot be null");
this.clock = clock;
}
/**
* Sets the {@code protocolBinding} to use when generating authentication requests.
* Acceptable values are {@link SAMLConstants#SAML2_POST_BINDING_URI} and
* {@link SAMLConstants#SAML2_REDIRECT_BINDING_URI} The IDP will be reading this value
* in the {@code AuthNRequest} to determine how to send the Response/Assertion to the
* ACS URL, assertion consumer service URL.
* @param protocolBinding either {@link SAMLConstants#SAML2_POST_BINDING_URI} or
* {@link SAMLConstants#SAML2_REDIRECT_BINDING_URI}
* @throws IllegalArgumentException if the protocolBinding is not valid
* @deprecated Use
* {@link org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration.Builder#assertionConsumerServiceBinding(Saml2MessageBinding)}
* instead
*/
@Deprecated
public void setProtocolBinding(String protocolBinding) {
Saml2MessageBinding binding = Saml2MessageBinding.from(protocolBinding);
Assert.notNull(binding, "Invalid protocol binding: " + protocolBinding);
this.protocolBindingResolver = (context) -> binding;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@ -606,9 +606,9 @@ public class OpenSamlAuthenticationProviderTests {
private Consumer<Saml2AuthenticationException> errorOf(String errorCode, String description) {
return (ex) -> {
assertThat(ex.getError().getErrorCode()).isEqualTo(errorCode);
assertThat(ex.getSaml2Error().getErrorCode()).isEqualTo(errorCode);
if (StringUtils.hasText(description)) {
assertThat(ex.getError().getDescription()).contains(description);
assertThat(ex.getSaml2Error().getDescription()).contains(description);
}
};
}

View File

@ -1,287 +0,0 @@
/*
* Copyright 2002-2020 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.saml2.provider.service.authentication;
import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import org.joda.time.DateTime;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
import org.opensaml.saml.common.xml.SAMLConstants;
import org.opensaml.saml.saml2.core.AuthnRequest;
import org.opensaml.saml.saml2.core.impl.AuthnRequestUnmarshaller;
import org.opensaml.xmlsec.signature.support.SignatureConstants;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.springframework.core.convert.converter.Converter;
import org.springframework.security.saml2.Saml2Exception;
import org.springframework.security.saml2.core.Saml2X509Credential;
import org.springframework.security.saml2.credentials.TestSaml2X509Credentials;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
/**
* Tests for {@link OpenSamlAuthenticationRequestFactory}
*/
public class OpenSamlAuthenticationRequestFactoryTests {
private OpenSamlAuthenticationRequestFactory factory;
private Saml2AuthenticationRequestContext.Builder contextBuilder;
private Saml2AuthenticationRequestContext context;
private RelyingPartyRegistration.Builder relyingPartyRegistrationBuilder;
private RelyingPartyRegistration relyingPartyRegistration;
private AuthnRequestUnmarshaller unmarshaller;
@BeforeEach
public void setUp() {
this.relyingPartyRegistrationBuilder = RelyingPartyRegistration.withRegistrationId("id")
.assertionConsumerServiceLocation("template")
.providerDetails((c) -> c.webSsoUrl("https://destination/sso"))
.providerDetails((c) -> c.entityId("remote-entity-id")).localEntityIdTemplate("local-entity-id")
.credentials((c) -> c.add(TestSaml2X509Credentials.relyingPartySigningCredential()));
this.relyingPartyRegistration = this.relyingPartyRegistrationBuilder.build();
this.contextBuilder = Saml2AuthenticationRequestContext.builder().issuer("https://issuer")
.relyingPartyRegistration(this.relyingPartyRegistration)
.assertionConsumerServiceUrl("https://issuer/sso");
this.context = this.contextBuilder.build();
this.factory = new OpenSamlAuthenticationRequestFactory();
this.unmarshaller = (AuthnRequestUnmarshaller) XMLObjectProviderRegistrySupport.getUnmarshallerFactory()
.getUnmarshaller(AuthnRequest.DEFAULT_ELEMENT_NAME);
}
@Test
public void createAuthenticationRequestWhenInvokingDeprecatedMethodThenReturnsXML() {
Saml2AuthenticationRequest request = Saml2AuthenticationRequest.withAuthenticationRequestContext(this.context)
.build();
String result = this.factory.createAuthenticationRequest(request);
assertThat(result.replace("\n", ""))
.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\"?><saml2p:AuthnRequest");
}
@Test
public void createRedirectAuthenticationRequestWhenUsingContextThenAllValuesAreSet() {
this.context = this.contextBuilder.relayState("Relay State Value").build();
Saml2RedirectAuthenticationRequest result = this.factory.createRedirectAuthenticationRequest(this.context);
assertThat(result.getSamlRequest()).isNotEmpty();
assertThat(result.getRelayState()).isEqualTo("Relay State Value");
assertThat(result.getSigAlg()).isNotEmpty();
assertThat(result.getSignature()).isNotEmpty();
assertThat(result.getBinding()).isEqualTo(Saml2MessageBinding.REDIRECT);
}
@Test
public void createRedirectAuthenticationRequestWhenNotSignRequestThenNoSignatureIsPresent() {
this.context = this.contextBuilder.relayState("Relay State Value")
.relyingPartyRegistration(
RelyingPartyRegistration.withRelyingPartyRegistration(this.relyingPartyRegistration)
.providerDetails((c) -> c.signAuthNRequest(false)).build())
.build();
Saml2RedirectAuthenticationRequest result = this.factory.createRedirectAuthenticationRequest(this.context);
assertThat(result.getSamlRequest()).isNotEmpty();
assertThat(result.getRelayState()).isEqualTo("Relay State Value");
assertThat(result.getSigAlg()).isNull();
assertThat(result.getSignature()).isNull();
assertThat(result.getBinding()).isEqualTo(Saml2MessageBinding.REDIRECT);
}
@Test
public void createRedirectAuthenticationRequestWhenSignRequestThenSignatureIsPresent() {
this.context = this.contextBuilder.relayState("Relay State Value")
.relyingPartyRegistration(this.relyingPartyRegistration).build();
Saml2RedirectAuthenticationRequest request = this.factory.createRedirectAuthenticationRequest(this.context);
assertThat(request.getRelayState()).isEqualTo("Relay State Value");
assertThat(request.getSigAlg()).isEqualTo(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256);
assertThat(request.getSignature()).isNotNull();
}
@Test
public void createRedirectAuthenticationRequestWhenSignRequestThenCredentialIsRequired() {
Saml2X509Credential credential = org.springframework.security.saml2.core.TestSaml2X509Credentials
.relyingPartyVerifyingCredential();
RelyingPartyRegistration registration = TestRelyingPartyRegistrations.noCredentials()
.assertingPartyDetails((party) -> party.verificationX509Credentials((c) -> c.add(credential))).build();
this.context = this.contextBuilder.relayState("Relay State Value").relyingPartyRegistration(registration)
.build();
assertThatExceptionOfType(Saml2Exception.class)
.isThrownBy(() -> this.factory.createPostAuthenticationRequest(this.context));
}
@Test
public void createPostAuthenticationRequestWhenNotSignRequestThenNoSignatureIsPresent() {
this.context = this.contextBuilder.relayState("Relay State Value")
.relyingPartyRegistration(
RelyingPartyRegistration.withRelyingPartyRegistration(this.relyingPartyRegistration)
.providerDetails((c) -> c.signAuthNRequest(false)).build())
.build();
Saml2PostAuthenticationRequest result = this.factory.createPostAuthenticationRequest(this.context);
assertThat(result.getSamlRequest()).isNotEmpty();
assertThat(result.getRelayState()).isEqualTo("Relay State Value");
assertThat(result.getBinding()).isEqualTo(Saml2MessageBinding.POST);
assertThat(new String(Saml2Utils.samlDecode(result.getSamlRequest()), StandardCharsets.UTF_8))
.doesNotContain("ds:Signature");
}
@Test
public void createPostAuthenticationRequestWhenSignRequestThenSignatureIsPresent() {
this.context = this.contextBuilder.relayState("Relay State Value")
.relyingPartyRegistration(
RelyingPartyRegistration.withRelyingPartyRegistration(this.relyingPartyRegistration).build())
.build();
Saml2PostAuthenticationRequest result = this.factory.createPostAuthenticationRequest(this.context);
assertThat(result.getSamlRequest()).isNotEmpty();
assertThat(result.getRelayState()).isEqualTo("Relay State Value");
assertThat(result.getBinding()).isEqualTo(Saml2MessageBinding.POST);
assertThat(new String(Saml2Utils.samlDecode(result.getSamlRequest()), StandardCharsets.UTF_8))
.contains("ds:Signature");
}
@Test
public void createPostAuthenticationRequestWhenSignRequestThenCredentialIsRequired() {
Saml2X509Credential credential = org.springframework.security.saml2.core.TestSaml2X509Credentials
.relyingPartyVerifyingCredential();
RelyingPartyRegistration registration = TestRelyingPartyRegistrations.noCredentials()
.assertingPartyDetails((party) -> party.verificationX509Credentials((c) -> c.add(credential))).build();
this.context = this.contextBuilder.relayState("Relay State Value").relyingPartyRegistration(registration)
.build();
assertThatExceptionOfType(Saml2Exception.class)
.isThrownBy(() -> this.factory.createPostAuthenticationRequest(this.context));
}
@Test
public void createAuthenticationRequestWhenDefaultThenReturnsPostBinding() {
AuthnRequest authn = getAuthNRequest(Saml2MessageBinding.POST);
Assertions.assertEquals(SAMLConstants.SAML2_POST_BINDING_URI, authn.getProtocolBinding());
}
@Test
public void createAuthenticationRequestWhenSetUriThenReturnsCorrectBinding() {
this.factory.setProtocolBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);
AuthnRequest authn = getAuthNRequest(Saml2MessageBinding.POST);
Assertions.assertEquals(SAMLConstants.SAML2_REDIRECT_BINDING_URI, authn.getProtocolBinding());
}
@Test
public void createAuthenticationRequestWhenSetUnsupportredUriThenThrowsIllegalArgumentException() {
assertThatIllegalArgumentException().isThrownBy(() -> this.factory.setProtocolBinding("my-invalid-binding"))
.withMessageContaining("my-invalid-binding");
}
@Test
public void createPostAuthenticationRequestWhenAuthnRequestConsumerThenUses() {
Converter<Saml2AuthenticationRequestContext, AuthnRequest> authenticationRequestContextConverter = mock(
Converter.class);
given(authenticationRequestContextConverter.convert(this.context)).willReturn(authnRequest());
this.factory.setAuthenticationRequestContextConverter(authenticationRequestContextConverter);
this.factory.createPostAuthenticationRequest(this.context);
verify(authenticationRequestContextConverter).convert(this.context);
}
@Test
public void createRedirectAuthenticationRequestWhenAuthnRequestConsumerThenUses() {
Converter<Saml2AuthenticationRequestContext, AuthnRequest> authenticationRequestContextConverter = mock(
Converter.class);
given(authenticationRequestContextConverter.convert(this.context)).willReturn(authnRequest());
this.factory.setAuthenticationRequestContextConverter(authenticationRequestContextConverter);
this.factory.createRedirectAuthenticationRequest(this.context);
verify(authenticationRequestContextConverter).convert(this.context);
}
@Test
public void setAuthenticationRequestContextConverterWhenNullThenException() {
// @formatter:off
assertThatIllegalArgumentException()
.isThrownBy(() -> this.factory.setAuthenticationRequestContextConverter(null));
// @formatter:on
}
@Test
public void createPostAuthenticationRequestWhenAssertionConsumerServiceBindingThenUses() {
RelyingPartyRegistration relyingPartyRegistration = this.relyingPartyRegistrationBuilder
.assertionConsumerServiceBinding(Saml2MessageBinding.REDIRECT).build();
Saml2AuthenticationRequestContext context = this.contextBuilder
.relyingPartyRegistration(relyingPartyRegistration).build();
Saml2PostAuthenticationRequest request = this.factory.createPostAuthenticationRequest(context);
String samlRequest = request.getSamlRequest();
String inflated = new String(Saml2Utils.samlDecode(samlRequest));
assertThat(inflated).contains("ProtocolBinding=\"" + SAMLConstants.SAML2_REDIRECT_BINDING_URI + "\"");
}
@Test
public void createRedirectAuthenticationRequestWhenSHA1SignRequestThenSignatureIsPresent() {
RelyingPartyRegistration relyingPartyRegistration = this.relyingPartyRegistrationBuilder
.assertingPartyDetails(
(a) -> a.signingAlgorithms((algs) -> algs.add(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1)))
.build();
Saml2AuthenticationRequestContext context = this.contextBuilder.relayState("Relay State Value")
.relyingPartyRegistration(relyingPartyRegistration).build();
Saml2RedirectAuthenticationRequest result = this.factory.createRedirectAuthenticationRequest(context);
assertThat(result.getSamlRequest()).isNotEmpty();
assertThat(result.getRelayState()).isEqualTo("Relay State Value");
assertThat(result.getSigAlg()).isEqualTo(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1);
assertThat(result.getSignature()).isNotNull();
assertThat(result.getBinding()).isEqualTo(Saml2MessageBinding.REDIRECT);
}
private AuthnRequest authnRequest() {
AuthnRequest authnRequest = TestOpenSamlObjects.authnRequest();
authnRequest.setIssueInstant(DateTime.now());
return authnRequest;
}
private AuthnRequest getAuthNRequest(Saml2MessageBinding binding) {
AbstractSaml2AuthenticationRequest result = (binding == Saml2MessageBinding.REDIRECT)
? this.factory.createRedirectAuthenticationRequest(this.context)
: this.factory.createPostAuthenticationRequest(this.context);
String samlRequest = result.getSamlRequest();
assertThat(samlRequest).isNotEmpty();
if (result.getBinding() == Saml2MessageBinding.REDIRECT) {
samlRequest = Saml2Utils.samlInflate(Saml2Utils.samlDecode(samlRequest));
}
else {
samlRequest = new String(Saml2Utils.samlDecode(samlRequest), StandardCharsets.UTF_8);
}
try {
Document document = XMLObjectProviderRegistrySupport.getParserPool()
.parse(new ByteArrayInputStream(samlRequest.getBytes(StandardCharsets.UTF_8)));
Element element = document.getDocumentElement();
return (AuthnRequest) this.unmarshaller.unmarshall(element);
}
catch (Exception ex) {
throw new Saml2Exception(ex);
}
}
}

View File

@ -1,204 +0,0 @@
/*
* 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.saml2.provider.service.authentication;
import java.nio.charset.StandardCharsets;
import java.time.Clock;
import java.time.Instant;
import java.util.Map;
import java.util.UUID;
import org.opensaml.core.config.ConfigurationService;
import org.opensaml.core.xml.config.XMLObjectProviderRegistry;
import org.opensaml.saml.common.xml.SAMLConstants;
import org.opensaml.saml.saml2.core.AuthnRequest;
import org.opensaml.saml.saml2.core.Issuer;
import org.opensaml.saml.saml2.core.NameIDPolicy;
import org.opensaml.saml.saml2.core.impl.AuthnRequestBuilder;
import org.opensaml.saml.saml2.core.impl.IssuerBuilder;
import org.opensaml.saml.saml2.core.impl.NameIDPolicyBuilder;
import org.springframework.core.convert.converter.Converter;
import org.springframework.security.saml2.core.OpenSamlInitializationService;
import org.springframework.security.saml2.core.Saml2ParameterNames;
import org.springframework.security.saml2.provider.service.authentication.OpenSamlSigningUtils.QueryParametersPartial;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* A {@link Saml2AuthenticationRequestFactory} that generates, signs, and serializes a
* SAML 2.0 AuthnRequest using OpenSAML 4
*
* @author Josh Cummings
* @since 5.5
* @deprecated Use
* {@link org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver}
* instead
*/
@Deprecated
public final class OpenSaml4AuthenticationRequestFactory implements Saml2AuthenticationRequestFactory {
static {
OpenSamlInitializationService.initialize();
}
private final AuthnRequestBuilder authnRequestBuilder;
private final IssuerBuilder issuerBuilder;
private final NameIDPolicyBuilder nameIdPolicyBuilder;
private Clock clock = Clock.systemUTC();
private Converter<Saml2AuthenticationRequestContext, AuthnRequest> authenticationRequestContextConverter;
/**
* Creates an {@link OpenSaml4AuthenticationRequestFactory}
*/
public OpenSaml4AuthenticationRequestFactory() {
this.authenticationRequestContextConverter = this::createAuthnRequest;
XMLObjectProviderRegistry registry = ConfigurationService.get(XMLObjectProviderRegistry.class);
this.authnRequestBuilder = (AuthnRequestBuilder) registry.getBuilderFactory()
.getBuilder(AuthnRequest.DEFAULT_ELEMENT_NAME);
this.issuerBuilder = (IssuerBuilder) registry.getBuilderFactory().getBuilder(Issuer.DEFAULT_ELEMENT_NAME);
this.nameIdPolicyBuilder = (NameIDPolicyBuilder) registry.getBuilderFactory()
.getBuilder(NameIDPolicy.DEFAULT_ELEMENT_NAME);
}
/**
* {@inheritDoc}
*/
@Override
@Deprecated
public String createAuthenticationRequest(Saml2AuthenticationRequest request) {
RelyingPartyRegistration registration = RelyingPartyRegistration.withRegistrationId("noId")
.assertionConsumerServiceBinding(Saml2MessageBinding.POST)
.assertionConsumerServiceLocation(request.getAssertionConsumerServiceUrl())
.entityId(request.getIssuer()).remoteIdpEntityId("noIssuer").idpWebSsoUrl("noUrl")
.credentials((credentials) -> credentials.addAll(request.getCredentials())).build();
Saml2AuthenticationRequestContext context = Saml2AuthenticationRequestContext.builder()
.relyingPartyRegistration(registration).issuer(request.getIssuer())
.assertionConsumerServiceUrl(request.getAssertionConsumerServiceUrl()).build();
AuthnRequest authnRequest = this.authenticationRequestContextConverter.convert(context);
return OpenSamlSigningUtils.serialize(OpenSamlSigningUtils.sign(authnRequest, registration));
}
/**
* {@inheritDoc}
*/
@Override
public Saml2PostAuthenticationRequest createPostAuthenticationRequest(Saml2AuthenticationRequestContext context) {
AuthnRequest authnRequest = this.authenticationRequestContextConverter.convert(context);
RelyingPartyRegistration registration = context.getRelyingPartyRegistration();
if (registration.getAssertingPartyDetails().getWantAuthnRequestsSigned()) {
OpenSamlSigningUtils.sign(authnRequest, registration);
}
String xml = OpenSamlSigningUtils.serialize(authnRequest);
return Saml2PostAuthenticationRequest.withAuthenticationRequestContext(context)
.samlRequest(Saml2Utils.samlEncode(xml.getBytes(StandardCharsets.UTF_8))).build();
}
/**
* {@inheritDoc}
*/
@Override
public Saml2RedirectAuthenticationRequest createRedirectAuthenticationRequest(
Saml2AuthenticationRequestContext context) {
AuthnRequest authnRequest = this.authenticationRequestContextConverter.convert(context);
RelyingPartyRegistration registration = context.getRelyingPartyRegistration();
String xml = OpenSamlSigningUtils.serialize(authnRequest);
Saml2RedirectAuthenticationRequest.Builder result = Saml2RedirectAuthenticationRequest
.withAuthenticationRequestContext(context);
String deflatedAndEncoded = Saml2Utils.samlEncode(Saml2Utils.samlDeflate(xml));
result.samlRequest(deflatedAndEncoded).relayState(context.getRelayState());
if (registration.getAssertingPartyDetails().getWantAuthnRequestsSigned()) {
QueryParametersPartial partial = OpenSamlSigningUtils.sign(registration)
.param(Saml2ParameterNames.SAML_REQUEST, deflatedAndEncoded);
if (StringUtils.hasText(context.getRelayState())) {
partial.param(Saml2ParameterNames.RELAY_STATE, context.getRelayState());
}
Map<String, String> parameters = partial.parameters();
return result.sigAlg(parameters.get(Saml2ParameterNames.SIG_ALG))
.signature(parameters.get(Saml2ParameterNames.SIGNATURE)).build();
}
return result.build();
}
private AuthnRequest createAuthnRequest(Saml2AuthenticationRequestContext context) {
String issuer = context.getIssuer();
String destination = context.getDestination();
String assertionConsumerServiceUrl = context.getAssertionConsumerServiceUrl();
String protocolBinding = context.getRelyingPartyRegistration().getAssertionConsumerServiceBinding().getUrn();
AuthnRequest auth = this.authnRequestBuilder.buildObject();
if (auth.getID() == null) {
auth.setID("ARQ" + UUID.randomUUID().toString().substring(1));
}
if (auth.getIssueInstant() == null) {
auth.setIssueInstant(Instant.now(this.clock));
}
if (auth.isForceAuthn() == null) {
auth.setForceAuthn(Boolean.FALSE);
}
if (auth.isPassive() == null) {
auth.setIsPassive(Boolean.FALSE);
}
if (auth.getProtocolBinding() == null) {
auth.setProtocolBinding(SAMLConstants.SAML2_POST_BINDING_URI);
}
auth.setProtocolBinding(protocolBinding);
if (auth.getNameIDPolicy() == null) {
setNameIdPolicy(auth, context.getRelyingPartyRegistration());
}
Issuer iss = this.issuerBuilder.buildObject();
iss.setValue(issuer);
auth.setIssuer(iss);
auth.setDestination(destination);
auth.setAssertionConsumerServiceURL(assertionConsumerServiceUrl);
return auth;
}
private void setNameIdPolicy(AuthnRequest authnRequest, RelyingPartyRegistration registration) {
if (!StringUtils.hasText(registration.getNameIdFormat())) {
return;
}
NameIDPolicy nameIdPolicy = this.nameIdPolicyBuilder.buildObject();
nameIdPolicy.setFormat(registration.getNameIdFormat());
authnRequest.setNameIDPolicy(nameIdPolicy);
}
/**
* Set the strategy for building an {@link AuthnRequest} from a given context
* @param authenticationRequestContextConverter the conversion strategy to use
*/
public void setAuthenticationRequestContextConverter(
Converter<Saml2AuthenticationRequestContext, AuthnRequest> authenticationRequestContextConverter) {
Assert.notNull(authenticationRequestContextConverter, "authenticationRequestContextConverter cannot be null");
this.authenticationRequestContextConverter = authenticationRequestContextConverter;
}
/**
* Use this {@link Clock} with {@link Instant#now()} for generating timestamps
* @param clock the {@link Clock} to use
*/
public void setClock(Clock clock) {
Assert.notNull(clock, "clock cannot be null");
this.clock = clock;
}
}

View File

@ -1,286 +0,0 @@
/*
* Copyright 2002-2021 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.saml2.provider.service.authentication;
import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
import org.opensaml.saml.common.xml.SAMLConstants;
import org.opensaml.saml.saml2.core.AuthnRequest;
import org.opensaml.saml.saml2.core.impl.AuthnRequestUnmarshaller;
import org.opensaml.xmlsec.signature.support.SignatureConstants;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.springframework.core.convert.converter.Converter;
import org.springframework.security.saml2.Saml2Exception;
import org.springframework.security.saml2.core.Saml2X509Credential;
import org.springframework.security.saml2.credentials.TestSaml2X509Credentials;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
/**
* Tests for {@link OpenSaml4AuthenticationRequestFactory}
*/
public class OpenSaml4AuthenticationRequestFactoryTests {
private OpenSaml4AuthenticationRequestFactory factory;
private Saml2AuthenticationRequestContext.Builder contextBuilder;
private Saml2AuthenticationRequestContext context;
private RelyingPartyRegistration.Builder relyingPartyRegistrationBuilder;
private RelyingPartyRegistration relyingPartyRegistration;
private AuthnRequestUnmarshaller unmarshaller;
@BeforeEach
public void setUp() {
this.relyingPartyRegistrationBuilder = RelyingPartyRegistration.withRegistrationId("id")
.assertionConsumerServiceLocation("template")
.providerDetails((c) -> c.webSsoUrl("https://destination/sso"))
.providerDetails((c) -> c.entityId("remote-entity-id")).localEntityIdTemplate("local-entity-id")
.credentials((c) -> c.add(TestSaml2X509Credentials.relyingPartySigningCredential()));
this.relyingPartyRegistration = this.relyingPartyRegistrationBuilder.build();
this.contextBuilder = Saml2AuthenticationRequestContext.builder().issuer("https://issuer")
.relyingPartyRegistration(this.relyingPartyRegistration)
.assertionConsumerServiceUrl("https://issuer/sso");
this.context = this.contextBuilder.build();
this.factory = new OpenSaml4AuthenticationRequestFactory();
this.unmarshaller = (AuthnRequestUnmarshaller) XMLObjectProviderRegistrySupport.getUnmarshallerFactory()
.getUnmarshaller(AuthnRequest.DEFAULT_ELEMENT_NAME);
}
@Test
public void createAuthenticationRequestWhenInvokingDeprecatedMethodThenReturnsXML() {
Saml2AuthenticationRequest request = Saml2AuthenticationRequest.withAuthenticationRequestContext(this.context)
.build();
String result = this.factory.createAuthenticationRequest(request);
assertThat(result.replace("\n", ""))
.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\"?><saml2p:AuthnRequest");
}
@Test
public void createRedirectAuthenticationRequestWhenUsingContextThenAllValuesAreSet() {
this.context = this.contextBuilder.relayState("Relay State Value").build();
Saml2RedirectAuthenticationRequest result = this.factory.createRedirectAuthenticationRequest(this.context);
assertThat(result.getSamlRequest()).isNotEmpty();
assertThat(result.getRelayState()).isEqualTo("Relay State Value");
assertThat(result.getSigAlg()).isNotEmpty();
assertThat(result.getSignature()).isNotEmpty();
assertThat(result.getBinding()).isEqualTo(Saml2MessageBinding.REDIRECT);
}
@Test
public void createRedirectAuthenticationRequestWhenNotSignRequestThenNoSignatureIsPresent() {
this.context = this.contextBuilder.relayState("Relay State Value")
.relyingPartyRegistration(
RelyingPartyRegistration.withRelyingPartyRegistration(this.relyingPartyRegistration)
.providerDetails((c) -> c.signAuthNRequest(false)).build())
.build();
Saml2RedirectAuthenticationRequest result = this.factory.createRedirectAuthenticationRequest(this.context);
assertThat(result.getSamlRequest()).isNotEmpty();
assertThat(result.getRelayState()).isEqualTo("Relay State Value");
assertThat(result.getSigAlg()).isNull();
assertThat(result.getSignature()).isNull();
assertThat(result.getBinding()).isEqualTo(Saml2MessageBinding.REDIRECT);
}
@Test
public void createRedirectAuthenticationRequestWhenSignRequestThenSignatureIsPresent() {
this.context = this.contextBuilder.relayState("Relay State Value")
.relyingPartyRegistration(this.relyingPartyRegistration).build();
Saml2RedirectAuthenticationRequest request = this.factory.createRedirectAuthenticationRequest(this.context);
assertThat(request.getRelayState()).isEqualTo("Relay State Value");
assertThat(request.getSigAlg()).isEqualTo(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256);
assertThat(request.getSignature()).isNotNull();
}
@Test
public void createRedirectAuthenticationRequestWhenSignRequestThenCredentialIsRequired() {
Saml2X509Credential credential = org.springframework.security.saml2.core.TestSaml2X509Credentials
.relyingPartyVerifyingCredential();
RelyingPartyRegistration registration = TestRelyingPartyRegistrations.noCredentials()
.assertingPartyDetails((party) -> party.verificationX509Credentials((c) -> c.add(credential))).build();
this.context = this.contextBuilder.relayState("Relay State Value").relyingPartyRegistration(registration)
.build();
assertThatExceptionOfType(Saml2Exception.class)
.isThrownBy(() -> this.factory.createPostAuthenticationRequest(this.context));
}
@Test
public void createPostAuthenticationRequestWhenNotSignRequestThenNoSignatureIsPresent() {
this.context = this.contextBuilder.relayState("Relay State Value")
.relyingPartyRegistration(
RelyingPartyRegistration.withRelyingPartyRegistration(this.relyingPartyRegistration)
.providerDetails((c) -> c.signAuthNRequest(false)).build())
.build();
Saml2PostAuthenticationRequest result = this.factory.createPostAuthenticationRequest(this.context);
assertThat(result.getSamlRequest()).isNotEmpty();
assertThat(result.getRelayState()).isEqualTo("Relay State Value");
assertThat(result.getBinding()).isEqualTo(Saml2MessageBinding.POST);
assertThat(new String(Saml2Utils.samlDecode(result.getSamlRequest()), StandardCharsets.UTF_8))
.doesNotContain("ds:Signature");
}
@Test
public void createPostAuthenticationRequestWhenSignRequestThenSignatureIsPresent() {
this.context = this.contextBuilder.relayState("Relay State Value")
.relyingPartyRegistration(
RelyingPartyRegistration.withRelyingPartyRegistration(this.relyingPartyRegistration).build())
.build();
Saml2PostAuthenticationRequest result = this.factory.createPostAuthenticationRequest(this.context);
assertThat(result.getSamlRequest()).isNotEmpty();
assertThat(result.getRelayState()).isEqualTo("Relay State Value");
assertThat(result.getBinding()).isEqualTo(Saml2MessageBinding.POST);
assertThat(new String(Saml2Utils.samlDecode(result.getSamlRequest()), StandardCharsets.UTF_8))
.contains("ds:Signature");
}
@Test
public void createPostAuthenticationRequestWhenSignRequestThenCredentialIsRequired() {
Saml2X509Credential credential = org.springframework.security.saml2.core.TestSaml2X509Credentials
.relyingPartyVerifyingCredential();
RelyingPartyRegistration registration = TestRelyingPartyRegistrations.noCredentials()
.assertingPartyDetails((party) -> party.verificationX509Credentials((c) -> c.add(credential))).build();
this.context = this.contextBuilder.relayState("Relay State Value").relyingPartyRegistration(registration)
.build();
assertThatExceptionOfType(Saml2Exception.class)
.isThrownBy(() -> this.factory.createPostAuthenticationRequest(this.context));
}
@Test
public void createAuthenticationRequestWhenDefaultThenReturnsPostBinding() {
AuthnRequest authn = getAuthNRequest(Saml2MessageBinding.POST);
Assertions.assertEquals(SAMLConstants.SAML2_POST_BINDING_URI, authn.getProtocolBinding());
}
@Test
public void createPostAuthenticationRequestWhenAuthnRequestConsumerThenUses() {
Converter<Saml2AuthenticationRequestContext, AuthnRequest> authenticationRequestContextConverter = mock(
Converter.class);
given(authenticationRequestContextConverter.convert(this.context)).willReturn(authnRequest());
this.factory.setAuthenticationRequestContextConverter(authenticationRequestContextConverter);
this.factory.createPostAuthenticationRequest(this.context);
verify(authenticationRequestContextConverter).convert(this.context);
}
@Test
public void createRedirectAuthenticationRequestWhenAuthnRequestConsumerThenUses() {
Converter<Saml2AuthenticationRequestContext, AuthnRequest> authenticationRequestContextConverter = mock(
Converter.class);
given(authenticationRequestContextConverter.convert(this.context)).willReturn(authnRequest());
this.factory.setAuthenticationRequestContextConverter(authenticationRequestContextConverter);
this.factory.createRedirectAuthenticationRequest(this.context);
verify(authenticationRequestContextConverter).convert(this.context);
}
@Test
public void setAuthenticationRequestContextConverterWhenNullThenException() {
// @formatter:off
assertThatIllegalArgumentException()
.isThrownBy(() -> this.factory.setAuthenticationRequestContextConverter(null));
// @formatter:on
}
@Test
public void createPostAuthenticationRequestWhenAssertionConsumerServiceBindingThenUses() {
RelyingPartyRegistration relyingPartyRegistration = this.relyingPartyRegistrationBuilder
.assertionConsumerServiceBinding(Saml2MessageBinding.REDIRECT).build();
Saml2AuthenticationRequestContext context = this.contextBuilder
.relyingPartyRegistration(relyingPartyRegistration).build();
Saml2PostAuthenticationRequest request = this.factory.createPostAuthenticationRequest(context);
String samlRequest = request.getSamlRequest();
String inflated = new String(Saml2Utils.samlDecode(samlRequest));
assertThat(inflated).contains("ProtocolBinding=\"" + SAMLConstants.SAML2_REDIRECT_BINDING_URI + "\"");
}
@Test
public void createRedirectAuthenticationRequestWhenSHA1SignRequestThenSignatureIsPresent() {
RelyingPartyRegistration relyingPartyRegistration = this.relyingPartyRegistrationBuilder
.assertingPartyDetails(
(a) -> a.signingAlgorithms((algs) -> algs.add(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1)))
.build();
Saml2AuthenticationRequestContext context = this.contextBuilder.relayState("Relay State Value")
.relyingPartyRegistration(relyingPartyRegistration).build();
Saml2RedirectAuthenticationRequest result = this.factory.createRedirectAuthenticationRequest(context);
assertThat(result.getSamlRequest()).isNotEmpty();
assertThat(result.getRelayState()).isEqualTo("Relay State Value");
assertThat(result.getSigAlg()).isEqualTo(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1);
assertThat(result.getSignature()).isNotNull();
assertThat(result.getBinding()).isEqualTo(Saml2MessageBinding.REDIRECT);
}
@Test
public void createAuthenticationRequestWhenSetNameIDPolicyThenReturnsCorrectNameIDPolicy() {
RelyingPartyRegistration registration = TestRelyingPartyRegistrations.full().nameIdFormat("format").build();
this.context = this.contextBuilder.relayState("Relay State Value").relyingPartyRegistration(registration)
.build();
AuthnRequest authn = getAuthNRequest(Saml2MessageBinding.POST);
assertThat(authn.getNameIDPolicy()).isNotNull();
assertThat(authn.getNameIDPolicy().getAllowCreate()).isFalse();
assertThat(authn.getNameIDPolicy().getFormat()).isEqualTo("format");
assertThat(authn.getNameIDPolicy().getSPNameQualifier()).isNull();
}
private AuthnRequest authnRequest() {
AuthnRequest authnRequest = TestOpenSamlObjects.authnRequest();
authnRequest.setIssueInstant(Instant.now());
return authnRequest;
}
private AuthnRequest getAuthNRequest(Saml2MessageBinding binding) {
AbstractSaml2AuthenticationRequest result = (binding == Saml2MessageBinding.REDIRECT)
? this.factory.createRedirectAuthenticationRequest(this.context)
: this.factory.createPostAuthenticationRequest(this.context);
String samlRequest = result.getSamlRequest();
assertThat(samlRequest).isNotEmpty();
if (result.getBinding() == Saml2MessageBinding.REDIRECT) {
samlRequest = Saml2Utils.samlInflate(Saml2Utils.samlDecode(samlRequest));
}
else {
samlRequest = new String(Saml2Utils.samlDecode(samlRequest), StandardCharsets.UTF_8);
}
try {
Document document = XMLObjectProviderRegistrySupport.getParserPool()
.parse(new ByteArrayInputStream(samlRequest.getBytes(StandardCharsets.UTF_8)));
Element element = document.getDocumentElement();
return (AuthnRequest) this.unmarshaller.unmarshall(element);
}
catch (Exception ex) {
throw new Saml2Exception(ex);
}
}
}

View File

@ -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.
@ -26,7 +26,7 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.security.converter.RsaKeyConverters;
import org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType;
import org.springframework.security.saml2.core.Saml2X509Credential;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
@ -79,66 +79,66 @@ public class Saml2X509CredentialTests {
@Test
public void constructorWhenRelyingPartyWithCredentialsThenItSucceeds() {
new Saml2X509Credential(this.key, this.certificate, Saml2X509CredentialType.SIGNING);
new Saml2X509Credential(this.key, this.certificate, Saml2X509CredentialType.SIGNING,
Saml2X509CredentialType.DECRYPTION);
new Saml2X509Credential(this.key, this.certificate, Saml2X509CredentialType.DECRYPTION);
new Saml2X509Credential(this.key, this.certificate, Saml2X509Credential.Saml2X509CredentialType.SIGNING);
new Saml2X509Credential(this.key, this.certificate, Saml2X509Credential.Saml2X509CredentialType.SIGNING,
Saml2X509Credential.Saml2X509CredentialType.DECRYPTION);
new Saml2X509Credential(this.key, this.certificate, Saml2X509Credential.Saml2X509CredentialType.DECRYPTION);
}
@Test
public void constructorWhenAssertingPartyWithCredentialsThenItSucceeds() {
new Saml2X509Credential(this.certificate, Saml2X509CredentialType.VERIFICATION);
new Saml2X509Credential(this.certificate, Saml2X509CredentialType.VERIFICATION,
Saml2X509CredentialType.ENCRYPTION);
new Saml2X509Credential(this.certificate, Saml2X509CredentialType.ENCRYPTION);
new Saml2X509Credential(this.certificate, Saml2X509Credential.Saml2X509CredentialType.VERIFICATION);
new Saml2X509Credential(this.certificate, Saml2X509Credential.Saml2X509CredentialType.VERIFICATION,
Saml2X509Credential.Saml2X509CredentialType.ENCRYPTION);
new Saml2X509Credential(this.certificate, Saml2X509Credential.Saml2X509CredentialType.ENCRYPTION);
}
@Test
public void constructorWhenRelyingPartyWithoutCredentialsThenItFails() {
assertThatIllegalArgumentException().isThrownBy(
() -> new Saml2X509Credential(null, (X509Certificate) null, Saml2X509CredentialType.SIGNING));
assertThatIllegalArgumentException().isThrownBy(() -> new Saml2X509Credential(null, (X509Certificate) null,
Saml2X509Credential.Saml2X509CredentialType.SIGNING));
}
@Test
public void constructorWhenRelyingPartyWithoutPrivateKeyThenItFails() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new Saml2X509Credential(null, this.certificate, Saml2X509CredentialType.SIGNING));
assertThatIllegalArgumentException().isThrownBy(() -> new Saml2X509Credential(null, this.certificate,
Saml2X509Credential.Saml2X509CredentialType.SIGNING));
}
@Test
public void constructorWhenRelyingPartyWithoutCertificateThenItFails() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new Saml2X509Credential(this.key, null, Saml2X509CredentialType.SIGNING));
assertThatIllegalArgumentException().isThrownBy(
() -> new Saml2X509Credential(this.key, null, Saml2X509Credential.Saml2X509CredentialType.SIGNING));
}
@Test
public void constructorWhenAssertingPartyWithoutCertificateThenItFails() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new Saml2X509Credential(null, Saml2X509CredentialType.SIGNING));
.isThrownBy(() -> new Saml2X509Credential(null, Saml2X509Credential.Saml2X509CredentialType.SIGNING));
}
@Test
public void constructorWhenRelyingPartyWithEncryptionUsageThenItFails() {
assertThatIllegalStateException().isThrownBy(
() -> new Saml2X509Credential(this.key, this.certificate, Saml2X509CredentialType.ENCRYPTION));
assertThatIllegalStateException().isThrownBy(() -> new Saml2X509Credential(this.key, this.certificate,
Saml2X509Credential.Saml2X509CredentialType.ENCRYPTION));
}
@Test
public void constructorWhenRelyingPartyWithVerificationUsageThenItFails() {
assertThatIllegalStateException().isThrownBy(
() -> new Saml2X509Credential(this.key, this.certificate, Saml2X509CredentialType.VERIFICATION));
assertThatIllegalStateException().isThrownBy(() -> new Saml2X509Credential(this.key, this.certificate,
Saml2X509Credential.Saml2X509CredentialType.VERIFICATION));
}
@Test
public void constructorWhenAssertingPartyWithSigningUsageThenItFails() {
assertThatIllegalStateException()
.isThrownBy(() -> new Saml2X509Credential(this.certificate, Saml2X509CredentialType.SIGNING));
assertThatIllegalStateException().isThrownBy(
() -> new Saml2X509Credential(this.certificate, Saml2X509Credential.Saml2X509CredentialType.SIGNING));
}
@Test
public void constructorWhenAssertingPartyWithDecryptionUsageThenItFails() {
assertThatIllegalStateException()
.isThrownBy(() -> new Saml2X509Credential(this.certificate, Saml2X509CredentialType.DECRYPTION));
assertThatIllegalStateException().isThrownBy(() -> new Saml2X509Credential(this.certificate,
Saml2X509Credential.Saml2X509CredentialType.DECRYPTION));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 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.
@ -27,7 +27,7 @@ import java.security.cert.X509Certificate;
import org.opensaml.security.crypto.KeySupport;
import org.springframework.security.saml2.Saml2Exception;
import org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType;
import org.springframework.security.saml2.core.Saml2X509Credential;
public final class TestSaml2X509Credentials {
@ -35,28 +35,32 @@ public final class TestSaml2X509Credentials {
}
public static Saml2X509Credential assertingPartySigningCredential() {
return new Saml2X509Credential(idpPrivateKey(), idpCertificate(), Saml2X509CredentialType.SIGNING);
return new Saml2X509Credential(idpPrivateKey(), idpCertificate(),
Saml2X509Credential.Saml2X509CredentialType.SIGNING);
}
public static Saml2X509Credential assertingPartyEncryptingCredential() {
return new Saml2X509Credential(spCertificate(), Saml2X509CredentialType.ENCRYPTION);
return new Saml2X509Credential(spCertificate(), Saml2X509Credential.Saml2X509CredentialType.ENCRYPTION);
}
public static Saml2X509Credential assertingPartyPrivateCredential() {
return new Saml2X509Credential(idpPrivateKey(), idpCertificate(), Saml2X509CredentialType.SIGNING,
Saml2X509CredentialType.DECRYPTION);
return new Saml2X509Credential(idpPrivateKey(), idpCertificate(),
Saml2X509Credential.Saml2X509CredentialType.SIGNING,
Saml2X509Credential.Saml2X509CredentialType.DECRYPTION);
}
public static Saml2X509Credential relyingPartyVerifyingCredential() {
return new Saml2X509Credential(idpCertificate(), Saml2X509CredentialType.VERIFICATION);
return new Saml2X509Credential(idpCertificate(), Saml2X509Credential.Saml2X509CredentialType.VERIFICATION);
}
public static Saml2X509Credential relyingPartySigningCredential() {
return new Saml2X509Credential(spPrivateKey(), spCertificate(), Saml2X509CredentialType.SIGNING);
return new Saml2X509Credential(spPrivateKey(), spCertificate(),
Saml2X509Credential.Saml2X509CredentialType.SIGNING);
}
public static Saml2X509Credential relyingPartyDecryptingCredential() {
return new Saml2X509Credential(spPrivateKey(), spCertificate(), Saml2X509CredentialType.DECRYPTION);
return new Saml2X509Credential(spPrivateKey(), spCertificate(),
Saml2X509Credential.Saml2X509CredentialType.DECRYPTION);
}
private static X509Certificate certificate(String cert) {

View File

@ -1,66 +0,0 @@
/*
* Copyright 2002-2020 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.saml2.provider.service.authentication;
import java.util.UUID;
import org.junit.jupiter.api.Test;
import org.springframework.security.saml2.credentials.TestSaml2X509Credentials;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link Saml2AuthenticationRequestFactory} default interface methods
*/
public class Saml2AuthenticationRequestFactoryTests {
private RelyingPartyRegistration registration = RelyingPartyRegistration.withRegistrationId("id")
.assertionConsumerServiceUrlTemplate("template")
.providerDetails((c) -> c.webSsoUrl("https://example.com/destination"))
.providerDetails((c) -> c.entityId("remote-entity-id")).localEntityIdTemplate("local-entity-id")
.credentials((c) -> c.add(TestSaml2X509Credentials.relyingPartySigningCredential())).build();
@Test
public void createAuthenticationRequestParametersWhenRedirectDefaultIsUsedMessageIsDeflatedAndEncoded() {
final String value = "Test String: " + UUID.randomUUID().toString();
Saml2AuthenticationRequestFactory factory = (request) -> value;
Saml2AuthenticationRequestContext request = Saml2AuthenticationRequestContext.builder()
.relyingPartyRegistration(this.registration).issuer("https://example.com/issuer")
.assertionConsumerServiceUrl("https://example.com/acs-url").build();
Saml2RedirectAuthenticationRequest response = factory.createRedirectAuthenticationRequest(request);
String resultValue = response.getSamlRequest();
byte[] decoded = Saml2Utils.samlDecode(resultValue);
String inflated = Saml2Utils.samlInflate(decoded);
assertThat(inflated).isEqualTo(value);
}
@Test
public void createAuthenticationRequestParametersWhenPostDefaultIsUsedMessageIsEncoded() {
final String value = "Test String: " + UUID.randomUUID().toString();
Saml2AuthenticationRequestFactory factory = (request) -> value;
Saml2AuthenticationRequestContext request = Saml2AuthenticationRequestContext.builder()
.relyingPartyRegistration(this.registration).issuer("https://example.com/issuer")
.assertionConsumerServiceUrl("https://example.com/acs-url").build();
Saml2PostAuthenticationRequest response = factory.createPostAuthenticationRequest(request);
String resultValue = response.getSamlRequest();
byte[] decoded = Saml2Utils.samlDecode(resultValue);
assertThat(new String(decoded)).isEqualTo(value);
}
}

View File

@ -18,6 +18,7 @@ package org.springframework.security.saml2.provider.service.authentication;
import org.junit.jupiter.api.Test;
import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations;
import org.springframework.util.SerializationUtils;
import static org.assertj.core.api.Assertions.assertThat;
@ -48,8 +49,7 @@ class Saml2PostAuthenticationRequestTests {
private Saml2PostAuthenticationRequest.Builder getAuthenticationRequestBuilder() {
return Saml2PostAuthenticationRequest
.withAuthenticationRequestContext(
TestSaml2AuthenticationRequestContexts.authenticationRequestContext().build())
.withRelyingPartyRegistration(TestRelyingPartyRegistrations.relyingPartyRegistration().build())
.samlRequest("request").authenticationRequestUri(IDP_SSO_URL);
}

View File

@ -18,6 +18,7 @@ package org.springframework.security.saml2.provider.service.authentication;
import org.junit.jupiter.api.Test;
import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations;
import org.springframework.util.SerializationUtils;
import static org.assertj.core.api.Assertions.assertThat;
@ -48,8 +49,7 @@ class Saml2RedirectAuthenticationRequestTests {
private Saml2RedirectAuthenticationRequest.Builder getAuthenticationRequestBuilder() {
return Saml2RedirectAuthenticationRequest
.withAuthenticationRequestContext(
TestSaml2AuthenticationRequestContexts.authenticationRequestContext().build())
.withRelyingPartyRegistration(TestRelyingPartyRegistrations.relyingPartyRegistration().build())
.samlRequest("request").authenticationRequestUri(IDP_SSO_URL);
}

View File

@ -1,35 +0,0 @@
/*
* Copyright 2002-2020 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.saml2.provider.service.authentication;
import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations;
/**
* Test {@link Saml2AuthenticationRequestContext}s
*/
public final class TestSaml2AuthenticationRequestContexts {
private TestSaml2AuthenticationRequestContexts() {
}
public static Saml2AuthenticationRequestContext.Builder authenticationRequestContext() {
return Saml2AuthenticationRequestContext.builder().relayState("relayState").issuer("issuer")
.relyingPartyRegistration(TestRelyingPartyRegistrations.relyingPartyRegistration().build())
.assertionConsumerServiceUrl("assertionConsumerServiceUrl");
}
}

View File

@ -40,31 +40,24 @@ public class RelyingPartyRegistrationTests {
private void compareRegistrations(RelyingPartyRegistration registration, RelyingPartyRegistration copy) {
assertThat(copy.getRegistrationId()).isEqualTo(registration.getRegistrationId()).isEqualTo("simplesamlphp");
assertThat(copy.getProviderDetails().getEntityId()).isEqualTo(registration.getProviderDetails().getEntityId())
.isEqualTo(copy.getAssertingPartyDetails().getEntityId())
assertThat(copy.getAssertingPartyDetails().getEntityId())
.isEqualTo(registration.getAssertingPartyDetails().getEntityId())
.isEqualTo("https://simplesaml-for-spring-saml.apps.pcfone.io/saml2/idp/metadata.php");
assertThat(copy.getAssertionConsumerServiceUrlTemplate())
.isEqualTo(registration.getAssertionConsumerServiceUrlTemplate())
.isEqualTo(copy.getAssertionConsumerServiceLocation())
assertThat(copy.getAssertionConsumerServiceLocation())
.isEqualTo(registration.getAssertionConsumerServiceLocation())
.isEqualTo("{baseUrl}" + Saml2WebSsoAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI);
assertThat(copy.getCredentials()).containsAll(registration.getCredentials())
.containsExactly(registration.getCredentials().get(0), registration.getCredentials().get(1));
assertThat(copy.getLocalEntityIdTemplate()).isEqualTo(registration.getLocalEntityIdTemplate())
.isEqualTo(copy.getEntityId()).isEqualTo(registration.getEntityId())
assertThat(copy.getSigningX509Credentials()).containsAll(registration.getSigningX509Credentials());
assertThat(copy.getDecryptionX509Credentials()).containsAll(registration.getDecryptionX509Credentials());
assertThat(copy.getEntityId()).isEqualTo(registration.getEntityId()).isEqualTo(copy.getEntityId())
.isEqualTo(registration.getEntityId())
.isEqualTo("{baseUrl}/saml2/service-provider-metadata/{registrationId}");
assertThat(copy.getProviderDetails().getWebSsoUrl()).isEqualTo(registration.getProviderDetails().getWebSsoUrl())
.isEqualTo(copy.getAssertingPartyDetails().getSingleSignOnServiceLocation())
assertThat(copy.getAssertingPartyDetails().getSingleSignOnServiceLocation())
.isEqualTo(registration.getAssertingPartyDetails().getSingleSignOnServiceLocation())
.isEqualTo("https://simplesaml-for-spring-saml.apps.pcfone.io/saml2/idp/SSOService.php");
assertThat(copy.getProviderDetails().getBinding()).isEqualTo(registration.getProviderDetails().getBinding())
.isEqualTo(copy.getAssertingPartyDetails().getSingleSignOnServiceBinding())
assertThat(copy.getAssertingPartyDetails().getSingleSignOnServiceBinding())
.isEqualTo(registration.getAssertingPartyDetails().getSingleSignOnServiceBinding())
.isEqualTo(Saml2MessageBinding.POST);
assertThat(copy.getProviderDetails().isSignAuthNRequest())
.isEqualTo(registration.getProviderDetails().isSignAuthNRequest())
.isEqualTo(copy.getAssertingPartyDetails().getWantAuthnRequestsSigned())
assertThat(copy.getAssertingPartyDetails().getWantAuthnRequestsSigned())
.isEqualTo(registration.getAssertingPartyDetails().getWantAuthnRequestsSigned()).isFalse();
assertThat(copy.getAssertionConsumerServiceBinding())
.isEqualTo(registration.getAssertionConsumerServiceBinding());

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 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.
@ -16,7 +16,7 @@
package org.springframework.security.saml2.provider.service.registration;
import org.springframework.security.saml2.credentials.Saml2X509Credential;
import org.springframework.security.saml2.core.Saml2X509Credential;
import org.springframework.security.saml2.credentials.TestSaml2X509Credentials;
import org.springframework.security.saml2.provider.service.servlet.filter.Saml2WebSsoAuthenticationFilter;
@ -40,9 +40,10 @@ public final class TestRelyingPartyRegistrations {
String singleLogoutServiceLocation = "{baseUrl}/logout/saml2/slo";
return RelyingPartyRegistration.withRegistrationId(registrationId).entityId(rpEntityId)
.assertionConsumerServiceLocation(assertionConsumerServiceLocation)
.singleLogoutServiceLocation(singleLogoutServiceLocation).credentials((c) -> c.add(signingCredential))
.providerDetails((c) -> c.entityId(apEntityId).webSsoUrl(singleSignOnServiceLocation))
.credentials((c) -> c.add(verificationCertificate));
.singleLogoutServiceLocation(singleLogoutServiceLocation)
.signingX509Credentials((c) -> c.add(signingCredential)).assertingPartyDetails(
(a) -> a.entityId(apEntityId).singleSignOnServiceLocation(singleSignOnServiceLocation)
.verificationX509Credentials((c) -> c.add(verificationCertificate)));
}
public static RelyingPartyRegistration.Builder noCredentials() {

View File

@ -31,23 +31,14 @@ import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.security.saml2.credentials.TestSaml2X509Credentials;
import org.springframework.security.saml2.provider.service.authentication.AbstractSaml2AuthenticationRequest;
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.Saml2PostAuthenticationRequest;
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.Saml2MessageBinding;
import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations;
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.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.authentication.Saml2AuthenticationRequestResolver;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.web.util.HtmlUtils;
import org.springframework.web.util.UriUtils;
@ -58,7 +49,6 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
public class Saml2WebSsoAuthenticationRequestFilterTests {
@ -68,10 +58,6 @@ public class Saml2WebSsoAuthenticationRequestFilterTests {
private RelyingPartyRegistrationRepository repository = mock(RelyingPartyRegistrationRepository.class);
private Saml2AuthenticationRequestFactory factory = mock(Saml2AuthenticationRequestFactory.class);
private Saml2AuthenticationRequestContextResolver resolver = mock(Saml2AuthenticationRequestContextResolver.class);
private Saml2AuthenticationRequestResolver authenticationRequestResolver = mock(
Saml2AuthenticationRequestResolver.class);
@ -88,7 +74,7 @@ public class Saml2WebSsoAuthenticationRequestFilterTests {
@BeforeEach
public void setup() {
this.filter = new Saml2WebSsoAuthenticationRequestFilter(this.resolver, this.factory);
this.filter = new Saml2WebSsoAuthenticationRequestFilter(this.authenticationRequestResolver);
this.request = new MockHttpServletRequest();
this.response = new MockHttpServletResponse();
this.request.setPathInfo("/saml2/authenticate/registration-id");
@ -99,30 +85,26 @@ public class Saml2WebSsoAuthenticationRequestFilterTests {
}
};
this.rpBuilder = RelyingPartyRegistration.withRegistrationId("registration-id")
.providerDetails((c) -> c.entityId("idp-entity-id")).providerDetails((c) -> c.webSsoUrl(IDP_SSO_URL))
.assertionConsumerServiceUrlTemplate("template")
.credentials((c) -> c.add(TestSaml2X509Credentials.assertingPartyPrivateCredential()));
.assertingPartyDetails((c) -> c.entityId("idp-entity-id"))
.assertingPartyDetails((c) -> c.singleSignOnServiceLocation(IDP_SSO_URL))
.assertionConsumerServiceLocation("template")
.signingX509Credentials((c) -> c.add(TestSaml2X509Credentials.assertingPartyPrivateCredential()))
.decryptionX509Credentials((c) -> c.add(TestSaml2X509Credentials.assertingPartyPrivateCredential()));
this.filter.setAuthenticationRequestRepository(this.authenticationRequestRepository);
}
@Test
public void doFilterWhenNoRelayStateThenRedirectDoesNotContainParameter() throws ServletException, IOException {
Saml2AuthenticationRequestContext context = authenticationRequestContext().relayState(null).build();
Saml2RedirectAuthenticationRequest request = redirectAuthenticationRequest(context).build();
given(this.resolver.resolve(any())).willReturn(context);
given(this.factory.createRedirectAuthenticationRequest(any())).willReturn(request);
Saml2RedirectAuthenticationRequest request = redirectAuthenticationRequest().build();
given(this.authenticationRequestResolver.resolve(any())).willReturn(request);
this.filter.doFilterInternal(this.request, this.response, this.filterChain);
assertThat(this.response.getHeader("Location")).doesNotContain("RelayState=").startsWith(IDP_SSO_URL);
}
private static Saml2AuthenticationRequestContext.Builder authenticationRequestContext() {
return TestSaml2AuthenticationRequestContexts.authenticationRequestContext();
}
private static Saml2RedirectAuthenticationRequest.Builder redirectAuthenticationRequest(
Saml2AuthenticationRequestContext context) {
return Saml2RedirectAuthenticationRequest.withAuthenticationRequestContext(context).samlRequest("request")
.authenticationRequestUri(IDP_SSO_URL);
private static Saml2RedirectAuthenticationRequest.Builder redirectAuthenticationRequest() {
return Saml2RedirectAuthenticationRequest
.withRelyingPartyRegistration(TestRelyingPartyRegistrations.relyingPartyRegistration().build())
.samlRequest("request").authenticationRequestUri(IDP_SSO_URL);
}
private static Saml2RedirectAuthenticationRequest.Builder redirectAuthenticationRequest(
@ -131,18 +113,16 @@ public class Saml2WebSsoAuthenticationRequestFilterTests {
.authenticationRequestUri(IDP_SSO_URL);
}
private static Saml2PostAuthenticationRequest.Builder postAuthenticationRequest(
Saml2AuthenticationRequestContext context) {
return Saml2PostAuthenticationRequest.withAuthenticationRequestContext(context).samlRequest("request")
.authenticationRequestUri(IDP_SSO_URL);
private static Saml2PostAuthenticationRequest.Builder postAuthenticationRequest() {
return Saml2PostAuthenticationRequest
.withRelyingPartyRegistration(TestRelyingPartyRegistrations.relyingPartyRegistration().build())
.samlRequest("request").authenticationRequestUri(IDP_SSO_URL);
}
@Test
public void doFilterWhenRelayStateThenRedirectDoesContainParameter() throws ServletException, IOException {
Saml2AuthenticationRequestContext context = authenticationRequestContext().build();
Saml2RedirectAuthenticationRequest request = redirectAuthenticationRequest(context).build();
given(this.resolver.resolve(any())).willReturn(context);
given(this.factory.createRedirectAuthenticationRequest(any())).willReturn(request);
Saml2RedirectAuthenticationRequest request = redirectAuthenticationRequest().relayState("relayState").build();
given(this.authenticationRequestResolver.resolve(any())).willReturn(request);
this.filter.doFilterInternal(this.request, this.response, this.filterChain);
assertThat(this.response.getHeader("Location")).contains("RelayState=relayState").startsWith(IDP_SSO_URL);
}
@ -151,10 +131,9 @@ public class Saml2WebSsoAuthenticationRequestFilterTests {
public void doFilterWhenRelayStateThatRequiresEncodingThenRedirectDoesContainsEncodedParameter() throws Exception {
String relayStateValue = "https://my-relay-state.example.com?with=param&other=param";
String relayStateEncoded = UriUtils.encode(relayStateValue, StandardCharsets.ISO_8859_1);
Saml2AuthenticationRequestContext context = authenticationRequestContext().relayState(relayStateValue).build();
Saml2RedirectAuthenticationRequest request = redirectAuthenticationRequest(context).build();
given(this.resolver.resolve(any())).willReturn(context);
given(this.factory.createRedirectAuthenticationRequest(any())).willReturn(request);
Saml2RedirectAuthenticationRequest request = redirectAuthenticationRequest().relayState(relayStateValue)
.build();
given(this.authenticationRequestResolver.resolve(any())).willReturn(request);
this.filter.doFilterInternal(this.request, this.response, this.filterChain);
assertThat(this.response.getHeader("Location")).contains("RelayState=" + relayStateEncoded)
.startsWith(IDP_SSO_URL);
@ -162,11 +141,9 @@ public class Saml2WebSsoAuthenticationRequestFilterTests {
@Test
public void doFilterWhenSimpleSignatureSpecifiedThenSignatureParametersAreInTheRedirectURL() throws Exception {
Saml2AuthenticationRequestContext context = authenticationRequestContext().build();
Saml2RedirectAuthenticationRequest request = redirectAuthenticationRequest(context).sigAlg("sigalg")
Saml2RedirectAuthenticationRequest request = redirectAuthenticationRequest().sigAlg("sigalg")
.signature("signature").build();
given(this.resolver.resolve(any())).willReturn(context);
given(this.factory.createRedirectAuthenticationRequest(any())).willReturn(request);
given(this.authenticationRequestResolver.resolve(any())).willReturn(request);
this.filter.doFilterInternal(this.request, this.response, this.filterChain);
assertThat(this.response.getHeader("Location")).contains("SigAlg=").contains("Signature=")
.startsWith(IDP_SSO_URL);
@ -174,10 +151,8 @@ public class Saml2WebSsoAuthenticationRequestFilterTests {
@Test
public void doFilterWhenSignatureIsDisabledThenSignatureParametersAreNotInTheRedirectURL() throws Exception {
Saml2AuthenticationRequestContext context = authenticationRequestContext().build();
Saml2RedirectAuthenticationRequest request = redirectAuthenticationRequest(context).build();
given(this.resolver.resolve(any())).willReturn(context);
given(this.factory.createRedirectAuthenticationRequest(any())).willReturn(request);
Saml2RedirectAuthenticationRequest request = redirectAuthenticationRequest().build();
given(this.authenticationRequestResolver.resolve(any())).willReturn(request);
this.filter.doFilterInternal(this.request, this.response, this.filterChain);
assertThat(this.response.getHeader("Location")).doesNotContain("SigAlg=").doesNotContain("Signature=")
.startsWith(IDP_SSO_URL);
@ -190,11 +165,9 @@ public class Saml2WebSsoAuthenticationRequestFilterTests {
RelyingPartyRegistration registration = this.rpBuilder
.assertingPartyDetails((asserting) -> asserting.singleSignOnServiceBinding(Saml2MessageBinding.POST))
.build();
Saml2AuthenticationRequestContext context = authenticationRequestContext().relayState(relayStateValue)
.relyingPartyRegistration(registration).build();
Saml2PostAuthenticationRequest request = postAuthenticationRequest(context).build();
given(this.resolver.resolve(any())).willReturn(context);
given(this.factory.createPostAuthenticationRequest(any())).willReturn(request);
Saml2PostAuthenticationRequest request = Saml2PostAuthenticationRequest
.withRelyingPartyRegistration(registration).samlRequest("request").relayState(relayStateValue).build();
given(this.authenticationRequestResolver.resolve(any())).willReturn(request);
this.filter.doFilterInternal(this.request, this.response, this.filterChain);
assertThat(this.response.getHeader("Location")).isNull();
assertThat(this.response.getContentAsString())
@ -203,62 +176,25 @@ public class Saml2WebSsoAuthenticationRequestFilterTests {
.contains("value=\"" + relayStateEncoded + "\"");
}
@Test
public void doFilterWhenSetAuthenticationRequestFactoryThenUses() throws Exception {
Saml2AuthenticationRequestContext context = authenticationRequestContext().build();
Saml2RedirectAuthenticationRequest authenticationRequest = redirectAuthenticationRequest(context).build();
Saml2AuthenticationRequestFactory factory = mock(Saml2AuthenticationRequestFactory.class);
given(this.resolver.resolve(any())).willReturn(context);
given(factory.createRedirectAuthenticationRequest(any())).willReturn(authenticationRequest);
this.filter.setAuthenticationRequestFactory(factory);
this.filter.doFilterInternal(this.request, this.response, this.filterChain);
verify(factory).createRedirectAuthenticationRequest(any());
}
@Test
public void setRequestMatcherWhenNullThenException() {
Saml2WebSsoAuthenticationRequestFilter filter = new Saml2WebSsoAuthenticationRequestFilter(this.resolver,
this.factory);
assertThatIllegalArgumentException().isThrownBy(() -> filter.setRedirectMatcher(null));
}
@Test
public void setAuthenticationRequestFactoryWhenNullThenException() {
Saml2WebSsoAuthenticationRequestFilter filter = new Saml2WebSsoAuthenticationRequestFilter(this.resolver,
this.factory);
assertThatIllegalArgumentException().isThrownBy(() -> filter.setAuthenticationRequestFactory(null));
}
@Test
public void doFilterWhenRequestMatcherFailsThenSkipsFilter() throws Exception {
Saml2WebSsoAuthenticationRequestFilter filter = new Saml2WebSsoAuthenticationRequestFilter(this.resolver,
this.factory);
filter.setRedirectMatcher((request) -> false);
filter.doFilter(this.request, this.response, this.filterChain);
verifyNoInteractions(this.resolver, this.factory);
}
@Test
public void doFilterWhenRelyingPartyRegistrationNotFoundThenUnauthorized() throws Exception {
Saml2WebSsoAuthenticationRequestFilter filter = new Saml2WebSsoAuthenticationRequestFilter(this.resolver,
this.factory);
Saml2WebSsoAuthenticationRequestFilter filter = new Saml2WebSsoAuthenticationRequestFilter(
this.authenticationRequestResolver);
filter.doFilter(this.request, this.response, this.filterChain);
assertThat(this.response.getStatus()).isEqualTo(401);
}
@Test
public void setAuthenticationRequestRepositoryWhenNullThenException() {
Saml2WebSsoAuthenticationRequestFilter filter = new Saml2WebSsoAuthenticationRequestFilter(this.resolver,
this.factory);
Saml2WebSsoAuthenticationRequestFilter filter = new Saml2WebSsoAuthenticationRequestFilter(
this.authenticationRequestResolver);
assertThatIllegalArgumentException().isThrownBy(() -> filter.setAuthenticationRequestRepository(null));
}
@Test
public void doFilterWhenRedirectThenSaveRedirectRequest() throws ServletException, IOException {
Saml2AuthenticationRequestContext context = authenticationRequestContext().build();
Saml2RedirectAuthenticationRequest request = redirectAuthenticationRequest(context).build();
given(this.resolver.resolve(any())).willReturn(context);
given(this.factory.createRedirectAuthenticationRequest(any())).willReturn(request);
Saml2RedirectAuthenticationRequest request = redirectAuthenticationRequest().build();
given(this.authenticationRequestResolver.resolve(any())).willReturn(request);
this.filter.doFilterInternal(this.request, this.response, this.filterChain);
verify(this.authenticationRequestRepository).saveAuthenticationRequest(
any(Saml2RedirectAuthenticationRequest.class), eq(this.request), eq(this.response));
@ -269,41 +205,14 @@ public class Saml2WebSsoAuthenticationRequestFilterTests {
RelyingPartyRegistration registration = this.rpBuilder
.assertingPartyDetails((asserting) -> asserting.singleSignOnServiceBinding(Saml2MessageBinding.POST))
.build();
Saml2AuthenticationRequestContext context = authenticationRequestContext()
.relyingPartyRegistration(registration).build();
Saml2PostAuthenticationRequest request = postAuthenticationRequest(context).build();
given(this.resolver.resolve(any())).willReturn(context);
given(this.factory.createPostAuthenticationRequest(any())).willReturn(request);
Saml2PostAuthenticationRequest request = Saml2PostAuthenticationRequest
.withRelyingPartyRegistration(registration).samlRequest("request").build();
given(this.authenticationRequestResolver.resolve(any())).willReturn(request);
this.filter.doFilterInternal(this.request, this.response, this.filterChain);
verify(this.authenticationRequestRepository).saveAuthenticationRequest(
any(Saml2PostAuthenticationRequest.class), eq(this.request), eq(this.response));
}
@Test
public void doFilterWhenPathStartsWithRegistrationIdThenPosts() throws Exception {
RelyingPartyRegistration registration = TestRelyingPartyRegistrations.full()
.assertingPartyDetails((party) -> party.singleSignOnServiceBinding(Saml2MessageBinding.POST)).build();
RequestMatcher matcher = new AntPathRequestMatcher("/{registrationId}/saml2/authenticate");
DefaultRelyingPartyRegistrationResolver delegate = new DefaultRelyingPartyRegistrationResolver(this.repository);
RelyingPartyRegistrationResolver resolver = (request, id) -> {
String registrationId = matcher.matcher(request).getVariables().get("registrationId");
return delegate.resolve(request, registrationId);
};
Saml2AuthenticationRequestContextResolver authenticationRequestContextResolver = new DefaultSaml2AuthenticationRequestContextResolver(
resolver);
Saml2PostAuthenticationRequest authenticationRequest = mock(Saml2PostAuthenticationRequest.class);
given(authenticationRequest.getAuthenticationRequestUri()).willReturn("uri");
given(authenticationRequest.getRelayState()).willReturn("relay");
given(authenticationRequest.getSamlRequest()).willReturn("saml");
given(this.repository.findByRegistrationId("registration-id")).willReturn(registration);
given(this.factory.createPostAuthenticationRequest(any())).willReturn(authenticationRequest);
this.filter = new Saml2WebSsoAuthenticationRequestFilter(authenticationRequestContextResolver, this.factory);
this.filter.setRedirectMatcher(matcher);
this.request.setPathInfo("/registration-id/saml2/authenticate");
this.filter.doFilter(this.request, this.response, new MockFilterChain());
verify(this.repository).findByRegistrationId("registration-id");
}
@Test
public void doFilterWhenCustomAuthenticationRequestResolverThenUses() throws Exception {
RelyingPartyRegistration registration = TestRelyingPartyRegistrations.relyingPartyRegistration().build();

View File

@ -1,104 +0,0 @@
/*
* Copyright 2002-2020 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.saml2.provider.service.web;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.security.saml2.core.Saml2ParameterNames;
import org.springframework.security.saml2.credentials.TestSaml2X509Credentials;
import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationRequestContext;
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
/**
* Tests for {@link DefaultSaml2AuthenticationRequestContextResolver}
*
* @author Shazin Sadakath
* @author Josh Cummings
*/
public class DefaultSaml2AuthenticationRequestContextResolverTests {
private static final String ASSERTING_PARTY_SSO_URL = "https://idp.example.com/sso";
private static final String RELYING_PARTY_SSO_URL = "https://sp.example.com/sso";
private static final String ASSERTING_PARTY_ENTITY_ID = "asserting-party-entity-id";
private static final String RELYING_PARTY_ENTITY_ID = "relying-party-entity-id";
private static final String REGISTRATION_ID = "registration-id";
private MockHttpServletRequest request;
private RelyingPartyRegistration.Builder relyingPartyBuilder;
private RelyingPartyRegistrationResolver relyingPartyRegistrationResolver = new DefaultRelyingPartyRegistrationResolver(
(id) -> this.relyingPartyBuilder.build());
private Saml2AuthenticationRequestContextResolver authenticationRequestContextResolver = new DefaultSaml2AuthenticationRequestContextResolver(
this.relyingPartyRegistrationResolver);
@BeforeEach
public void setup() {
this.request = new MockHttpServletRequest();
this.request.setPathInfo("/saml2/authenticate/registration-id");
this.relyingPartyBuilder = RelyingPartyRegistration.withRegistrationId(REGISTRATION_ID)
.localEntityIdTemplate(RELYING_PARTY_ENTITY_ID)
.providerDetails((c) -> c.entityId(ASSERTING_PARTY_ENTITY_ID))
.providerDetails((c) -> c.webSsoUrl(ASSERTING_PARTY_SSO_URL))
.assertionConsumerServiceUrlTemplate(RELYING_PARTY_SSO_URL)
.credentials((c) -> c.add(TestSaml2X509Credentials.relyingPartyVerifyingCredential()));
}
@Test
public void resolveWhenRequestAndRelyingPartyNotNullThenCreateSaml2AuthenticationRequestContext() {
this.request.addParameter(Saml2ParameterNames.RELAY_STATE, "relay-state");
Saml2AuthenticationRequestContext context = this.authenticationRequestContextResolver.resolve(this.request);
assertThat(context).isNotNull();
assertThat(context.getAssertionConsumerServiceUrl()).isEqualTo(RELYING_PARTY_SSO_URL);
assertThat(context.getRelayState()).isEqualTo("relay-state");
assertThat(context.getDestination()).isEqualTo(ASSERTING_PARTY_SSO_URL);
assertThat(context.getIssuer()).isEqualTo(RELYING_PARTY_ENTITY_ID);
assertThat(context.getRelyingPartyRegistration().getRegistrationId())
.isSameAs(this.relyingPartyBuilder.build().getRegistrationId());
}
@Test
public void resolveWhenAssertionConsumerServiceUrlTemplateContainsRegistrationIdThenResolves() {
this.relyingPartyBuilder.assertionConsumerServiceLocation("/saml2/authenticate/{registrationId}");
Saml2AuthenticationRequestContext context = this.authenticationRequestContextResolver.resolve(this.request);
assertThat(context.getAssertionConsumerServiceUrl()).isEqualTo("/saml2/authenticate/registration-id");
}
@Test
public void resolveWhenAssertionConsumerServiceUrlTemplateContainsBaseUrlThenResolves() {
this.relyingPartyBuilder.assertionConsumerServiceLocation("{baseUrl}/saml2/authenticate/{registrationId}");
Saml2AuthenticationRequestContext context = this.authenticationRequestContextResolver.resolve(this.request);
assertThat(context.getAssertionConsumerServiceUrl())
.isEqualTo("http://localhost/saml2/authenticate/registration-id");
}
@Test
public void resolveWhenRelyingPartyNullThenException() {
assertThatIllegalArgumentException().isThrownBy(() -> this.authenticationRequestContextResolver.resolve(null));
}
}

View File

@ -25,7 +25,6 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.io.ClassPathResource;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.security.saml2.core.Saml2ErrorCodes;
@ -50,7 +49,7 @@ import static org.mockito.Mockito.mock;
public class Saml2AuthenticationTokenConverterTests {
@Mock
Converter<HttpServletRequest, RelyingPartyRegistration> relyingPartyRegistrationResolver;
RelyingPartyRegistrationResolver relyingPartyRegistrationResolver;
RelyingPartyRegistration relyingPartyRegistration = TestRelyingPartyRegistrations.relyingPartyRegistration()
.build();
@ -59,7 +58,7 @@ public class Saml2AuthenticationTokenConverterTests {
public void convertWhenSamlResponseThenToken() {
Saml2AuthenticationTokenConverter converter = new Saml2AuthenticationTokenConverter(
this.relyingPartyRegistrationResolver);
given(this.relyingPartyRegistrationResolver.convert(any(HttpServletRequest.class)))
given(this.relyingPartyRegistrationResolver.resolve(any(HttpServletRequest.class), any()))
.willReturn(this.relyingPartyRegistration);
MockHttpServletRequest request = new MockHttpServletRequest();
request.setParameter(Saml2ParameterNames.SAML_RESPONSE,
@ -74,7 +73,7 @@ public class Saml2AuthenticationTokenConverterTests {
public void convertWhenSamlResponseInvalidBase64ThenSaml2AuthenticationException() {
Saml2AuthenticationTokenConverter converter = new Saml2AuthenticationTokenConverter(
this.relyingPartyRegistrationResolver);
given(this.relyingPartyRegistrationResolver.convert(any(HttpServletRequest.class)))
given(this.relyingPartyRegistrationResolver.resolve(any(HttpServletRequest.class), any()))
.willReturn(this.relyingPartyRegistration);
MockHttpServletRequest request = new MockHttpServletRequest();
request.setParameter(Saml2ParameterNames.SAML_RESPONSE, "invalid");
@ -90,7 +89,7 @@ public class Saml2AuthenticationTokenConverterTests {
public void convertWhenNoSamlResponseThenNull() {
Saml2AuthenticationTokenConverter converter = new Saml2AuthenticationTokenConverter(
this.relyingPartyRegistrationResolver);
given(this.relyingPartyRegistrationResolver.convert(any(HttpServletRequest.class)))
given(this.relyingPartyRegistrationResolver.resolve(any(HttpServletRequest.class), any()))
.willReturn(this.relyingPartyRegistration);
MockHttpServletRequest request = new MockHttpServletRequest();
assertThat(converter.convert(request)).isNull();
@ -100,7 +99,7 @@ public class Saml2AuthenticationTokenConverterTests {
public void convertWhenNoRelyingPartyRegistrationThenNull() {
Saml2AuthenticationTokenConverter converter = new Saml2AuthenticationTokenConverter(
this.relyingPartyRegistrationResolver);
given(this.relyingPartyRegistrationResolver.convert(any(HttpServletRequest.class))).willReturn(null);
given(this.relyingPartyRegistrationResolver.resolve(any(HttpServletRequest.class), any())).willReturn(null);
MockHttpServletRequest request = new MockHttpServletRequest();
assertThat(converter.convert(request)).isNull();
}
@ -109,7 +108,7 @@ public class Saml2AuthenticationTokenConverterTests {
public void convertWhenGetRequestThenInflates() {
Saml2AuthenticationTokenConverter converter = new Saml2AuthenticationTokenConverter(
this.relyingPartyRegistrationResolver);
given(this.relyingPartyRegistrationResolver.convert(any(HttpServletRequest.class)))
given(this.relyingPartyRegistrationResolver.resolve(any(HttpServletRequest.class), any()))
.willReturn(this.relyingPartyRegistration);
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("GET");
@ -126,7 +125,7 @@ public class Saml2AuthenticationTokenConverterTests {
public void convertWhenGetRequestInvalidDeflatedThenSaml2AuthenticationException() {
Saml2AuthenticationTokenConverter converter = new Saml2AuthenticationTokenConverter(
this.relyingPartyRegistrationResolver);
given(this.relyingPartyRegistrationResolver.convert(any(HttpServletRequest.class)))
given(this.relyingPartyRegistrationResolver.resolve(any(HttpServletRequest.class), any()))
.willReturn(this.relyingPartyRegistration);
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("GET");
@ -145,7 +144,7 @@ public class Saml2AuthenticationTokenConverterTests {
public void convertWhenUsingSamlUtilsBase64ThenXmlIsValid() throws Exception {
Saml2AuthenticationTokenConverter converter = new Saml2AuthenticationTokenConverter(
this.relyingPartyRegistrationResolver);
given(this.relyingPartyRegistrationResolver.convert(any(HttpServletRequest.class)))
given(this.relyingPartyRegistrationResolver.resolve(any(HttpServletRequest.class), any()))
.willReturn(this.relyingPartyRegistration);
MockHttpServletRequest request = new MockHttpServletRequest();
request.setParameter(Saml2ParameterNames.SAML_RESPONSE, getSsoCircleEncodedXml());
@ -161,7 +160,7 @@ public class Saml2AuthenticationTokenConverterTests {
Saml2AuthenticationTokenConverter converter = new Saml2AuthenticationTokenConverter(
this.relyingPartyRegistrationResolver);
converter.setAuthenticationRequestRepository(authenticationRequestRepository);
given(this.relyingPartyRegistrationResolver.convert(any(HttpServletRequest.class)))
given(this.relyingPartyRegistrationResolver.resolve(any(HttpServletRequest.class), any()))
.willReturn(this.relyingPartyRegistration);
given(authenticationRequestRepository.loadAuthenticationRequest(any(HttpServletRequest.class)))
.willReturn(authenticationRequest);
@ -177,8 +176,7 @@ public class Saml2AuthenticationTokenConverterTests {
@Test
public void constructorWhenResolverIsNullThenIllegalArgument() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new Saml2AuthenticationTokenConverter((RelyingPartyRegistrationResolver) null));
assertThatIllegalArgumentException().isThrownBy(() -> new Saml2AuthenticationTokenConverter(null));
}
@Test

View File

@ -105,7 +105,7 @@ public class Saml2MetadataFilterTests {
.build();
String generatedMetadata = "<xml>test</xml>";
given(this.resolver.resolve(validRegistration)).willReturn(generatedMetadata);
this.filter = new Saml2MetadataFilter((request) -> validRegistration, this.resolver);
this.filter = new Saml2MetadataFilter((request, registrationId) -> validRegistration, this.resolver);
this.filter.doFilter(this.request, this.response, this.chain);
verifyNoInteractions(this.chain);
assertThat(this.response.getStatus()).isEqualTo(200);
@ -131,7 +131,7 @@ public class Saml2MetadataFilterTests {
String generatedMetadata = "<xml>test</xml>";
this.request.setPathInfo("/saml2/service-provider-metadata/registration-id");
given(this.resolver.resolve(validRegistration)).willReturn(generatedMetadata);
this.filter = new Saml2MetadataFilter((request) -> validRegistration, this.resolver);
this.filter = new Saml2MetadataFilter((request, registrationId) -> validRegistration, this.resolver);
this.filter.setMetadataFilename(testMetadataFilename);
this.filter.doFilter(this.request, this.response, this.chain);
assertThat(this.response.getHeaderValue(HttpHeaders.CONTENT_DISPOSITION)).asString()