diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/saml2/Saml2RelyingPartyProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/saml2/Saml2RelyingPartyProperties.java index 3dc230994c7..1c22d53558c 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/saml2/Saml2RelyingPartyProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/saml2/Saml2RelyingPartyProperties.java @@ -50,6 +50,17 @@ public class Saml2RelyingPartyProperties { */ public static class Registration { + /** + * Relying party's EntityID. + * + * This value may contain a number of placeholders. They are: baseUrl, + * registrationId, baseScheme, baseHost, and basePort. + * + * The default value is + * {baseUrl}/saml2/service-provider-metadata/{registrationId}. + */ + private String relyingPartyEntityId = "{baseUrl}/saml2/service-provider-metadata/{registrationId}"; + private final Signing signing = new Signing(); /** @@ -57,6 +68,14 @@ public class Saml2RelyingPartyProperties { */ private Identityprovider identityprovider = new Identityprovider(); + public String getRelyingPartyEntityId() { + return this.relyingPartyEntityId; + } + + public void setRelyingPartyEntityId(String entityId) { + this.relyingPartyEntityId = entityId; + } + public Signing getSigning() { return this.signing; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/saml2/Saml2RelyingPartyRegistrationConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/saml2/Saml2RelyingPartyRegistrationConfiguration.java index efb9c290c8a..327bdd4dd05 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/saml2/Saml2RelyingPartyRegistrationConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/saml2/Saml2RelyingPartyRegistrationConfiguration.java @@ -80,6 +80,7 @@ class Saml2RelyingPartyRegistrationConfiguration { builder.assertingPartyDetails((details) -> details .verificationX509Credentials((credentials) -> properties.getIdentityprovider().getVerification() .getCredentials().stream().map(this::asVerificationCredential).forEach(credentials::add))); + builder.entityId(properties.getRelyingPartyEntityId()); return builder.build(); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/saml2/Saml2RelyingPartyAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/saml2/Saml2RelyingPartyAutoConfigurationTests.java index b0d55b02e58..96570d80be6 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/saml2/Saml2RelyingPartyAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/saml2/Saml2RelyingPartyAutoConfigurationTests.java @@ -92,6 +92,7 @@ public class Saml2RelyingPartyAutoConfigurationTests { assertThat(registration.getAssertingPartyDetails().getWantAuthnRequestsSigned()).isEqualTo(false); assertThat(registration.getSigningX509Credentials()).isNotNull(); assertThat(registration.getAssertingPartyDetails().getVerificationX509Credentials()).isNotNull(); + assertThat(registration.getEntityId()).isEqualTo("{baseUrl}/saml2/foo-entity-id"); }); } @@ -149,7 +150,8 @@ public class Saml2RelyingPartyAutoConfigurationTests { PREFIX + ".foo.identityprovider.singlesignon.binding=post", PREFIX + ".foo.identityprovider.singlesignon.sign-request=false", PREFIX + ".foo.identityprovider.entity-id=https://simplesaml-for-spring-saml.cfapps.io/saml2/idp/metadata.php", - PREFIX + ".foo.identityprovider.verification.credentials[0].certificate-location=classpath:saml/certificate-location" }; + PREFIX + ".foo.identityprovider.verification.credentials[0].certificate-location=classpath:saml/certificate-location", + PREFIX + ".foo.relying-party-entity-id={baseUrl}/saml2/foo-entity-id" }; } private boolean hasFilter(AssertableWebApplicationContext context, Class filter) { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/saml2/Saml2RelyingPartyPropertiesTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/saml2/Saml2RelyingPartyPropertiesTests.java index 19b55351bec..378a9a98407 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/saml2/Saml2RelyingPartyPropertiesTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/saml2/Saml2RelyingPartyPropertiesTests.java @@ -25,6 +25,7 @@ import org.springframework.boot.context.properties.bind.Bindable; import org.springframework.boot.context.properties.bind.Binder; import org.springframework.boot.context.properties.source.ConfigurationPropertySource; import org.springframework.boot.context.properties.source.MapConfigurationPropertySource; +import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration; import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding; import static org.assertj.core.api.Assertions.assertThat; @@ -87,6 +88,20 @@ class Saml2RelyingPartyPropertiesTests { .isSignRequest()).isEqualTo(true); } + @Test + void customizeRelyingPartyEntityId() { + bind("spring.security.saml2.relyingparty.registration.simplesamlphp.relying-party-entity-id", + "{baseUrl}/saml2/custom-entity-id"); + assertThat(this.properties.getRegistration().get("simplesamlphp").getRelyingPartyEntityId()) + .isEqualTo("{baseUrl}/saml2/custom-entity-id"); + } + + @Test + void customizeRelyingPartyEntityIdDefaultsToServiceProviderMetadata() { + assertThat(RelyingPartyRegistration.withRegistrationId("id")).extracting("entityId") + .isEqualTo(new Saml2RelyingPartyProperties.Registration().getRelyingPartyEntityId()); + } + private void bind(String name, String value) { bind(Collections.singletonMap(name, value)); } diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-saml2-service-provider/src/main/resources/application.yml b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-saml2-service-provider/src/main/resources/application.yml index 84201340b60..4256d2d331c 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-saml2-service-provider/src/main/resources/application.yml +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-saml2-service-provider/src/main/resources/application.yml @@ -15,6 +15,7 @@ spring: entity-id: simplesaml singlesignon: url: https://simplesaml-for-spring-saml/SSOService.php + relying-party-entity-id: "{baseUrl}/saml2/simple-relying-party" okta: signing: credentials: