Skip to content

Commit 27294b2

Browse files
committed
Allow RelyingPartyRegistration Placeholder Resolution in XML
Closes gh-14645
1 parent 689a414 commit 27294b2

File tree

3 files changed

+79
-11
lines changed

3 files changed

+79
-11
lines changed

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

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,10 @@ private List<RelyingPartyRegistration> getRelyingPartyRegistrations(Element elem
213213
private static RelyingPartyRegistration.Builder getBuilderFromMetadataLocationIfPossible(
214214
Element relyingPartyRegistrationElt, Map<String, Map<String, Object>> assertingParties,
215215
ParserContext parserContext) {
216-
String registrationId = relyingPartyRegistrationElt.getAttribute(ATT_REGISTRATION_ID);
217-
String metadataLocation = relyingPartyRegistrationElt.getAttribute(ATT_METADATA_LOCATION);
216+
String registrationId = resolveAttribute(parserContext,
217+
relyingPartyRegistrationElt.getAttribute(ATT_REGISTRATION_ID));
218+
String metadataLocation = resolveAttribute(parserContext,
219+
relyingPartyRegistrationElt.getAttribute(ATT_METADATA_LOCATION));
218220
RelyingPartyRegistration.Builder builder;
219221
if (StringUtils.hasText(metadataLocation)) {
220222
builder = RelyingPartyRegistrations.fromMetadataLocation(metadataLocation).registrationId(registrationId);
@@ -224,20 +226,20 @@ private static RelyingPartyRegistration.Builder getBuilderFromMetadataLocationIf
224226
.assertingPartyMetadata((apBuilder) -> buildAssertingParty(relyingPartyRegistrationElt,
225227
assertingParties, apBuilder, parserContext));
226228
}
227-
addRemainingProperties(relyingPartyRegistrationElt, builder);
229+
addRemainingProperties(parserContext, relyingPartyRegistrationElt, builder);
228230
return builder;
229231
}
230232

231-
private static void addRemainingProperties(Element relyingPartyRegistrationElt,
233+
private static void addRemainingProperties(ParserContext pc, Element relyingPartyRegistrationElt,
232234
RelyingPartyRegistration.Builder builder) {
233-
String entityId = relyingPartyRegistrationElt.getAttribute(ATT_ENTITY_ID);
234-
String singleLogoutServiceLocation = relyingPartyRegistrationElt
235-
.getAttribute(ATT_SINGLE_LOGOUT_SERVICE_LOCATION);
236-
String singleLogoutServiceResponseLocation = relyingPartyRegistrationElt
237-
.getAttribute(ATT_SINGLE_LOGOUT_SERVICE_RESPONSE_LOCATION);
235+
String entityId = resolveAttribute(pc, relyingPartyRegistrationElt.getAttribute(ATT_ENTITY_ID));
236+
String singleLogoutServiceLocation = resolveAttribute(pc,
237+
relyingPartyRegistrationElt.getAttribute(ATT_SINGLE_LOGOUT_SERVICE_LOCATION));
238+
String singleLogoutServiceResponseLocation = resolveAttribute(pc,
239+
relyingPartyRegistrationElt.getAttribute(ATT_SINGLE_LOGOUT_SERVICE_RESPONSE_LOCATION));
238240
Saml2MessageBinding singleLogoutServiceBinding = getSingleLogoutServiceBinding(relyingPartyRegistrationElt);
239-
String assertionConsumerServiceLocation = relyingPartyRegistrationElt
240-
.getAttribute(ATT_ASSERTION_CONSUMER_SERVICE_LOCATION);
241+
String assertionConsumerServiceLocation = resolveAttribute(pc,
242+
relyingPartyRegistrationElt.getAttribute(ATT_ASSERTION_CONSUMER_SERVICE_LOCATION));
241243
Saml2MessageBinding assertionConsumerServiceBinding = getAssertionConsumerServiceBinding(
242244
relyingPartyRegistrationElt);
243245
if (StringUtils.hasText(entityId)) {
@@ -400,4 +402,8 @@ private static X509Certificate readCertificate(String certificateLocation) {
400402
}
401403
}
402404

405+
private static String resolveAttribute(ParserContext pc, String value) {
406+
return pc.getReaderContext().getEnvironment().resolvePlaceholders(value);
407+
}
408+
403409
}

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
3636
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
3737
import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
38+
import org.springframework.security.saml2.provider.service.registration.TestRelyingPartyRegistrations;
3839
import org.springframework.security.saml2.provider.service.web.authentication.OpenSaml4AuthenticationRequestResolver;
3940

4041
import static org.assertj.core.api.Assertions.assertThat;
@@ -288,6 +289,32 @@ public void parseWhenRelayStateResolverThenUses() {
288289
verify(relayStateResolver).convert(request);
289290
}
290291

292+
@Test
293+
public void parseWhenPlaceholdersThenResolves() throws Exception {
294+
RelyingPartyRegistration sample = TestRelyingPartyRegistrations.relyingPartyRegistration().build();
295+
System.setProperty("registration-id", sample.getRegistrationId());
296+
System.setProperty("entity-id", sample.getEntityId());
297+
System.setProperty("acs-location", sample.getAssertionConsumerServiceLocation());
298+
System.setProperty("slo-location", sample.getSingleLogoutServiceLocation());
299+
System.setProperty("slo-response-location", sample.getSingleLogoutServiceResponseLocation());
300+
try (MockWebServer web = new MockWebServer()) {
301+
web.start();
302+
String serverUrl = web.url("/metadata").toString();
303+
web.enqueue(xmlResponse(METADATA_RESPONSE));
304+
System.setProperty("metadata-location", serverUrl);
305+
this.spring.configLocations(xml("PlaceholderRegistration")).autowire();
306+
}
307+
RelyingPartyRegistration registration = this.relyingPartyRegistrationRepository
308+
.findByRegistrationId(sample.getRegistrationId());
309+
assertThat(registration.getRegistrationId()).isEqualTo(sample.getRegistrationId());
310+
assertThat(registration.getEntityId()).isEqualTo(sample.getEntityId());
311+
assertThat(registration.getAssertionConsumerServiceLocation())
312+
.isEqualTo(sample.getAssertionConsumerServiceLocation());
313+
assertThat(registration.getSingleLogoutServiceLocation()).isEqualTo(sample.getSingleLogoutServiceLocation());
314+
assertThat(registration.getSingleLogoutServiceResponseLocation())
315+
.isEqualTo(sample.getSingleLogoutServiceResponseLocation());
316+
}
317+
291318
private static MockResponse xmlResponse(String xml) {
292319
return new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE).setBody(xml);
293320
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
~ Copyright 2002-2021 the original author or authors.
4+
~
5+
~ Licensed under the Apache License, Version 2.0 (the "License");
6+
~ you may not use this file except in compliance with the License.
7+
~ You may obtain a copy of the License at
8+
~
9+
~ https://www.apache.org/licenses/LICENSE-2.0
10+
~
11+
~ Unless required by applicable law or agreed to in writing, software
12+
~ distributed under the License is distributed on an "AS IS" BASIS,
13+
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
~ See the License for the specific language governing permissions and
15+
~ limitations under the License.
16+
-->
17+
18+
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
19+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
20+
xmlns="http://www.springframework.org/schema/security"
21+
xsi:schemaLocation="
22+
http://www.springframework.org/schema/security
23+
https://www.springframework.org/schema/security/spring-security.xsd
24+
http://www.springframework.org/schema/beans
25+
https://www.springframework.org/schema/beans/spring-beans.xsd">
26+
27+
<relying-party-registrations>
28+
<relying-party-registration registration-id="${registration-id}"
29+
entity-id="${entity-id}"
30+
metadata-location="${metadata-location}"
31+
assertion-consumer-service-location="${acs-location}"
32+
single-logout-service-location="${slo-location}"
33+
single-logout-service-response-location="${slo-response-location}"/>
34+
</relying-party-registrations>
35+
</b:beans>

0 commit comments

Comments
 (0)