Skip to content

Commit 97ba596

Browse files
Merge branch '5.7.x' into 5.8.x
Closes gh-12776
2 parents 79887fa + 1c3ce1e commit 97ba596

File tree

2 files changed

+94
-19
lines changed

2 files changed

+94
-19
lines changed

config/src/main/java/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParser.java

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2022 the original author or authors.
2+
* Copyright 2002-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -208,30 +208,49 @@ private static RelyingPartyRegistration.Builder getBuilderFromMetadataLocationIf
208208
ParserContext parserContext) {
209209
String registrationId = relyingPartyRegistrationElt.getAttribute(ATT_REGISTRATION_ID);
210210
String metadataLocation = relyingPartyRegistrationElt.getAttribute(ATT_METADATA_LOCATION);
211+
RelyingPartyRegistration.Builder builder;
212+
if (StringUtils.hasText(metadataLocation)) {
213+
builder = RelyingPartyRegistrations.fromMetadataLocation(metadataLocation).registrationId(registrationId);
214+
}
215+
else {
216+
builder = RelyingPartyRegistration.withRegistrationId(registrationId)
217+
.assertingPartyDetails((apBuilder) -> buildAssertingParty(relyingPartyRegistrationElt,
218+
assertingParties, apBuilder, parserContext));
219+
}
220+
addRemainingProperties(relyingPartyRegistrationElt, builder);
221+
return builder;
222+
}
223+
224+
private static void addRemainingProperties(Element relyingPartyRegistrationElt,
225+
RelyingPartyRegistration.Builder builder) {
226+
String entityId = relyingPartyRegistrationElt.getAttribute(ATT_ENTITY_ID);
211227
String singleLogoutServiceLocation = relyingPartyRegistrationElt
212228
.getAttribute(ATT_SINGLE_LOGOUT_SERVICE_LOCATION);
213229
String singleLogoutServiceResponseLocation = relyingPartyRegistrationElt
214230
.getAttribute(ATT_SINGLE_LOGOUT_SERVICE_RESPONSE_LOCATION);
215231
Saml2MessageBinding singleLogoutServiceBinding = getSingleLogoutServiceBinding(relyingPartyRegistrationElt);
216-
if (StringUtils.hasText(metadataLocation)) {
217-
return RelyingPartyRegistrations.fromMetadataLocation(metadataLocation).registrationId(registrationId)
218-
.singleLogoutServiceLocation(singleLogoutServiceLocation)
219-
.singleLogoutServiceResponseLocation(singleLogoutServiceResponseLocation)
220-
.singleLogoutServiceBinding(singleLogoutServiceBinding);
221-
}
222-
String entityId = relyingPartyRegistrationElt.getAttribute(ATT_ENTITY_ID);
223232
String assertionConsumerServiceLocation = relyingPartyRegistrationElt
224233
.getAttribute(ATT_ASSERTION_CONSUMER_SERVICE_LOCATION);
225234
Saml2MessageBinding assertionConsumerServiceBinding = getAssertionConsumerServiceBinding(
226235
relyingPartyRegistrationElt);
227-
return RelyingPartyRegistration.withRegistrationId(registrationId).entityId(entityId)
228-
.assertionConsumerServiceLocation(assertionConsumerServiceLocation)
229-
.assertionConsumerServiceBinding(assertionConsumerServiceBinding)
230-
.singleLogoutServiceLocation(singleLogoutServiceLocation)
231-
.singleLogoutServiceResponseLocation(singleLogoutServiceResponseLocation)
232-
.singleLogoutServiceBinding(singleLogoutServiceBinding)
233-
.assertingPartyDetails((builder) -> buildAssertingParty(relyingPartyRegistrationElt, assertingParties,
234-
builder, parserContext));
236+
if (StringUtils.hasText(entityId)) {
237+
builder.entityId(entityId);
238+
}
239+
if (StringUtils.hasText(singleLogoutServiceLocation)) {
240+
builder.singleLogoutServiceLocation(singleLogoutServiceLocation);
241+
}
242+
if (StringUtils.hasText(singleLogoutServiceResponseLocation)) {
243+
builder.singleLogoutServiceResponseLocation(singleLogoutServiceResponseLocation);
244+
}
245+
if (singleLogoutServiceBinding != null) {
246+
builder.singleLogoutServiceBinding(singleLogoutServiceBinding);
247+
}
248+
if (StringUtils.hasText(assertionConsumerServiceLocation)) {
249+
builder.assertionConsumerServiceLocation(assertionConsumerServiceLocation);
250+
}
251+
if (assertionConsumerServiceBinding != null) {
252+
builder.assertionConsumerServiceBinding(assertionConsumerServiceBinding);
253+
}
235254
}
236255

237256
private static void buildAssertingParty(Element relyingPartyElt, Map<String, Map<String, Object>> assertingParties,
@@ -309,15 +328,15 @@ private static Saml2MessageBinding getAssertionConsumerServiceBinding(Element re
309328
if (StringUtils.hasText(assertionConsumerServiceBinding)) {
310329
return Saml2MessageBinding.valueOf(assertionConsumerServiceBinding);
311330
}
312-
return Saml2MessageBinding.REDIRECT;
331+
return null;
313332
}
314333

315334
private static Saml2MessageBinding getSingleLogoutServiceBinding(Element relyingPartyRegistrationElt) {
316335
String singleLogoutServiceBinding = relyingPartyRegistrationElt.getAttribute(ATT_SINGLE_LOGOUT_SERVICE_BINDING);
317336
if (StringUtils.hasText(singleLogoutServiceBinding)) {
318337
return Saml2MessageBinding.valueOf(singleLogoutServiceBinding);
319338
}
320-
return Saml2MessageBinding.POST;
339+
return null;
321340
}
322341

323342
private static Saml2X509Credential getSaml2VerificationCredential(String certificateLocation) {

config/src/test/java/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParserTests.java

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2022 the original author or authors.
2+
* Copyright 2002-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -62,6 +62,27 @@ public class RelyingPartyRegistrationsBeanDefinitionParserTests {
6262
"</b:beans>\n";
6363
// @formatter:on
6464

65+
// @formatter:off
66+
private static final String METADATA_LOCATION_OVERRIDE_PROPERTIES_XML_CONFIG = "<b:beans xmlns:b=\"http://www.springframework.org/schema/beans\"\n" +
67+
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
68+
" xmlns=\"http://www.springframework.org/schema/security\"\n" +
69+
" xsi:schemaLocation=\"\n" +
70+
"\t\t\thttp://www.springframework.org/schema/security\n" +
71+
"\t\t\thttps://www.springframework.org/schema/security/spring-security.xsd\n" +
72+
"\t\t\thttp://www.springframework.org/schema/beans\n" +
73+
"\t\t\thttps://www.springframework.org/schema/beans/spring-beans.xsd\">\n" +
74+
" \n" +
75+
" <relying-party-registrations>\n" +
76+
" <relying-party-registration registration-id=\"one\"\n" +
77+
" entity-id=\"https://rp.example.org\"\n" +
78+
" metadata-location=\"${metadata-location}\"\n" +
79+
" assertion-consumer-service-location=\"https://rp.example.org/location\"\n" +
80+
" assertion-consumer-service-binding=\"REDIRECT\"/>" +
81+
" </relying-party-registrations>\n" +
82+
"\n" +
83+
"</b:beans>\n";
84+
// @formatter:on
85+
6586
// @formatter:off
6687
private static final String METADATA_RESPONSE = "<?xml version=\"1.0\"?>\n" +
6788
"<md:EntityDescriptor xmlns:md=\"urn:oasis:names:tc:SAML:2.0:metadata\" xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\" entityID=\"https://simplesaml-for-spring-saml.apps.pcfone.io/saml2/idp/metadata.php\" ID=\"_e793a707d3e1a9ee6cbec7454fdad2c7cd793dd3703179a527b9620a6e9682af\"><ds:Signature>\n" +
@@ -143,6 +164,41 @@ public void parseWhenMetadataLocationConfiguredThenRequestMetadataFromLocation()
143164
.containsExactly("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
144165
}
145166

167+
@Test
168+
public void parseWhenMetadataLocationConfiguredAndRegistrationHasPropertiesThenDoNotOverrideSpecifiedProperties()
169+
throws Exception {
170+
this.server = new MockWebServer();
171+
this.server.start();
172+
String serverUrl = this.server.url("/").toString();
173+
this.server.enqueue(xmlResponse(METADATA_RESPONSE));
174+
String metadataConfig = METADATA_LOCATION_OVERRIDE_PROPERTIES_XML_CONFIG.replace("${metadata-location}",
175+
serverUrl);
176+
this.spring.context(metadataConfig).autowire();
177+
assertThat(this.relyingPartyRegistrationRepository)
178+
.isInstanceOf(InMemoryRelyingPartyRegistrationRepository.class);
179+
RelyingPartyRegistration relyingPartyRegistration = this.relyingPartyRegistrationRepository
180+
.findByRegistrationId("one");
181+
RelyingPartyRegistration.AssertingPartyDetails assertingPartyDetails = relyingPartyRegistration
182+
.getAssertingPartyDetails();
183+
assertThat(relyingPartyRegistration).isNotNull();
184+
assertThat(relyingPartyRegistration.getRegistrationId()).isEqualTo("one");
185+
assertThat(relyingPartyRegistration.getEntityId()).isEqualTo("https://rp.example.org");
186+
assertThat(relyingPartyRegistration.getAssertionConsumerServiceLocation())
187+
.isEqualTo("https://rp.example.org/location");
188+
assertThat(relyingPartyRegistration.getAssertionConsumerServiceBinding())
189+
.isEqualTo(Saml2MessageBinding.REDIRECT);
190+
assertThat(assertingPartyDetails.getEntityId())
191+
.isEqualTo("https://simplesaml-for-spring-saml.apps.pcfone.io/saml2/idp/metadata.php");
192+
assertThat(assertingPartyDetails.getWantAuthnRequestsSigned()).isFalse();
193+
assertThat(assertingPartyDetails.getVerificationX509Credentials()).hasSize(1);
194+
assertThat(assertingPartyDetails.getEncryptionX509Credentials()).hasSize(1);
195+
assertThat(assertingPartyDetails.getSingleSignOnServiceLocation())
196+
.isEqualTo("https://simplesaml-for-spring-saml.apps.pcfone.io/saml2/idp/SSOService.php");
197+
assertThat(assertingPartyDetails.getSingleSignOnServiceBinding()).isEqualTo(Saml2MessageBinding.REDIRECT);
198+
assertThat(assertingPartyDetails.getSigningAlgorithms())
199+
.containsExactly("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
200+
}
201+
146202
@Test
147203
public void parseWhenSingleRelyingPartyRegistrationThenAvailableInRepository() {
148204
this.spring.configLocations(xml("SingleRegistration")).autowire();

0 commit comments

Comments
 (0)