parent
195d767d98
commit
995b2918bb
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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()
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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{");
|
||||
|
|
|
@ -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) -> 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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() : "");
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 <EntityDescriptor
|
||||
* EntityID="..."/>
|
||||
* @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 <SingleSignOnService
|
||||
* Location="..."/> in the asserting party's <IDPSSODescriptor>.
|
||||
* @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 <SingleSignOnService Binding="..."/>
|
||||
* in the asserting party's <IDPSSODescriptor>.
|
||||
* @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 <EntityDescriptor
|
||||
* EntityID="..."/>
|
||||
* @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) -> 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
* <saml2:AuthnRequest>
|
||||
* @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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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(
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue