From a4dbf458aba2e5b46605f128e0d12fcdebb28225 Mon Sep 17 00:00:00 2001 From: Josh Cummings Date: Thu, 18 Apr 2024 12:52:26 -0600 Subject: [PATCH] Add relying-party-registrations#id Closes gh-14487 --- ...artyRegistrationsBeanDefinitionParser.java | 9 ++- .../security/config/spring-security-6.3.rnc | 5 +- .../security/config/spring-security-6.3.xsd | 9 +++ ...egistrationsBeanDefinitionParserTests.java | 20 +++++++ ...efinitionParserTests-MultiRegistration.xml | 10 ++-- ...finitionParserTests-RelayStateResolver.xml | 58 +++++++++++++++++++ ...finitionParserTests-SingleRegistration.xml | 6 +- .../servlet/appendix/namespace/http.adoc | 6 ++ 8 files changed, 112 insertions(+), 11 deletions(-) create mode 100644 config/src/test/resources/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParserTests-RelayStateResolver.xml diff --git a/config/src/main/java/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParser.java index 5a06e2d314..60fe23c43e 100644 --- a/config/src/main/java/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParser.java @@ -64,6 +64,8 @@ public final class RelyingPartyRegistrationsBeanDefinitionParser implements Bean private static final String ELT_ENCRYPTION_CREDENTIAL = "encryption-credential"; + private static final String ATT_ID = "id"; + private static final String ATT_REGISTRATION_ID = "registration-id"; private static final String ATT_ASSERTING_PARTY_ID = "asserting-party-id"; @@ -108,8 +110,11 @@ public final class RelyingPartyRegistrationsBeanDefinitionParser implements Bean .rootBeanDefinition(InMemoryRelyingPartyRegistrationRepository.class) .addConstructorArgValue(relyingPartyRegistrations) .getBeanDefinition(); - String relyingPartyRegistrationRepositoryId = parserContext.getReaderContext() - .generateBeanName(relyingPartyRegistrationRepositoryBean); + String relyingPartyRegistrationRepositoryId = element.getAttribute(ATT_ID); + if (!StringUtils.hasText(relyingPartyRegistrationRepositoryId)) { + relyingPartyRegistrationRepositoryId = parserContext.getReaderContext() + .generateBeanName(relyingPartyRegistrationRepositoryBean); + } parserContext.registerBeanComponent(new BeanComponentDefinition(relyingPartyRegistrationRepositoryBean, relyingPartyRegistrationRepositoryId)); parserContext.popAndRegisterContainingComponent(); diff --git a/config/src/main/resources/org/springframework/security/config/spring-security-6.3.rnc b/config/src/main/resources/org/springframework/security/config/spring-security-6.3.rnc index 7f89ced5af..ab0c881b84 100644 --- a/config/src/main/resources/org/springframework/security/config/spring-security-6.3.rnc +++ b/config/src/main/resources/org/springframework/security/config/spring-security-6.3.rnc @@ -744,7 +744,10 @@ saml2-logout.attlist &= relying-party-registrations = ## Container element for relying party(ies) registered with a SAML 2.0 identity provider - element relying-party-registrations {relying-party-registration+, asserting-party*} + element relying-party-registrations {relying-party-registrations.attlist, relying-party-registration+, asserting-party*} +relying-party-registrations.attlist &= + ## The identifier by which to refer to the repository in other beans + attribute id {xsd:token}? relying-party-registration = ## Represents a relying party registered with a SAML 2.0 identity provider diff --git a/config/src/main/resources/org/springframework/security/config/spring-security-6.3.xsd b/config/src/main/resources/org/springframework/security/config/spring-security-6.3.xsd index f123ad830a..5d814f1713 100644 --- a/config/src/main/resources/org/springframework/security/config/spring-security-6.3.xsd +++ b/config/src/main/resources/org/springframework/security/config/spring-security-6.3.xsd @@ -2188,8 +2188,17 @@ + + + + + The identifier by which to refer to the repository in other beans + + + + Represents a relying party registered with a SAML 2.0 identity provider diff --git a/config/src/test/java/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParserTests.java b/config/src/test/java/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParserTests.java index 0d89c36370..5a332582d3 100644 --- a/config/src/test/java/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParserTests.java +++ b/config/src/test/java/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParserTests.java @@ -16,6 +16,7 @@ package org.springframework.security.config.saml2; +import jakarta.servlet.http.HttpServletRequest; import okhttp3.mockwebserver.MockResponse; import okhttp3.mockwebserver.MockWebServer; import org.junit.jupiter.api.AfterEach; @@ -23,16 +24,21 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.core.convert.converter.Converter; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; +import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.security.config.test.SpringTestContext; import org.springframework.security.config.test.SpringTestContextExtension; 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; import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding; +import org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.verify; /** * Tests for {@link RelyingPartyRegistrationsBeanDefinitionParser}. @@ -118,6 +124,7 @@ public class RelyingPartyRegistrationsBeanDefinitionParserTests { // @formatter:on @Autowired + @Qualifier("registrations") private RelyingPartyRegistrationRepository relyingPartyRegistrationRepository; public final SpringTestContext spring = new SpringTestContext(this); @@ -268,6 +275,19 @@ public class RelyingPartyRegistrationsBeanDefinitionParserTests { "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384"); } + @Test + public void parseWhenRelayStateResolverThenUses() { + this.spring.configLocations(xml("RelayStateResolver")).autowire(); + Converter relayStateResolver = this.spring.getContext().getBean(Converter.class); + OpenSaml4AuthenticationRequestResolver authenticationRequestResolver = this.spring.getContext() + .getBean(OpenSaml4AuthenticationRequestResolver.class); + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setRequestURI("/saml2/authenticate/one"); + request.setServletPath("/saml2/authenticate/one"); + authenticationRequestResolver.resolve(request); + verify(relayStateResolver).convert(request); + } + private static MockResponse xmlResponse(String xml) { return new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE).setBody(xml); } diff --git a/config/src/test/resources/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParserTests-MultiRegistration.xml b/config/src/test/resources/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParserTests-MultiRegistration.xml index dd274db7eb..2c3d00f46e 100644 --- a/config/src/test/resources/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParserTests-MultiRegistration.xml +++ b/config/src/test/resources/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParserTests-MultiRegistration.xml @@ -23,20 +23,20 @@ https://www.springframework.org/schema/security/spring-security.xsd http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> - - + + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/config/src/test/resources/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParserTests-SingleRegistration.xml b/config/src/test/resources/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParserTests-SingleRegistration.xml index 2b97e6f1c1..e68426bfd8 100644 --- a/config/src/test/resources/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParserTests-SingleRegistration.xml +++ b/config/src/test/resources/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParserTests-SingleRegistration.xml @@ -23,14 +23,14 @@ https://www.springframework.org/schema/security/spring-security.xsd http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> - - + + - + The container element for relying party(ies) registered (xref:servlet/saml2/login/overview.adoc#servlet-saml2login-relyingpartyregistration[ClientRegistration]) with a SAML 2.0 Identity Provider. +[[nsa-relying-party-registrations-attributes]] +=== Attributes + +[[nsa-relying-party-registrations-id]] +* **id** +The ID that uniquely identifies the `RelyingPartyRegistrationRepository`. [[nsa-relying-party-registrations-children]] === Child Elements of