Add relying-party-registrations#id

Closes gh-14487
This commit is contained in:
Josh Cummings 2024-04-18 12:52:26 -06:00
parent 671a240fea
commit a4dbf458ab
No known key found for this signature in database
GPG Key ID: A306A51F43B8E5A5
8 changed files with 112 additions and 11 deletions

View File

@ -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();

View File

@ -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

View File

@ -2188,8 +2188,17 @@
<xs:element maxOccurs="unbounded" ref="security:relying-party-registration"/>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="security:asserting-party"/>
</xs:sequence>
<xs:attributeGroup ref="security:relying-party-registrations.attlist"/>
</xs:complexType>
</xs:element>
<xs:attributeGroup name="relying-party-registrations.attlist">
<xs:attribute name="id" type="xs:token">
<xs:annotation>
<xs:documentation>The identifier by which to refer to the repository in other beans
</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:attributeGroup>
<xs:element name="relying-party-registration">
<xs:annotation>
<xs:documentation>Represents a relying party registered with a SAML 2.0 identity provider

View File

@ -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<HttpServletRequest, String> 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);
}

View File

@ -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">
<relying-party-registrations>
<relying-party-registrations id="registrations">
<relying-party-registration registration-id="one"
entity-id="{baseUrl}/saml2/service-provider-metadata/{registrationId}"
assertion-consumer-service-location="{baseUrl}/login/saml2/sso/{registrationId}"
assertion-consumer-service-binding="REDIRECT"
asserting-party-id="google"/>
<relying-party-registration registration-id="two"
entity-id="{baseUrl}/saml2/service-provider-metadata/{registrationId}"
assertion-consumer-service-location="{baseUrl}/login/saml2/sso/{registrationId}"
assertion-consumer-service-binding="POST"
asserting-party-id="simple-saml"/>
<asserting-party asserting-party-id="google" entity-id="https://accounts.google.com/o/saml2/idp/entity-id"
want-authn-requests-signed="true"
single-sign-on-service-location="https://accounts.google.com/o/saml2/idp/sso-url"
@ -48,7 +48,7 @@
certificate-location="classpath:org/springframework/security/config/saml2/idp-certificate.crt"
private-key-location="classpath:org/springframework/security/config/saml2/rp-private.key"/>
</asserting-party>
<asserting-party asserting-party-id="simple-saml"
entity-id="https://simplesaml-for-spring-saml.apps.pcfone.io/saml2/idp/metadata.php"
single-sign-on-service-location="https://simplesaml-for-spring-saml.apps.pcfone.io/saml2/idp/SSOService.php"

View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/security"
xsi:schemaLocation="
http://www.springframework.org/schema/security
https://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<relying-party-registrations id="registrations">
<relying-party-registration registration-id="one"
entity-id="{baseUrl}/saml2/service-provider-metadata/{registrationId}"
assertion-consumer-service-location="{baseUrl}/login/saml2/sso/{registrationId}"
assertion-consumer-service-binding="REDIRECT"
asserting-party-id="google">
<signing-credential
certificate-location="classpath:org/springframework/security/config/saml2/rp-certificate.crt"
private-key-location="classpath:org/springframework/security/config/saml2/rp-private.key"/>
</relying-party-registration>
<asserting-party asserting-party-id="google" entity-id="https://accounts.google.com/o/saml2/idp/entity-id"
want-authn-requests-signed="true"
single-sign-on-service-location="https://accounts.google.com/o/saml2/idp/sso-url"
single-sign-on-service-binding="POST">
<verification-credential
certificate-location="classpath:org/springframework/security/config/saml2/idp-certificate.crt"
private-key-location="classpath:org/springframework/security/config/saml2/rp-private.key"/>
<encryption-credential
certificate-location="classpath:org/springframework/security/config/saml2/idp-certificate.crt"
private-key-location="classpath:org/springframework/security/config/saml2/rp-private.key"/>
</asserting-party>
</relying-party-registrations>
<b:bean class="org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver">
<b:constructor-arg ref="registrations"/>
<b:property name="relayStateResolver" ref="relayStateResolver"/>
</b:bean>
<b:bean name="relayStateResolver" class="org.mockito.Mockito" factory-method="mock">
<b:constructor-arg value="org.springframework.core.convert.converter.Converter" type="java.lang.Class"/>
</b:bean>
</b:beans>

View File

@ -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">
<relying-party-registrations>
<relying-party-registrations id="registrations">
<relying-party-registration registration-id="one"
entity-id="{baseUrl}/saml2/service-provider-metadata/{registrationId}"
assertion-consumer-service-location="{baseUrl}/login/saml2/sso/{registrationId}"
assertion-consumer-service-binding="REDIRECT"
asserting-party-id="google"/>
<asserting-party asserting-party-id="google" entity-id="https://accounts.google.com/o/saml2/idp/entity-id"
want-authn-requests-signed="true"
single-sign-on-service-location="https://accounts.google.com/o/saml2/idp/sso-url"

View File

@ -1331,6 +1331,12 @@ Reference to an `OpaqueTokenAuthenticationConverter`. Responsible for converting
== <relying-party-registrations>
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]]
=== <relying-party-registrations> Attributes
[[nsa-relying-party-registrations-id]]
* **id**
The ID that uniquely identifies the `RelyingPartyRegistrationRepository`.
[[nsa-relying-party-registrations-children]]
=== Child Elements of <relying-party-registrations>