Sfoglia il codice sorgente

Use AssertingPartyMetadata

Issue gh-15394
Josh Cummings 1 anno fa
parent
commit
9d8888c5f0
29 ha cambiato i file con 320 aggiunte e 79 eliminazioni
  1. 7 6
      config/src/main/java/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParser.java
  2. 6 6
      docs/modules/ROOT/pages/servlet/saml2/login/authentication-requests.adoc
  3. 5 5
      docs/modules/ROOT/pages/servlet/saml2/login/overview.adoc
  4. 2 2
      docs/modules/ROOT/pages/servlet/saml2/logout.adoc
  5. 7 8
      docs/modules/ROOT/pages/servlet/saml2/metadata.adoc
  6. 2 2
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSaml4AuthenticationProvider.java
  7. 1 1
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlSigningUtils.java
  8. 3 2
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlVerificationUtils.java
  9. 1 1
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2PostAuthenticationRequest.java
  10. 1 1
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2RedirectAuthenticationRequest.java
  11. 1 1
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/logout/OpenSamlLogoutRequestValidator.java
  12. 1 1
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/logout/OpenSamlLogoutResponseValidator.java
  13. 2 2
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/logout/OpenSamlVerificationUtils.java
  14. 2 2
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/logout/Saml2LogoutRequest.java
  15. 2 2
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/logout/Saml2LogoutResponse.java
  16. 2 2
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/metadata/OpenSamlSigningUtils.java
  17. 1 1
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/InMemoryRelyingPartyRegistrationRepository.java
  18. 6 1
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/OpenSamlRelyingPartyRegistration.java
  19. 83 11
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistration.java
  20. 1 1
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/RelyingPartyRegistrationPlaceholderResolvers.java
  21. 4 4
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/OpenSamlAuthenticationRequestResolver.java
  22. 1 1
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/OpenSamlSigningUtils.java
  23. 2 2
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/OpenSamlVerificationUtils.java
  24. 3 3
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSamlLogoutRequestResolver.java
  25. 4 3
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSamlLogoutResponseResolver.java
  26. 1 1
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSamlSigningUtils.java
  27. 1 1
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutRequestResolver.java
  28. 1 1
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutResponseResolver.java
  29. 167 5
      saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistrationTests.java

+ 7 - 6
config/src/main/java/org/springframework/security/config/saml2/RelyingPartyRegistrationsBeanDefinitionParser.java

@@ -39,6 +39,7 @@ import org.springframework.core.io.Resource;
 import org.springframework.core.io.ResourceLoader;
 import org.springframework.security.converter.RsaKeyConverters;
 import org.springframework.security.saml2.core.Saml2X509Credential;
+import org.springframework.security.saml2.provider.service.registration.AssertingPartyMetadata;
 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.RelyingPartyRegistrations;
@@ -153,7 +154,7 @@ public final class RelyingPartyRegistrationsBeanDefinitionParser implements Bean
 	}
 
 	private static void addVerificationCredentials(Map<String, Object> assertingParty,
-			RelyingPartyRegistration.AssertingPartyDetails.Builder builder) {
+			AssertingPartyMetadata.Builder<?> builder) {
 		List<String> verificationCertificateLocations = (List<String>) assertingParty.get(ELT_VERIFICATION_CREDENTIAL);
 		List<Saml2X509Credential> verificationCredentials = new ArrayList<>();
 		for (String certificateLocation : verificationCertificateLocations) {
@@ -163,7 +164,7 @@ public final class RelyingPartyRegistrationsBeanDefinitionParser implements Bean
 	}
 
 	private static void addEncryptionCredentials(Map<String, Object> assertingParty,
-			RelyingPartyRegistration.AssertingPartyDetails.Builder builder) {
+			AssertingPartyMetadata.Builder<?> builder) {
 		List<String> encryptionCertificateLocations = (List<String>) assertingParty.get(ELT_ENCRYPTION_CREDENTIAL);
 		List<Saml2X509Credential> encryptionCredentials = new ArrayList<>();
 		for (String certificateLocation : encryptionCertificateLocations) {
@@ -220,8 +221,8 @@ public final class RelyingPartyRegistrationsBeanDefinitionParser implements Bean
 		}
 		else {
 			builder = RelyingPartyRegistration.withRegistrationId(registrationId)
-				.assertingPartyDetails((apBuilder) -> buildAssertingParty(relyingPartyRegistrationElt, assertingParties,
-						apBuilder, parserContext));
+				.assertingPartyMetadata((apBuilder) -> buildAssertingParty(relyingPartyRegistrationElt,
+						assertingParties, apBuilder, parserContext));
 		}
 		addRemainingProperties(relyingPartyRegistrationElt, builder);
 		return builder;
@@ -260,7 +261,7 @@ public final class RelyingPartyRegistrationsBeanDefinitionParser implements Bean
 	}
 
 	private static void buildAssertingParty(Element relyingPartyElt, Map<String, Map<String, Object>> assertingParties,
-			RelyingPartyRegistration.AssertingPartyDetails.Builder builder, ParserContext parserContext) {
+			AssertingPartyMetadata.Builder<?> builder, ParserContext parserContext) {
 		String assertingPartyId = relyingPartyElt.getAttribute(ATT_ASSERTING_PARTY_ID);
 		if (!assertingParties.containsKey(assertingPartyId)) {
 			Object source = parserContext.extractSource(relyingPartyElt);
@@ -293,7 +294,7 @@ public final class RelyingPartyRegistrationsBeanDefinitionParser implements Bean
 	}
 
 	private static void addSigningAlgorithms(Map<String, Object> assertingParty,
-			RelyingPartyRegistration.AssertingPartyDetails.Builder builder) {
+			AssertingPartyMetadata.Builder<?> builder) {
 		String signingAlgorithmsAttr = getAsString(assertingParty, ATT_SIGNING_ALGORITHMS);
 		if (StringUtils.hasText(signingAlgorithmsAttr)) {
 			List<String> signingAlgorithms = Arrays.asList(signingAlgorithmsAttr.split(","));

+ 6 - 6
docs/modules/ROOT/pages/servlet/saml2/login/authentication-requests.adoc

@@ -114,7 +114,7 @@ Java::
 ----
 RelyingPartyRegistration relyingPartyRegistration = RelyingPartyRegistration.withRegistrationId("okta")
         // ...
-        .assertingPartyDetails(party -> party
+        .assertingPartyMetadata(party -> party
             // ...
             .wantAuthnRequestsSigned(false)
         )
@@ -128,7 +128,7 @@ Kotlin::
 var relyingPartyRegistration: RelyingPartyRegistration =
     RelyingPartyRegistration.withRegistrationId("okta")
         // ...
-        .assertingPartyDetails { party: AssertingPartyDetails.Builder -> party
+        .assertingPartyMetadata { party: AssertingPartyMetadata.Builder -> party
                 // ...
                 .wantAuthnRequestsSigned(false)
         }
@@ -154,7 +154,7 @@ Java::
 String metadataLocation = "classpath:asserting-party-metadata.xml";
 RelyingPartyRegistration relyingPartyRegistration = RelyingPartyRegistrations.fromMetadataLocation(metadataLocation)
         // ...
-        .assertingPartyDetails((party) -> party
+        .assertingPartyMetadata((party) -> party
             // ...
             .signingAlgorithms((sign) -> sign.add(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA512))
         )
@@ -169,7 +169,7 @@ var metadataLocation = "classpath:asserting-party-metadata.xml"
 var relyingPartyRegistration: RelyingPartyRegistration =
     RelyingPartyRegistrations.fromMetadataLocation(metadataLocation)
         // ...
-        .assertingPartyDetails { party: AssertingPartyDetails.Builder -> party
+        .assertingPartyMetadata { party: AssertingPartyMetadata.Builder -> party
                 // ...
                 .signingAlgorithms { sign: MutableList<String?> ->
                     sign.add(
@@ -197,7 +197,7 @@ Java::
 ----
 RelyingPartyRegistration relyingPartyRegistration = RelyingPartyRegistration.withRegistrationId("okta")
         // ...
-        .assertingPartyDetails(party -> party
+        .assertingPartyMetadata(party -> party
             // ...
             .singleSignOnServiceBinding(Saml2MessageBinding.POST)
         )
@@ -211,7 +211,7 @@ Kotlin::
 var relyingPartyRegistration: RelyingPartyRegistration? =
     RelyingPartyRegistration.withRegistrationId("okta")
         // ...
-        .assertingPartyDetails { party: AssertingPartyDetails.Builder -> party
+        .assertingPartyMetadata { party: AssertingPartyMetadata.Builder -> party
             // ...
             .singleSignOnServiceBinding(Saml2MessageBinding.POST)
         }

+ 5 - 5
docs/modules/ROOT/pages/servlet/saml2/login/overview.adoc

@@ -484,7 +484,7 @@ public RelyingPartyRegistrationRepository relyingPartyRegistrations() throws Exc
     Saml2X509Credential credential = Saml2X509Credential.verification(certificate);
     RelyingPartyRegistration registration = RelyingPartyRegistration
             .withRegistrationId("example")
-            .assertingPartyDetails(party -> party
+            .assertingPartyMetadata(party -> party
                 .entityId("https://idp.example.com/issuer")
                 .singleSignOnServiceLocation("https://idp.example.com/SSO.saml2")
                 .wantAuthnRequestsSigned(false)
@@ -508,7 +508,7 @@ open fun relyingPartyRegistrations(): RelyingPartyRegistrationRepository {
     val credential: Saml2X509Credential = Saml2X509Credential.verification(certificate)
     val registration = RelyingPartyRegistration
         .withRegistrationId("example")
-        .assertingPartyDetails { party: AssertingPartyDetails.Builder ->
+        .assertingPartyMetadata { party: AssertingPartyMetadata.Builder ->
             party
                 .entityId("https://idp.example.com/issuer")
                 .singleSignOnServiceLocation("https://idp.example.com/SSO.saml2")
@@ -699,7 +699,7 @@ RelyingPartyRegistration relyingPartyRegistration = RelyingPartyRegistration.wit
         .entityId("{baseUrl}/{registrationId}")
         .decryptionX509Credentials(c -> c.add(relyingPartyDecryptingCredential()))
         .assertionConsumerServiceLocation("/my-login-endpoint/{registrationId}")
-        .assertingPartyDetails(party -> party
+        .assertingPartyMetadata(party -> party
                 .entityId("https://ap.example.org")
                 .verificationX509Credentials(c -> c.add(assertingPartyVerifyingCredential()))
                 .singleSignOnServiceLocation("https://ap.example.org/SSO.saml2")
@@ -718,7 +718,7 @@ val relyingPartyRegistration =
             c.add(relyingPartyDecryptingCredential())
         }
         .assertionConsumerServiceLocation("/my-login-endpoint/{registrationId}")
-        .assertingPartyDetails { party -> party
+        .assertingPartyMetadata { party -> party
                 .entityId("https://ap.example.org")
                 .verificationX509Credentials { c -> c.add(assertingPartyVerifyingCredential()) }
                 .singleSignOnServiceLocation("https://ap.example.org/SSO.saml2")
@@ -730,7 +730,7 @@ val relyingPartyRegistration =
 [TIP]
 ====
 The top-level metadata methods are details about the relying party.
-The methods inside `assertingPartyDetails` are details about the asserting party.
+The methods inside `AssertingPartyMetadata` are details about the asserting party.
 ====
 
 [NOTE]

+ 2 - 2
docs/modules/ROOT/pages/servlet/saml2/logout.adoc

@@ -339,7 +339,7 @@ It's common to need to set other values in the `<saml2:LogoutRequest>` than the
 
 By default, Spring Security will issue a `<saml2:LogoutRequest>` and supply:
 
-* The `Destination` attribute - from `RelyingPartyRegistration#getAssertingPartyDetails#getSingleLogoutServiceLocation`
+* The `Destination` attribute - from `RelyingPartyRegistration#getAssertingPartyMetadata#getSingleLogoutServiceLocation`
 * The `ID` attribute - a GUID
 * The `<Issuer>` element - from `RelyingPartyRegistration#getEntityId`
 * The `<NameID>` element - from `Authentication#getName`
@@ -424,7 +424,7 @@ It's common to need to set other values in the `<saml2:LogoutResponse>` than the
 
 By default, Spring Security will issue a `<saml2:LogoutResponse>` and supply:
 
-* The `Destination` attribute - from `RelyingPartyRegistration#getAssertingPartyDetails#getSingleLogoutServiceResponseLocation`
+* The `Destination` attribute - from `RelyingPartyRegistration#getAssertingPartyMetadata#getSingleLogoutServiceResponseLocation`
 * The `ID` attribute - a GUID
 * The `<Issuer>` element - from `RelyingPartyRegistration#getEntityId`
 * The `<Status>` element - `SUCCESS`

+ 7 - 8
docs/modules/ROOT/pages/servlet/saml2/metadata.adoc

@@ -1,14 +1,14 @@
 [[servlet-saml2login-metadata]]
 = Saml 2.0 Metadata
 
-Spring Security can <<parsing-asserting-party-metadata,parse asserting party metadata>> to produce an `AssertingPartyDetails` instance as well as <<publishing-relying-party-metadata,publish relying party metadata>> from a `RelyingPartyRegistration` instance.
+Spring Security can <<parsing-asserting-party-metadata,parse asserting party metadata>> to produce an `AssertingPartyMetadata` instance as well as <<publishing-relying-party-metadata,publish relying party metadata>> from a `RelyingPartyRegistration` instance.
 
 [[parsing-asserting-party-metadata]]
 == Parsing `<saml2:IDPSSODescriptor>` metadata
 
 You can parse an asserting party's metadata xref:servlet/saml2/login/overview.adoc#servlet-saml2login-relyingpartyregistrationrepository[using `RelyingPartyRegistrations`].
 
-When using the OpenSAML vendor support, the resulting `AssertingPartyDetails` will be of type `OpenSamlAssertingPartyDetails`.
+When using the OpenSAML vendor support, the resulting `AssertingPartyMetadata` will be of type `OpenSamlAssertingPartyDetails`.
 This means you'll be able to do get the underlying OpenSAML XMLObject by doing the following:
 
 [tabs]
@@ -18,7 +18,7 @@ Java::
 [source,java,role="primary"]
 ----
 OpenSamlAssertingPartyDetails details = (OpenSamlAssertingPartyDetails)
-        registration.getAssertingPartyDetails();
+        registration.getAssertingPartyMetadata();
 EntityDescriptor openSamlEntityDescriptor = details.getEntityDescriptor();
 ----
 
@@ -27,7 +27,7 @@ Kotlin::
 [source,kotlin,role="secondary"]
 ----
 val details: OpenSamlAssertingPartyDetails =
-        registration.getAssertingPartyDetails() as OpenSamlAssertingPartyDetails
+        registration.getAssertingPartyMetadata() as OpenSamlAssertingPartyDetails
 val openSamlEntityDescriptor: EntityDescriptor = details.getEntityDescriptor()
 ----
 ======
@@ -76,8 +76,7 @@ public class RefreshableRelyingPartyRegistrationRepository
     }
 
 	private RelyingPartyRegistration applyRelyingParty(AssertingPartyMetadata metadata) {
-		AssertingPartyDetails details = (AssertingPartyDetails) metadata;
-		return RelyingPartyRegistration.withAssertingPartyDetails(details)
+		return RelyingPartyRegistration.withAssertingPartyMetadata(metadata)
             // apply any relying party configuration
             .build();
 	}
@@ -110,8 +109,8 @@ class RefreshableRelyingPartyRegistrationRepository : IterableRelyingPartyRegist
     }
 
     private fun applyRelyingParty(metadata: AssertingPartyMetadata): RelyingPartyRegistration {
-        val details: AssertingPartyDetails = metadata as AssertingPartyDetails
-        return RelyingPartyRegistration.withAssertingPartyDetails(details)
+        val details: AssertingPartyMetadata = metadata as AssertingPartyMetadata
+        return RelyingPartyRegistration.withAssertingPartyMetadata(details)
             // apply any relying party configuration
             .build()
     }

+ 2 - 2
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSaml4AuthenticationProvider.java

@@ -400,7 +400,7 @@ public final class OpenSaml4AuthenticationProvider implements AuthenticationProv
 				result = result.concat(new Saml2Error(Saml2ErrorCodes.INVALID_DESTINATION, message));
 			}
 			String assertingPartyEntityId = token.getRelyingPartyRegistration()
-				.getAssertingPartyDetails()
+				.getAssertingPartyMetadata()
 				.getEntityId();
 			if (!StringUtils.hasText(issuer) || !issuer.equals(assertingPartyEntityId)) {
 				String message = String.format("Invalid issuer [%s] for SAML response [%s]", issuer, response.getID());
@@ -775,7 +775,7 @@ public final class OpenSaml4AuthenticationProvider implements AuthenticationProv
 		RelyingPartyRegistration relyingPartyRegistration = token.getRelyingPartyRegistration();
 		String audience = relyingPartyRegistration.getEntityId();
 		String recipient = relyingPartyRegistration.getAssertionConsumerServiceLocation();
-		String assertingPartyEntityId = relyingPartyRegistration.getAssertingPartyDetails().getEntityId();
+		String assertingPartyEntityId = relyingPartyRegistration.getAssertingPartyMetadata().getEntityId();
 		Map<String, Object> params = new HashMap<>();
 		Assertion assertion = assertionToken.getAssertion();
 		if (assertionContainsInResponseTo(assertion)) {

+ 1 - 1
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlSigningUtils.java

@@ -96,7 +96,7 @@ final class OpenSamlSigningUtils {
 	private static SignatureSigningParameters resolveSigningParameters(
 			RelyingPartyRegistration relyingPartyRegistration) {
 		List<Credential> credentials = resolveSigningCredentials(relyingPartyRegistration);
-		List<String> algorithms = relyingPartyRegistration.getAssertingPartyDetails().getSigningAlgorithms();
+		List<String> algorithms = relyingPartyRegistration.getAssertingPartyMetadata().getSigningAlgorithms();
 		List<String> digests = Collections.singletonList(SignatureConstants.ALGO_ID_DIGEST_SHA256);
 		String canonicalization = SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS;
 		SignatureSigningParametersResolver resolver = new SAMLMetadataSignatureSigningParametersResolver();

+ 3 - 2
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlVerificationUtils.java

@@ -73,11 +73,12 @@ final class OpenSamlVerificationUtils {
 
 	static SignatureTrustEngine trustEngine(RelyingPartyRegistration registration) {
 		Set<Credential> credentials = new HashSet<>();
-		Collection<Saml2X509Credential> keys = registration.getAssertingPartyDetails().getVerificationX509Credentials();
+		Collection<Saml2X509Credential> keys = registration.getAssertingPartyMetadata()
+			.getVerificationX509Credentials();
 		for (Saml2X509Credential key : keys) {
 			BasicX509Credential cred = new BasicX509Credential(key.getCertificate());
 			cred.setUsageType(UsageType.SIGNING);
-			cred.setEntityId(registration.getAssertingPartyDetails().getEntityId());
+			cred.setEntityId(registration.getAssertingPartyMetadata().getEntityId());
 			credentials.add(cred);
 		}
 		CredentialResolver credentialsResolver = new CollectionCredentialResolver(credentials);

+ 1 - 1
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2PostAuthenticationRequest.java

@@ -50,7 +50,7 @@ public class Saml2PostAuthenticationRequest extends AbstractSaml2AuthenticationR
 	 * @since 5.7
 	 */
 	public static Builder withRelyingPartyRegistration(RelyingPartyRegistration registration) {
-		String location = registration.getAssertingPartyDetails().getSingleSignOnServiceLocation();
+		String location = registration.getAssertingPartyMetadata().getSingleSignOnServiceLocation();
 		return new Builder(registration).authenticationRequestUri(location);
 	}
 

+ 1 - 1
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2RedirectAuthenticationRequest.java

@@ -73,7 +73,7 @@ public final class Saml2RedirectAuthenticationRequest extends AbstractSaml2Authe
 	 * @since 5.7
 	 */
 	public static Builder withRelyingPartyRegistration(RelyingPartyRegistration registration) {
-		String location = registration.getAssertingPartyDetails().getSingleSignOnServiceLocation();
+		String location = registration.getAssertingPartyMetadata().getSingleSignOnServiceLocation();
 		return new Builder(registration).authenticationRequestUri(location);
 	}
 

+ 1 - 1
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/logout/OpenSamlLogoutRequestValidator.java

@@ -134,7 +134,7 @@ public final class OpenSamlLogoutRequestValidator implements Saml2LogoutRequestV
 				return;
 			}
 			String issuer = request.getIssuer().getValue();
-			if (!issuer.equals(registration.getAssertingPartyDetails().getEntityId())) {
+			if (!issuer.equals(registration.getAssertingPartyMetadata().getEntityId())) {
 				errors
 					.add(new Saml2Error(Saml2ErrorCodes.INVALID_ISSUER, "Failed to match issuer to configured issuer"));
 			}

+ 1 - 1
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/logout/OpenSamlLogoutResponseValidator.java

@@ -132,7 +132,7 @@ public class OpenSamlLogoutResponseValidator implements Saml2LogoutResponseValid
 				return;
 			}
 			String issuer = response.getIssuer().getValue();
-			if (!issuer.equals(registration.getAssertingPartyDetails().getEntityId())) {
+			if (!issuer.equals(registration.getAssertingPartyMetadata().getEntityId())) {
 				errors
 					.add(new Saml2Error(Saml2ErrorCodes.INVALID_ISSUER, "Failed to match issuer to configured issuer"));
 			}

+ 2 - 2
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/logout/OpenSamlVerificationUtils.java

@@ -164,12 +164,12 @@ final class OpenSamlVerificationUtils {
 
 		private SignatureTrustEngine trustEngine(RelyingPartyRegistration registration) {
 			Set<Credential> credentials = new HashSet<>();
-			Collection<Saml2X509Credential> keys = registration.getAssertingPartyDetails()
+			Collection<Saml2X509Credential> keys = registration.getAssertingPartyMetadata()
 				.getVerificationX509Credentials();
 			for (Saml2X509Credential key : keys) {
 				BasicX509Credential cred = new BasicX509Credential(key.getCertificate());
 				cred.setUsageType(UsageType.SIGNING);
-				cred.setEntityId(registration.getAssertingPartyDetails().getEntityId());
+				cred.setEntityId(registration.getAssertingPartyMetadata().getEntityId());
 				credentials.add(cred);
 			}
 			CredentialResolver credentialsResolver = new CollectionCredentialResolver(credentials);

+ 2 - 2
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/logout/Saml2LogoutRequest.java

@@ -190,8 +190,8 @@ public final class Saml2LogoutRequest implements Serializable {
 
 		private Builder(RelyingPartyRegistration registration) {
 			this.registration = registration;
-			this.location = registration.getAssertingPartyDetails().getSingleLogoutServiceLocation();
-			this.binding = registration.getAssertingPartyDetails().getSingleLogoutServiceBinding();
+			this.location = registration.getAssertingPartyMetadata().getSingleLogoutServiceLocation();
+			this.binding = registration.getAssertingPartyMetadata().getSingleLogoutServiceBinding();
 		}
 
 		/**

+ 2 - 2
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/logout/Saml2LogoutResponse.java

@@ -156,8 +156,8 @@ public final class Saml2LogoutResponse {
 		private Function<Map<String, String>, String> encoder = DEFAULT_ENCODER;
 
 		private Builder(RelyingPartyRegistration registration) {
-			this.location = registration.getAssertingPartyDetails().getSingleLogoutServiceResponseLocation();
-			this.binding = registration.getAssertingPartyDetails().getSingleLogoutServiceBinding();
+			this.location = registration.getAssertingPartyMetadata().getSingleLogoutServiceResponseLocation();
+			this.binding = registration.getAssertingPartyMetadata().getSingleLogoutServiceBinding();
 		}
 
 		/**

+ 2 - 2
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/metadata/OpenSamlSigningUtils.java

@@ -80,7 +80,7 @@ final class OpenSamlSigningUtils {
 	}
 
 	static <O extends SignableXMLObject> O sign(O object, RelyingPartyRegistration relyingPartyRegistration) {
-		List<String> algorithms = relyingPartyRegistration.getAssertingPartyDetails().getSigningAlgorithms();
+		List<String> algorithms = relyingPartyRegistration.getAssertingPartyMetadata().getSigningAlgorithms();
 		List<Credential> credentials = resolveSigningCredentials(relyingPartyRegistration);
 		return sign(object, algorithms, credentials);
 	}
@@ -103,7 +103,7 @@ final class OpenSamlSigningUtils {
 	private static SignatureSigningParameters resolveSigningParameters(
 			RelyingPartyRegistration relyingPartyRegistration) {
 		List<Credential> credentials = resolveSigningCredentials(relyingPartyRegistration);
-		List<String> algorithms = relyingPartyRegistration.getAssertingPartyDetails().getSigningAlgorithms();
+		List<String> algorithms = relyingPartyRegistration.getAssertingPartyMetadata().getSigningAlgorithms();
 		return resolveSigningParameters(algorithms, credentials);
 	}
 

+ 1 - 1
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/InMemoryRelyingPartyRegistrationRepository.java

@@ -69,7 +69,7 @@ public class InMemoryRelyingPartyRegistrationRepository implements IterableRelyi
 			Collection<RelyingPartyRegistration> rps) {
 		MultiValueMap<String, RelyingPartyRegistration> result = new LinkedMultiValueMap<>();
 		for (RelyingPartyRegistration rp : rps) {
-			result.add(rp.getAssertingPartyDetails().getEntityId(), rp);
+			result.add(rp.getAssertingPartyMetadata().getEntityId(), rp);
 		}
 		return Collections.unmodifiableMap(result);
 	}

+ 6 - 1
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/OpenSamlRelyingPartyRegistration.java

@@ -36,7 +36,7 @@ import org.springframework.security.saml2.core.Saml2X509Credential;
  * 	    EntityDescriptor descriptor = openSamlRegistration.getAssertingPartyDetails.getEntityDescriptor();
  * 	}
  * </pre> do instead: <pre>
- * 	if (registration.getAssertingPartyDetails() instanceof openSamlAssertingPartyDetails) {
+ * 	if (registration.getAssertingPartyMetadata() instanceof openSamlAssertingPartyDetails) {
  * 	    EntityDescriptor descriptor = openSamlAssertingPartyDetails.getEntityDescriptor();
  * 	}
  * </pre>
@@ -170,6 +170,11 @@ public final class OpenSamlRelyingPartyRegistration extends RelyingPartyRegistra
 			return (Builder) super.assertingPartyDetails(assertingPartyDetails);
 		}
 
+		@Override
+		public Builder assertingPartyMetadata(Consumer<AssertingPartyMetadata.Builder<?>> assertingPartyMetadata) {
+			return (Builder) super.assertingPartyMetadata(assertingPartyMetadata);
+		}
+
 		/**
 		 * Build an {@link OpenSamlRelyingPartyRegistration}
 		 * {@link org.springframework.security.saml2.provider.service.registration.OpenSamlRelyingPartyRegistration}

+ 83 - 11
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistration.java

@@ -88,7 +88,7 @@ public class RelyingPartyRegistration {
 
 	private final boolean authnRequestsSigned;
 
-	private final AssertingPartyDetails assertingPartyDetails;
+	private final AssertingPartyMetadata assertingPartyMetadata;
 
 	private final Collection<Saml2X509Credential> decryptionX509Credentials;
 
@@ -127,7 +127,45 @@ public class RelyingPartyRegistration {
 		this.singleLogoutServiceBindings = Collections.unmodifiableList(new LinkedList<>(singleLogoutServiceBindings));
 		this.nameIdFormat = nameIdFormat;
 		this.authnRequestsSigned = authnRequestsSigned;
-		this.assertingPartyDetails = assertingPartyDetails;
+		this.assertingPartyMetadata = assertingPartyDetails;
+		this.decryptionX509Credentials = Collections.unmodifiableList(new LinkedList<>(decryptionX509Credentials));
+		this.signingX509Credentials = Collections.unmodifiableList(new LinkedList<>(signingX509Credentials));
+	}
+
+	private RelyingPartyRegistration(String registrationId, String entityId, String assertionConsumerServiceLocation,
+			Saml2MessageBinding assertionConsumerServiceBinding, String singleLogoutServiceLocation,
+			String singleLogoutServiceResponseLocation, Collection<Saml2MessageBinding> singleLogoutServiceBindings,
+			AssertingPartyMetadata assertingPartyMetadata, String nameIdFormat, boolean authnRequestsSigned,
+			Collection<Saml2X509Credential> decryptionX509Credentials,
+			Collection<Saml2X509Credential> signingX509Credentials) {
+		Assert.hasText(registrationId, "registrationId cannot be empty");
+		Assert.hasText(entityId, "entityId cannot be empty");
+		Assert.hasText(assertionConsumerServiceLocation, "assertionConsumerServiceLocation cannot be empty");
+		Assert.notNull(assertionConsumerServiceBinding, "assertionConsumerServiceBinding cannot be null");
+		Assert.isTrue(singleLogoutServiceLocation == null || !CollectionUtils.isEmpty(singleLogoutServiceBindings),
+				"singleLogoutServiceBindings cannot be null or empty when singleLogoutServiceLocation is set");
+		Assert.notNull(assertingPartyMetadata, "assertingPartyDetails cannot be null");
+		Assert.notNull(decryptionX509Credentials, "decryptionX509Credentials cannot be null");
+		for (Saml2X509Credential c : decryptionX509Credentials) {
+			Assert.notNull(c, "decryptionX509Credentials cannot contain null elements");
+			Assert.isTrue(c.isDecryptionCredential(),
+					"All decryptionX509Credentials must have a usage of DECRYPTION set");
+		}
+		Assert.notNull(signingX509Credentials, "signingX509Credentials cannot be null");
+		for (Saml2X509Credential c : signingX509Credentials) {
+			Assert.notNull(c, "signingX509Credentials cannot contain null elements");
+			Assert.isTrue(c.isSigningCredential(), "All signingX509Credentials must have a usage of SIGNING set");
+		}
+		this.registrationId = registrationId;
+		this.entityId = entityId;
+		this.assertionConsumerServiceLocation = assertionConsumerServiceLocation;
+		this.assertionConsumerServiceBinding = assertionConsumerServiceBinding;
+		this.singleLogoutServiceLocation = singleLogoutServiceLocation;
+		this.singleLogoutServiceResponseLocation = singleLogoutServiceResponseLocation;
+		this.singleLogoutServiceBindings = Collections.unmodifiableList(new LinkedList<>(singleLogoutServiceBindings));
+		this.nameIdFormat = nameIdFormat;
+		this.authnRequestsSigned = authnRequestsSigned;
+		this.assertingPartyMetadata = assertingPartyMetadata;
 		this.decryptionX509Credentials = Collections.unmodifiableList(new LinkedList<>(decryptionX509Credentials));
 		this.signingX509Credentials = Collections.unmodifiableList(new LinkedList<>(signingX509Credentials));
 	}
@@ -139,7 +177,7 @@ public class RelyingPartyRegistration {
 	 * @since 6.1
 	 */
 	public Builder mutate() {
-		return new Builder(this.registrationId, this.assertingPartyDetails.mutate()).entityId(this.entityId)
+		return new Builder(this.registrationId, this.assertingPartyMetadata.mutate()).entityId(this.entityId)
 			.signingX509Credentials((c) -> c.addAll(this.signingX509Credentials))
 			.decryptionX509Credentials((c) -> c.addAll(this.decryptionX509Credentials))
 			.assertionConsumerServiceLocation(this.assertionConsumerServiceLocation)
@@ -317,9 +355,22 @@ public class RelyingPartyRegistration {
 	 * Get the configuration details for the Asserting Party
 	 * @return the {@link AssertingPartyDetails}
 	 * @since 5.4
+	 * @deprecated Use {@link #getAssertingPartyMetadata()} instead
 	 */
+	@Deprecated
 	public AssertingPartyDetails getAssertingPartyDetails() {
-		return this.assertingPartyDetails;
+		Assert.isInstanceOf(AssertingPartyDetails.class, this.assertingPartyMetadata,
+				"This class was initialized with an AssertingPartyMetadata, please call #getAssertingPartyMetadata instead");
+		return (AssertingPartyDetails) this.assertingPartyMetadata;
+	}
+
+	/**
+	 * Get the metadata for the Asserting Party
+	 * @return the {@link AssertingPartyDetails}
+	 * @since 6.4
+	 */
+	public AssertingPartyMetadata getAssertingPartyMetadata() {
+		return this.assertingPartyMetadata;
 	}
 
 	/**
@@ -333,6 +384,12 @@ public class RelyingPartyRegistration {
 		return new Builder(registrationId, new AssertingPartyDetails.Builder());
 	}
 
+	/**
+	 * @param assertingPartyDetails the asserting party metadata
+	 * @return {@code Builder} to create a {@code RelyingPartyRegistration} object
+	 * @deprecated Use {@link #withAssertingPartyMetadata} instead
+	 */
+	@Deprecated(forRemoval = true, since = "6.4")
 	public static Builder withAssertingPartyDetails(AssertingPartyDetails assertingPartyDetails) {
 		Assert.notNull(assertingPartyDetails, "assertingPartyDetails cannot be null");
 		return new Builder(assertingPartyDetails.getEntityId(), assertingPartyDetails.mutate());
@@ -353,8 +410,8 @@ public class RelyingPartyRegistration {
 	 * @since 6.4
 	 */
 	public static Builder withAssertingPartyMetadata(AssertingPartyMetadata metadata) {
-		Assert.isInstanceOf(AssertingPartyDetails.class, metadata, "metadata must be of type AssertingPartyDetails");
-		return withAssertingPartyDetails((AssertingPartyDetails) metadata);
+		Assert.notNull(metadata, "assertingPartyMetadata cannot be null");
+		return new Builder(metadata.getEntityId(), metadata.mutate());
 	}
 
 	/**
@@ -819,11 +876,11 @@ public class RelyingPartyRegistration {
 
 		private boolean authnRequestsSigned = false;
 
-		private AssertingPartyDetails.Builder assertingPartyDetailsBuilder;
+		private AssertingPartyMetadata.Builder<?> assertingPartyMetadataBuilder;
 
-		protected Builder(String registrationId, AssertingPartyDetails.Builder assertingPartyDetailsBuilder) {
+		protected Builder(String registrationId, AssertingPartyMetadata.Builder<?> assertingPartyMetadataBuilder) {
 			this.registrationId = registrationId;
-			this.assertingPartyDetailsBuilder = assertingPartyDetailsBuilder;
+			this.assertingPartyMetadataBuilder = assertingPartyMetadataBuilder;
 		}
 
 		/**
@@ -1028,9 +1085,24 @@ public class RelyingPartyRegistration {
 		 * @param assertingPartyDetails The {@link Consumer} to apply
 		 * @return the {@link Builder} for further configuration
 		 * @since 5.4
+		 * @deprecated Use {@link #assertingPartyMetadata} instead
 		 */
+		@Deprecated(forRemoval = true, since = "6.4")
 		public Builder assertingPartyDetails(Consumer<AssertingPartyDetails.Builder> assertingPartyDetails) {
-			assertingPartyDetails.accept(this.assertingPartyDetailsBuilder);
+			Assert.isInstanceOf(AssertingPartyDetails.Builder.class, this.assertingPartyMetadataBuilder,
+					"This class was constructed with an AssertingPartyMetadata instance, as such, please use #assertingPartyMetadata");
+			assertingPartyDetails.accept((AssertingPartyDetails.Builder) this.assertingPartyMetadataBuilder);
+			return this;
+		}
+
+		/**
+		 * Apply this {@link Consumer} to further configure the Asserting Party metadata
+		 * @param assertingPartyMetadata The {@link Consumer} to apply
+		 * @return the {@link Builder} for further configuration
+		 * @since 6.4
+		 */
+		public Builder assertingPartyMetadata(Consumer<AssertingPartyMetadata.Builder<?>> assertingPartyMetadata) {
+			assertingPartyMetadata.accept(this.assertingPartyMetadataBuilder);
 			return this;
 		}
 
@@ -1048,7 +1120,7 @@ public class RelyingPartyRegistration {
 				this.singleLogoutServiceBindings.add(Saml2MessageBinding.POST);
 			}
 
-			AssertingPartyDetails party = this.assertingPartyDetailsBuilder.build();
+			AssertingPartyMetadata party = this.assertingPartyMetadataBuilder.build();
 			return new RelyingPartyRegistration(this.registrationId, this.entityId,
 					this.assertionConsumerServiceLocation, this.assertionConsumerServiceBinding,
 					this.singleLogoutServiceLocation, this.singleLogoutServiceResponseLocation,

+ 1 - 1
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/RelyingPartyRegistrationPlaceholderResolvers.java

@@ -68,7 +68,7 @@ public final class RelyingPartyRegistrationPlaceholderResolvers {
 	 */
 	public static UriResolver uriResolver(HttpServletRequest request, RelyingPartyRegistration registration) {
 		String relyingPartyEntityId = registration.getEntityId();
-		String assertingPartyEntityId = registration.getAssertingPartyDetails().getEntityId();
+		String assertingPartyEntityId = registration.getAssertingPartyMetadata().getEntityId();
 		String registrationId = registration.getRegistrationId();
 		Map<String, String> uriVariables = uriVariables(request);
 		uriVariables.put("relyingPartyEntityId", StringUtils.hasText(relyingPartyEntityId) ? relyingPartyEntityId : "");

+ 4 - 4
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/OpenSamlAuthenticationRequestResolver.java

@@ -146,7 +146,7 @@ class OpenSamlAuthenticationRequestResolver {
 		Issuer iss = this.issuerBuilder.buildObject();
 		iss.setValue(entityId);
 		authnRequest.setIssuer(iss);
-		authnRequest.setDestination(registration.getAssertingPartyDetails().getSingleSignOnServiceLocation());
+		authnRequest.setDestination(registration.getAssertingPartyMetadata().getSingleSignOnServiceLocation());
 		authnRequest.setAssertionConsumerServiceURL(assertionConsumerServiceLocation);
 		if (registration.getNameIdFormat() != null) {
 			NameIDPolicy nameIdPolicy = this.nameIdPolicyBuilder.buildObject();
@@ -158,9 +158,9 @@ class OpenSamlAuthenticationRequestResolver {
 			authnRequest.setID("ARQ" + UUID.randomUUID().toString().substring(1));
 		}
 		String relayState = this.relayStateResolver.convert(request);
-		Saml2MessageBinding binding = registration.getAssertingPartyDetails().getSingleSignOnServiceBinding();
+		Saml2MessageBinding binding = registration.getAssertingPartyMetadata().getSingleSignOnServiceBinding();
 		if (binding == Saml2MessageBinding.POST) {
-			if (registration.getAssertingPartyDetails().getWantAuthnRequestsSigned()
+			if (registration.getAssertingPartyMetadata().getWantAuthnRequestsSigned()
 					|| registration.isAuthnRequestsSigned()) {
 				OpenSamlSigningUtils.sign(authnRequest, registration);
 			}
@@ -180,7 +180,7 @@ class OpenSamlAuthenticationRequestResolver {
 				.samlRequest(deflatedAndEncoded)
 				.relayState(relayState)
 				.id(authnRequest.getID());
-			if (registration.getAssertingPartyDetails().getWantAuthnRequestsSigned()
+			if (registration.getAssertingPartyMetadata().getWantAuthnRequestsSigned()
 					|| registration.isAuthnRequestsSigned()) {
 				OpenSamlSigningUtils.QueryParametersPartial parametersPartial = OpenSamlSigningUtils.sign(registration)
 					.param(Saml2ParameterNames.SAML_REQUEST, deflatedAndEncoded);

+ 1 - 1
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/OpenSamlSigningUtils.java

@@ -95,7 +95,7 @@ final class OpenSamlSigningUtils {
 	private static SignatureSigningParameters resolveSigningParameters(
 			RelyingPartyRegistration relyingPartyRegistration) {
 		List<Credential> credentials = resolveSigningCredentials(relyingPartyRegistration);
-		List<String> algorithms = relyingPartyRegistration.getAssertingPartyDetails().getSigningAlgorithms();
+		List<String> algorithms = relyingPartyRegistration.getAssertingPartyMetadata().getSigningAlgorithms();
 		List<String> digests = Collections.singletonList(SignatureConstants.ALGO_ID_DIGEST_SHA256);
 		String canonicalization = SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS;
 		SignatureSigningParametersResolver resolver = new SAMLMetadataSignatureSigningParametersResolver();

+ 2 - 2
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/OpenSamlVerificationUtils.java

@@ -155,12 +155,12 @@ final class OpenSamlVerificationUtils {
 
 		private SignatureTrustEngine trustEngine(RelyingPartyRegistration registration) {
 			Set<Credential> credentials = new HashSet<>();
-			Collection<Saml2X509Credential> keys = registration.getAssertingPartyDetails()
+			Collection<Saml2X509Credential> keys = registration.getAssertingPartyMetadata()
 				.getVerificationX509Credentials();
 			for (Saml2X509Credential key : keys) {
 				BasicX509Credential cred = new BasicX509Credential(key.getCertificate());
 				cred.setUsageType(UsageType.SIGNING);
-				cred.setEntityId(registration.getAssertingPartyDetails().getEntityId());
+				cred.setEntityId(registration.getAssertingPartyMetadata().getEntityId());
 				credentials.add(cred);
 			}
 			CredentialResolver credentialsResolver = new CollectionCredentialResolver(credentials);

+ 3 - 3
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSamlLogoutRequestResolver.java

@@ -126,13 +126,13 @@ final class OpenSamlLogoutRequestResolver {
 		if (registration == null) {
 			return null;
 		}
-		if (registration.getAssertingPartyDetails().getSingleLogoutServiceLocation() == null) {
+		if (registration.getAssertingPartyMetadata().getSingleLogoutServiceLocation() == null) {
 			return null;
 		}
 		UriResolver uriResolver = RelyingPartyRegistrationPlaceholderResolvers.uriResolver(request, registration);
 		String entityId = uriResolver.resolve(registration.getEntityId());
 		LogoutRequest logoutRequest = this.logoutRequestBuilder.buildObject();
-		logoutRequest.setDestination(registration.getAssertingPartyDetails().getSingleLogoutServiceLocation());
+		logoutRequest.setDestination(registration.getAssertingPartyMetadata().getSingleLogoutServiceLocation());
 		Issuer issuer = this.issuerBuilder.buildObject();
 		issuer.setValue(entityId);
 		logoutRequest.setIssuer(issuer);
@@ -154,7 +154,7 @@ final class OpenSamlLogoutRequestResolver {
 		String relayState = this.relayStateResolver.convert(request);
 		Saml2LogoutRequest.Builder result = Saml2LogoutRequest.withRelyingPartyRegistration(registration)
 			.id(logoutRequest.getID());
-		if (registration.getAssertingPartyDetails().getSingleLogoutServiceBinding() == Saml2MessageBinding.POST) {
+		if (registration.getAssertingPartyMetadata().getSingleLogoutServiceBinding() == Saml2MessageBinding.POST) {
 			String xml = serialize(OpenSamlSigningUtils.sign(logoutRequest, registration));
 			String samlRequest = Saml2Utils.samlEncode(xml.getBytes(StandardCharsets.UTF_8));
 			return result.samlRequest(samlRequest).relayState(relayState).build();

+ 4 - 3
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSamlLogoutResponseResolver.java

@@ -143,13 +143,14 @@ final class OpenSamlLogoutResponseResolver {
 		if (registration == null) {
 			return null;
 		}
-		if (registration.getAssertingPartyDetails().getSingleLogoutServiceResponseLocation() == null) {
+		if (registration.getAssertingPartyMetadata().getSingleLogoutServiceResponseLocation() == null) {
 			return null;
 		}
 		UriResolver uriResolver = RelyingPartyRegistrationPlaceholderResolvers.uriResolver(request, registration);
 		String entityId = uriResolver.resolve(registration.getEntityId());
 		LogoutResponse logoutResponse = this.logoutResponseBuilder.buildObject();
-		logoutResponse.setDestination(registration.getAssertingPartyDetails().getSingleLogoutServiceResponseLocation());
+		logoutResponse
+			.setDestination(registration.getAssertingPartyMetadata().getSingleLogoutServiceResponseLocation());
 		Issuer issuer = this.issuerBuilder.buildObject();
 		issuer.setValue(entityId);
 		logoutResponse.setIssuer(issuer);
@@ -164,7 +165,7 @@ final class OpenSamlLogoutResponseResolver {
 		}
 		logoutResponseConsumer.accept(registration, logoutResponse);
 		Saml2LogoutResponse.Builder result = Saml2LogoutResponse.withRelyingPartyRegistration(registration);
-		if (registration.getAssertingPartyDetails().getSingleLogoutServiceBinding() == Saml2MessageBinding.POST) {
+		if (registration.getAssertingPartyMetadata().getSingleLogoutServiceBinding() == Saml2MessageBinding.POST) {
 			String xml = serialize(OpenSamlSigningUtils.sign(logoutResponse, registration));
 			String samlResponse = Saml2Utils.samlEncode(xml.getBytes(StandardCharsets.UTF_8));
 			result.samlResponse(samlResponse);

+ 1 - 1
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/OpenSamlSigningUtils.java

@@ -96,7 +96,7 @@ final class OpenSamlSigningUtils {
 	private static SignatureSigningParameters resolveSigningParameters(
 			RelyingPartyRegistration relyingPartyRegistration) {
 		List<Credential> credentials = resolveSigningCredentials(relyingPartyRegistration);
-		List<String> algorithms = relyingPartyRegistration.getAssertingPartyDetails().getSigningAlgorithms();
+		List<String> algorithms = relyingPartyRegistration.getAssertingPartyMetadata().getSigningAlgorithms();
 		List<String> digests = Collections.singletonList(SignatureConstants.ALGO_ID_DIGEST_SHA256);
 		String canonicalization = SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS;
 		SignatureSigningParametersResolver resolver = new SAMLMetadataSignatureSigningParametersResolver();

+ 1 - 1
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutRequestResolver.java

@@ -28,7 +28,7 @@ import org.springframework.security.saml2.provider.service.registration.RelyingP
  *
  * The returned logout request is suitable for sending to the asserting party based on,
  * for example, the location and binding specified in
- * {@link RelyingPartyRegistration#getAssertingPartyDetails()}.
+ * {@link RelyingPartyRegistration#getAssertingPartyMetadata()}.
  *
  * @author Josh Cummings
  * @since 5.6

+ 1 - 1
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2LogoutResponseResolver.java

@@ -28,7 +28,7 @@ import org.springframework.security.saml2.provider.service.registration.RelyingP
  *
  * The returned logout response is suitable for sending to the asserting party based on,
  * for example, the location and binding specified in
- * {@link RelyingPartyRegistration#getAssertingPartyDetails()}.
+ * {@link RelyingPartyRegistration#getAssertingPartyMetadata()}.
  *
  * @author Josh Cummings
  * @since 5.6

+ 167 - 5
saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistrationTests.java

@@ -16,13 +16,19 @@
 
 package org.springframework.security.saml2.provider.service.registration;
 
+import java.util.Collection;
+import java.util.List;
+import java.util.function.Consumer;
+
 import org.junit.jupiter.api.Test;
 
 import org.springframework.security.saml2.core.Saml2X509Credential;
 import org.springframework.security.saml2.core.TestSaml2X509Credentials;
+import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration.AssertingPartyDetails;
 import org.springframework.security.saml2.provider.service.web.authentication.Saml2WebSsoAuthenticationFilter;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
 
 public class RelyingPartyRegistrationTests {
 
@@ -167,16 +173,54 @@ public class RelyingPartyRegistrationTests {
 	}
 
 	@Test
-	void withAssertingPartyMetadataWhenDetailsThenBuilderCopies() {
+	void withAssertingPartyMetadataWhenMetadataThenBuilderCopies() {
 		RelyingPartyRegistration registration = TestRelyingPartyRegistrations.relyingPartyRegistration()
 			.nameIdFormat("format")
-			.assertingPartyDetails((a) -> a.singleSignOnServiceBinding(Saml2MessageBinding.POST))
-			.assertingPartyDetails((a) -> a.wantAuthnRequestsSigned(false))
-			.assertingPartyDetails((a) -> a.signingAlgorithms((algs) -> algs.add("alg")))
+			.assertingPartyMetadata((a) -> a.singleSignOnServiceBinding(Saml2MessageBinding.POST))
+			.assertingPartyMetadata((a) -> a.wantAuthnRequestsSigned(false))
+			.assertingPartyMetadata((a) -> a.signingAlgorithms((algs) -> algs.add("alg")))
 			.assertionConsumerServiceBinding(Saml2MessageBinding.REDIRECT)
 			.build();
 		RelyingPartyRegistration copied = RelyingPartyRegistration
-			.withAssertingPartyMetadata(registration.getAssertingPartyDetails())
+			.withAssertingPartyMetadata(registration.getAssertingPartyMetadata())
+			.registrationId(registration.getRegistrationId())
+			.entityId(registration.getEntityId())
+			.signingX509Credentials((c) -> c.addAll(registration.getSigningX509Credentials()))
+			.decryptionX509Credentials((c) -> c.addAll(registration.getDecryptionX509Credentials()))
+			.assertionConsumerServiceLocation(registration.getAssertionConsumerServiceLocation())
+			.assertionConsumerServiceBinding(registration.getAssertionConsumerServiceBinding())
+			.singleLogoutServiceLocation(registration.getSingleLogoutServiceLocation())
+			.singleLogoutServiceResponseLocation(registration.getSingleLogoutServiceResponseLocation())
+			.singleLogoutServiceBindings((c) -> c.addAll(registration.getSingleLogoutServiceBindings()))
+			.nameIdFormat(registration.getNameIdFormat())
+			.authnRequestsSigned(registration.isAuthnRequestsSigned())
+			.build();
+		compareRegistrations(registration, copied);
+	}
+
+	@Test
+	void withAssertingPartyMetadataWhenMetadataThenDisallowsDetails() {
+		AssertingPartyMetadata metadata = new CustomAssertingPartyMetadata();
+		assertThatExceptionOfType(IllegalArgumentException.class)
+			.isThrownBy(() -> RelyingPartyRegistration.withAssertingPartyMetadata(metadata)
+				.assertingPartyDetails((a) -> a.entityId("entity-id"))
+				.build());
+		assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(
+				() -> RelyingPartyRegistration.withAssertingPartyMetadata(metadata).build().getAssertingPartyDetails());
+	}
+
+	@Test
+	void withAssertingPartyMetadataWhenDetailsThenBuilderCopies() {
+		RelyingPartyRegistration registration = TestRelyingPartyRegistrations.relyingPartyRegistration()
+			.nameIdFormat("format")
+			.assertingPartyMetadata((a) -> a.singleSignOnServiceBinding(Saml2MessageBinding.POST))
+			.assertingPartyMetadata((a) -> a.wantAuthnRequestsSigned(false))
+			.assertingPartyMetadata((a) -> a.signingAlgorithms((algs) -> algs.add("alg")))
+			.assertionConsumerServiceBinding(Saml2MessageBinding.REDIRECT)
+			.build();
+		AssertingPartyDetails details = registration.getAssertingPartyDetails();
+		RelyingPartyRegistration copied = RelyingPartyRegistration.withAssertingPartyDetails(details)
+			.assertingPartyDetails((a) -> a.entityId(details.getEntityId()))
 			.registrationId(registration.getRegistrationId())
 			.entityId(registration.getEntityId())
 			.signingX509Credentials((c) -> c.addAll(registration.getSigningX509Credentials()))
@@ -192,4 +236,122 @@ public class RelyingPartyRegistrationTests {
 		compareRegistrations(registration, copied);
 	}
 
+	private static class CustomAssertingPartyMetadata implements AssertingPartyMetadata {
+
+		@Override
+		public String getEntityId() {
+			return "";
+		}
+
+		@Override
+		public boolean getWantAuthnRequestsSigned() {
+			return false;
+		}
+
+		@Override
+		public List<String> getSigningAlgorithms() {
+			return List.of();
+		}
+
+		@Override
+		public Collection<Saml2X509Credential> getVerificationX509Credentials() {
+			return List.of();
+		}
+
+		@Override
+		public Collection<Saml2X509Credential> getEncryptionX509Credentials() {
+			return List.of();
+		}
+
+		@Override
+		public String getSingleSignOnServiceLocation() {
+			return "";
+		}
+
+		@Override
+		public Saml2MessageBinding getSingleSignOnServiceBinding() {
+			return null;
+		}
+
+		@Override
+		public String getSingleLogoutServiceLocation() {
+			return "";
+		}
+
+		@Override
+		public String getSingleLogoutServiceResponseLocation() {
+			return "";
+		}
+
+		@Override
+		public Saml2MessageBinding getSingleLogoutServiceBinding() {
+			return null;
+		}
+
+		@Override
+		public Builder mutate() {
+			return new Builder();
+		}
+
+		private static class Builder implements AssertingPartyMetadata.Builder<Builder> {
+
+			@Override
+			public Builder entityId(String entityId) {
+				return this;
+			}
+
+			@Override
+			public Builder wantAuthnRequestsSigned(boolean wantAuthnRequestsSigned) {
+				return this;
+			}
+
+			@Override
+			public Builder signingAlgorithms(Consumer<List<String>> signingMethodAlgorithmsConsumer) {
+				return this;
+			}
+
+			@Override
+			public Builder verificationX509Credentials(Consumer<Collection<Saml2X509Credential>> credentialsConsumer) {
+				return this;
+			}
+
+			@Override
+			public Builder encryptionX509Credentials(Consumer<Collection<Saml2X509Credential>> credentialsConsumer) {
+				return this;
+			}
+
+			@Override
+			public Builder singleSignOnServiceLocation(String singleSignOnServiceLocation) {
+				return this;
+			}
+
+			@Override
+			public Builder singleSignOnServiceBinding(Saml2MessageBinding singleSignOnServiceBinding) {
+				return this;
+			}
+
+			@Override
+			public Builder singleLogoutServiceLocation(String singleLogoutServiceLocation) {
+				return this;
+			}
+
+			@Override
+			public Builder singleLogoutServiceResponseLocation(String singleLogoutServiceResponseLocation) {
+				return this;
+			}
+
+			@Override
+			public Builder singleLogoutServiceBinding(Saml2MessageBinding singleLogoutServiceBinding) {
+				return this;
+			}
+
+			@Override
+			public AssertingPartyMetadata build() {
+				return new CustomAssertingPartyMetadata();
+			}
+
+		}
+
+	}
+
 }