فهرست منبع

Use Spec Language in RelyingPartyRegistration

Changed conventions to better follow the metadata descriptors that
the registration is meant to represent.

Closes gh-8777
Josh Cummings 5 سال پیش
والد
کامیت
8e8a642e5a
11فایلهای تغییر یافته به همراه470 افزوده شده و 192 حذف شده
  1. 2 2
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationRequestFactory.java
  2. 1 1
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticationRequestContext.java
  3. 415 148
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistration.java
  4. 1 1
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2ServletUtils.java
  5. 2 2
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2WebSsoAuthenticationFilter.java
  6. 7 7
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2WebSsoAuthenticationRequestFilter.java
  7. 3 3
      saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/DefaultSaml2AuthenticationRequestContextResolver.java
  8. 1 1
      saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationRequestFactoryTests.java
  9. 12 0
      saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistrationTests.java
  10. 14 16
      saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/registration/TestRelyingPartyRegistrations.java
  11. 12 11
      samples/javaconfig/saml2login/src/main/java/org/springframework/security/samples/config/SecurityConfig.java

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

@@ -57,7 +57,7 @@ public class OpenSamlAuthenticationRequestFactory implements Saml2Authentication
 	@Override
 	public Saml2PostAuthenticationRequest createPostAuthenticationRequest(Saml2AuthenticationRequestContext context) {
 		AuthnRequest authnRequest = createAuthnRequest(context);
-		String xml = context.getRelyingPartyRegistration().getProviderDetails().isSignAuthNRequest() ?
+		String xml = context.getRelyingPartyRegistration().getAssertingPartyDetails().getWantAuthnRequestsSigned() ?
 			this.saml.serialize(authnRequest, context.getRelyingPartyRegistration().getSigningCredentials()) :
 			this.saml.serialize(authnRequest);
 
@@ -78,7 +78,7 @@ public class OpenSamlAuthenticationRequestFactory implements Saml2Authentication
 		result.samlRequest(deflatedAndEncoded)
 				.relayState(context.getRelayState());
 
-		if (context.getRelyingPartyRegistration().getProviderDetails().isSignAuthNRequest()) {
+		if (context.getRelyingPartyRegistration().getAssertingPartyDetails().getWantAuthnRequestsSigned()) {
 			List<Saml2X509Credential> signingCredentials = context.getRelyingPartyRegistration().getSigningCredentials();
 			Map<String, String> signedParams = this.saml.signQueryParameters(
 					signingCredentials,

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

@@ -91,7 +91,7 @@ public class Saml2AuthenticationRequestContext {
 	 * @return the Destination value
 	 */
 	public String getDestination() {
-		return this.getRelyingPartyRegistration().getProviderDetails().getWebSsoUrl();
+		return this.getRelyingPartyRegistration().getAssertingPartyDetails().getSingleSignOnServiceLocation();
 	}
 
 	/**

+ 415 - 148
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistration.java

@@ -16,125 +16,178 @@
 
 package org.springframework.security.saml2.provider.service.registration;
 
-import org.springframework.security.saml2.credentials.Saml2X509Credential;
-import org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType;
-import org.springframework.util.Assert;
-
 import java.util.Collection;
+import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.function.Consumer;
 import java.util.function.Function;
 
-import static java.util.Collections.unmodifiableList;
-import static org.springframework.util.Assert.hasText;
-import static org.springframework.util.Assert.notEmpty;
-import static org.springframework.util.Assert.notNull;
+import org.springframework.security.saml2.credentials.Saml2X509Credential;
+import org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType;
+import org.springframework.util.Assert;
 
 /**
- * Represents a configured service provider, SP, and a remote identity provider, IDP, pair.
- * Each SP/IDP pair is uniquely identified using a <code>registrationId</code>, an arbitrary string.
- * A fully configured registration may look like
+ * Represents a configured relying party (aka Service Provider) and asserting party (aka Identity Provider) pair.
+ *
+ * <p>
+ * Each RP/AP pair is uniquely identified using a {@code registrationId}, an arbitrary string.
+ *
+ * <p>
+ * A fully configured registration may look like:
+ *
  * <pre>
- *		//remote IDP entity ID
- *		String idpEntityId = "https://simplesaml-for-spring-saml.cfapps.io/saml2/idp/metadata.php";
- *		//remote WebSSO Endpoint - Where to Send AuthNRequests to
- *		String webSsoEndpoint = "https://simplesaml-for-spring-saml.cfapps.io/saml2/idp/SSOService.php";
- *		//local registration ID
- *		String registrationId = "simplesamlphp";
- *		//local entity ID - autogenerated based on URL
- *		String localEntityIdTemplate = "{baseUrl}/saml2/service-provider-metadata/{registrationId}";
- *		//local SSO URL - autogenerated, endpoint to receive SAML Response objects
- *		String acsUrlTemplate = "{baseUrl}/login/saml2/sso/{registrationId}";
- *		//local signing (and local decryption key and remote encryption certificate)
- *		Saml2X509Credential signingCredential = getSigningCredential();
- *		//IDP certificate for verification of incoming messages
- *		Saml2X509Credential idpVerificationCertificate = getVerificationCertificate();
- *		RelyingPartyRegistration rp = RelyingPartyRegistration.withRegistrationId(registrationId)
- * 				.providerDetails(config -> config.entityId(idpEntityId));
- * 				.providerDetails(config -> config.webSsoUrl(url));
- * 				.credentials(c -> c.add(signingCredential))
- * 				.credentials(c -> c.add(idpVerificationCertificate))
- * 				.localEntityIdTemplate(localEntityIdTemplate)
- * 				.assertionConsumerServiceUrlTemplate(acsUrlTemplate)
- * 				.build();
+ *	String registrationId = "simplesamlphp";
+ *
+ * 	String relyingPartyEntityId = "{baseUrl}/saml2/service-provider-metadata/{registrationId}";
+ *	String assertionConsumerServiceLocation = "{baseUrl}/login/saml2/sso/{registrationId}";
+ *	Saml2X509Credential relyingPartySigningCredential = ...;
+ *
+ *	String assertingPartyEntityId = "https://simplesaml-for-spring-saml.cfapps.io/saml2/idp/metadata.php";
+ *	String singleSignOnServiceLocation = "https://simplesaml-for-spring-saml.cfapps.io/saml2/idp/SSOService.php";
+ * 	Saml2X509Credential assertingPartyVerificationCredential = ...;
+ *
+ *
+ *	RelyingPartyRegistration rp = RelyingPartyRegistration.withRegistrationId(registrationId)
+ * 			.entityId(relyingPartyEntityId)
+ * 			.assertionConsumerServiceLocation(assertingConsumerServiceLocation)
+ * 		 	.credentials(c -> c.add(relyingPartySigningCredential))
+ * 			.assertingPartyDetails(details -> details
+ * 				.entityId(assertingPartyEntityId));
+ * 				.singleSignOnServiceLocation(singleSignOnServiceLocation))
+ * 				.credentials(c -> c.add(assertingPartyVerificationCredential))
+ * 			.build();
  * </pre>
+ *
  * @since 5.2
+ * @author Filip Hanik
+ * @author Josh Cummings
  */
 public class RelyingPartyRegistration {
 
 	private final String registrationId;
-	private final String assertionConsumerServiceUrlTemplate;
-	private final List<Saml2X509Credential> credentials;
-	private final String localEntityIdTemplate;
+	private final String entityId;
+	private final String assertionConsumerServiceLocation;
 	private final ProviderDetails providerDetails;
+	private final List<Saml2X509Credential> credentials;
 
 	private RelyingPartyRegistration(
 			String registrationId,
-			String assertionConsumerServiceUrlTemplate,
+			String entityId,
+			String assertionConsumerServiceLocation,
 			ProviderDetails providerDetails,
-			List<Saml2X509Credential> credentials,
-			String localEntityIdTemplate) {
-		hasText(registrationId, "registrationId cannot be empty");
-		hasText(assertionConsumerServiceUrlTemplate, "assertionConsumerServiceUrlTemplate cannot be empty");
-		hasText(localEntityIdTemplate, "localEntityIdTemplate cannot be empty");
-		notEmpty(credentials, "credentials cannot be empty");
-		notNull(providerDetails, "providerDetails cannot be null");
-		hasText(providerDetails.webSsoUrl, "providerDetails.webSsoUrl cannot be empty");
+			List<Saml2X509Credential> credentials) {
+
+		Assert.hasText(registrationId, "registrationId cannot be empty");
+		Assert.hasText(entityId, "entityId cannot be empty");
+		Assert.hasText(assertionConsumerServiceLocation, "assertionConsumerServiceLocation cannot be empty");
+		Assert.notNull(providerDetails, "providerDetails cannot be null");
+		Assert.notEmpty(credentials, "credentials cannot be empty");
 		for (Saml2X509Credential c : credentials) {
-			notNull(c, "credentials cannot contain null elements");
+			Assert.notNull(c, "credentials cannot contain null elements");
 		}
 		this.registrationId = registrationId;
-		this.assertionConsumerServiceUrlTemplate = assertionConsumerServiceUrlTemplate;
-		this.credentials = unmodifiableList(new LinkedList<>(credentials));
+		this.entityId = entityId;
+		this.assertionConsumerServiceLocation = assertionConsumerServiceLocation;
 		this.providerDetails = providerDetails;
-		this.localEntityIdTemplate = localEntityIdTemplate;
+		this.credentials = Collections.unmodifiableList(new LinkedList<>(credentials));
+	}
+
+	/**
+	 * Get the unique registration id for this RP/AP pair
+	 *
+	 * @return the unique registration id for this RP/AP pair
+	 */
+	public String getRegistrationId() {
+		return this.registrationId;
+	}
+
+	/**
+	 * Get the relying party's
+	 * <a href="https://wiki.shibboleth.net/confluence/display/CONCEPT/EntityNaming">EntityID</a>.
+	 *
+	 * <p>
+	 * Equivalent to the value found in the relying party's
+	 * &lt;EntityDescriptor EntityID="..."/&gt;
+	 *
+	 * <p>
+	 * This value may contain a number of placeholders, which need to be
+	 * resolved before use. They are {@code baseUrl}, {@code registrationId},
+	 * {@code baseScheme}, {@code baseHost}, and {@code basePort}.
+	 *
+	 * @return the relying party's EntityID
+	 * @since 5.4
+	 */
+	public String getEntityId() {
+		return this.entityId;
+	}
+
+	/**
+	 * Get the AssertionConsumerService Location.
+	 * Equivalent to the value found in &lt;AssertionConsumerService Location="..."/&gt;
+	 * in the relying party's &lt;SPSSODescriptor&gt;.
+	 *
+	 * This value may contain a number of placeholders, which need to be
+	 * resolved before use. They are {@code baseUrl}, {@code registrationId},
+	 * {@code baseScheme}, {@code baseHost}, and {@code basePort}.
+	 *
+	 * @return the AssertionConsumerService Location
+	 * @since 5.4
+	 */
+	public String getAssertionConsumerServiceLocation() {
+		return this.assertionConsumerServiceLocation;
+	}
+
+	/**
+	 * Get the configuration details for the Asserting Party
+	 *
+	 * @return the {@link AssertingPartyDetails}
+	 * @since 5.4
+	 */
+	public AssertingPartyDetails getAssertingPartyDetails() {
+		return this.providerDetails.assertingPartyDetails;
 	}
 
 	/**
 	 * Returns the entity ID of the IDP, the asserting party.
 	 * @return entity ID of the asserting party
-	 * @deprecated use {@link ProviderDetails#getEntityId()} from {@link #getProviderDetails()}
+	 * @deprecated use {@link AssertingPartyDetails#getEntityId} from {@link #getAssertingPartyDetails}
 	 */
 	@Deprecated
 	public String getRemoteIdpEntityId() {
 		return this.providerDetails.getEntityId();
 	}
 
-	/**
-	 * Returns the unique relying party registration ID
-	 * @return registrationId
-	 */
-	public String getRegistrationId() {
-		return this.registrationId;
-	}
-
 	/**
 	 * returns the URL template for which ACS URL authentication requests should contain
 	 * Possible variables are {@code baseUrl}, {@code registrationId},
 	 * {@code baseScheme}, {@code baseHost}, and {@code basePort}.
 	 * @return string containing the ACS URL template, with or without variables present
+	 * @deprecated Use {@link #getAssertionConsumerServiceLocation} instead
 	 */
+	@Deprecated
 	public String getAssertionConsumerServiceUrlTemplate() {
-		return this.assertionConsumerServiceUrlTemplate;
+		return this.assertionConsumerServiceLocation;
 	}
 
 	/**
 	 * Contains the URL for which to send the SAML 2 Authentication Request to initiate
 	 * a single sign on flow.
 	 * @return a IDP URL that accepts REDIRECT or POST binding for authentication requests
-	 * @deprecated use {@link ProviderDetails#getWebSsoUrl()} from {@link #getProviderDetails()}
+	 * @deprecated use {@link AssertingPartyDetails#getSingleSignOnServiceLocation} from {@link #getAssertingPartyDetails}
 	 */
 	@Deprecated
 	public String getIdpWebSsoUrl() {
-		return this.getProviderDetails().webSsoUrl;
+		return this.getAssertingPartyDetails().getSingleSignOnServiceLocation();
 	}
 
 	/**
 	 * Returns specific configuration around the Identity Provider SSO endpoint
 	 * @return the IDP SSO endpoint configuration
 	 * @since 5.3
+	 * @deprecated Use {@link #getAssertingPartyDetails} instead
 	 */
+	@Deprecated
 	public ProviderDetails getProviderDetails() {
 		return this.providerDetails;
 	}
@@ -145,9 +198,11 @@ public class RelyingPartyRegistration {
 	 * {@code baseScheme}, {@code baseHost}, and {@code basePort}, for example
 	 * {@code {baseUrl}/saml2/service-provider-metadata/{registrationId}}
 	 * @return a string containing the entity ID or entity ID template
+	 * @deprecated Use {@link #getEntityId} instead
 	 */
+	@Deprecated
 	public String getLocalEntityIdTemplate() {
-		return this.localEntityIdTemplate;
+		return this.entityId;
 	}
 
 	/**
@@ -223,40 +278,196 @@ public class RelyingPartyRegistration {
 	public static Builder withRelyingPartyRegistration(RelyingPartyRegistration registration) {
 		Assert.notNull(registration, "registration cannot be null");
 		return withRegistrationId(registration.getRegistrationId())
-				.providerDetails(c -> {
-					c.webSsoUrl(registration.getProviderDetails().getWebSsoUrl());
-					c.binding(registration.getProviderDetails().getBinding());
-					c.signAuthNRequest(registration.getProviderDetails().isSignAuthNRequest());
-					c.entityId(registration.getProviderDetails().getEntityId());
-				})
-				.credentials(c -> c.addAll(registration.getCredentials()))
-				.localEntityIdTemplate(registration.getLocalEntityIdTemplate())
-				.assertionConsumerServiceUrlTemplate(registration.getAssertionConsumerServiceUrlTemplate())
-				;
+				.entityId(registration.getEntityId())
+				.assertionConsumerServiceLocation(registration.getAssertionConsumerServiceLocation())
+				.assertingPartyDetails(c -> c
+					.entityId(registration.getAssertingPartyDetails().getEntityId())
+					.wantAuthnRequestsSigned(registration.getAssertingPartyDetails().getWantAuthnRequestsSigned())
+					.singleSignOnServiceLocation(registration.getAssertingPartyDetails().getSingleSignOnServiceLocation())
+					.singleSignOnServiceBinding(registration.getAssertingPartyDetails().getSingleSignOnServiceBinding())
+				)
+				.credentials(c -> c.addAll(registration.getCredentials()));
 	}
 
+
 	/**
-	 * Configuration for IDP SSO endpoint configuration
-	 * @since 5.3
+	 * The configuration metadata of the Asserting party
+	 *
+	 * @since 5.4
 	 */
-	public final static class ProviderDetails {
+	public final static class AssertingPartyDetails {
 		private final String entityId;
-		private final String webSsoUrl;
-		private final boolean signAuthNRequest;
-		private final Saml2MessageBinding binding;
+		private final boolean wantAuthnRequestsSigned;
+		private final String singleSignOnServiceLocation;
+		private final Saml2MessageBinding singleSignOnServiceBinding;
 
-		private ProviderDetails(
+		private AssertingPartyDetails(
 				String entityId,
-				String webSsoUrl,
-				boolean signAuthNRequest,
-				Saml2MessageBinding binding) {
-			hasText(entityId, "entityId cannot be null or empty");
-			notNull(webSsoUrl, "webSsoUrl cannot be null");
-			notNull(binding, "binding cannot be null");
+				boolean wantAuthnRequestsSigned,
+				String singleSignOnServiceLocation,
+				Saml2MessageBinding singleSignOnServiceBinding) {
+
+			Assert.hasText(entityId, "entityId cannot be null or empty");
+			Assert.notNull(singleSignOnServiceLocation, "singleSignOnServiceLocation cannot be null");
+			Assert.notNull(singleSignOnServiceBinding, "singleSignOnServiceBinding cannot be null");
 			this.entityId = entityId;
-			this.webSsoUrl = webSsoUrl;
-			this.signAuthNRequest = signAuthNRequest;
-			this.binding = binding;
+			this.wantAuthnRequestsSigned = wantAuthnRequestsSigned;
+			this.singleSignOnServiceLocation = singleSignOnServiceLocation;
+			this.singleSignOnServiceBinding = singleSignOnServiceBinding;
+		}
+
+		/**
+		 * Get the asserting party's
+		 * <a href="https://wiki.shibboleth.net/confluence/display/CONCEPT/EntityNaming">EntityID</a>.
+		 *
+		 * <p>
+		 * Equivalent to the value found in the asserting party's
+		 * &lt;EntityDescriptor EntityID="..."/&gt;
+		 *
+		 * <p>
+		 * This value may contain a number of placeholders, which need to be
+		 * resolved before use. They are {@code baseUrl}, {@code registrationId},
+		 * {@code baseScheme}, {@code baseHost}, and {@code basePort}.
+		 *
+		 * @return the asserting party's EntityID
+		 */
+		public String getEntityId() {
+			return this.entityId;
+		}
+
+		/**
+		 * Get the WantAuthnRequestsSigned setting, indicating the asserting party's preference that
+		 * relying parties should sign the AuthnRequest before sending.
+		 *
+		 * @return the WantAuthnRequestsSigned value
+		 */
+		public boolean getWantAuthnRequestsSigned() {
+			return this.wantAuthnRequestsSigned;
+		}
+
+		/**
+		 * Get the
+		 * <a href="https://wiki.shibboleth.net/confluence/display/CONCEPT/MetadataForIdP#MetadataForIdP-SingleSign-OnServices">SingleSignOnService</a>
+		 * Location.
+		 *
+		 * <p>
+		 * Equivalent to the value found in &lt;SingleSignOnService Location="..."/&gt;
+		 * in the asserting party's &lt;IDPSSODescriptor&gt;.
+		 *
+		 * @return the SingleSignOnService Location
+		 */
+		public String getSingleSignOnServiceLocation() {
+			return this.singleSignOnServiceLocation;
+		}
+
+		/**
+		 * Get the
+		 * <a href="https://wiki.shibboleth.net/confluence/display/CONCEPT/MetadataForIdP#MetadataForIdP-SingleSign-OnServices">SingleSignOnService</a>
+		 * Binding.
+		 *
+		 * <p>
+		 * Equivalent to the value found in &lt;SingleSignOnService Binding="..."/&gt;
+		 * in the asserting party's &lt;IDPSSODescriptor&gt;.
+		 *
+		 * @return the SingleSignOnService Location
+		 */
+		public Saml2MessageBinding getSingleSignOnServiceBinding() {
+			return this.singleSignOnServiceBinding;
+		}
+
+		public final static class Builder {
+			private String entityId;
+			private boolean wantAuthnRequestsSigned = true;
+			private String singleSignOnServiceLocation;
+			private Saml2MessageBinding singleSignOnServiceBinding = Saml2MessageBinding.REDIRECT;
+
+			/**
+			 * Set the asserting party's
+			 * <a href="https://wiki.shibboleth.net/confluence/display/CONCEPT/EntityNaming">EntityID</a>.
+			 * Equivalent to the value found in the asserting party's
+			 * &lt;EntityDescriptor EntityID="..."/&gt;
+			 *
+			 * @param entityId the asserting party's EntityID
+			 * @return the {@link ProviderDetails.Builder} for further configuration
+			 */
+			public Builder entityId(String entityId) {
+				this.entityId = entityId;
+				return this;
+			}
+
+			/**
+			 * Set the WantAuthnRequestsSigned setting, indicating the asserting party's preference that
+			 * relying parties should sign the AuthnRequest before sending.
+			 *
+			 * @param wantAuthnRequestsSigned the WantAuthnRequestsSigned setting
+			 * @return the {@link ProviderDetails.Builder} for further configuration
+			 */
+			public Builder wantAuthnRequestsSigned(boolean wantAuthnRequestsSigned) {
+				this.wantAuthnRequestsSigned = wantAuthnRequestsSigned;
+				return this;
+			}
+
+			/**
+			 * Set the
+			 * <a href="https://wiki.shibboleth.net/confluence/display/CONCEPT/MetadataForIdP#MetadataForIdP-SingleSign-OnServices">SingleSignOnService</a>
+			 * Location.
+			 *
+			 * <p>
+			 * Equivalent to the value found in &lt;SingleSignOnService Location="..."/&gt;
+			 * in the asserting party's &lt;IDPSSODescriptor&gt;.
+			 *
+			 * @param singleSignOnServiceLocation the SingleSignOnService Location
+			 * @return the {@link ProviderDetails.Builder} for further configuration
+			 */
+			public Builder singleSignOnServiceLocation(String singleSignOnServiceLocation) {
+				this.singleSignOnServiceLocation = singleSignOnServiceLocation;
+				return this;
+			}
+
+			/**
+			 * Set the
+			 * <a href="https://wiki.shibboleth.net/confluence/display/CONCEPT/MetadataForIdP#MetadataForIdP-SingleSign-OnServices">SingleSignOnService</a>
+			 * Binding.
+			 *
+			 * <p>
+			 * Equivalent to the value found in &lt;SingleSignOnService Binding="..."/&gt;
+			 * in the asserting party's &lt;IDPSSODescriptor&gt;.
+			 *
+			 * @param singleSignOnServiceBinding the SingleSignOnService Binding
+			 * @return the {@link ProviderDetails.Builder} for further configuration
+			 */
+			public Builder singleSignOnServiceBinding(Saml2MessageBinding singleSignOnServiceBinding) {
+				this.singleSignOnServiceBinding = singleSignOnServiceBinding;
+				return this;
+			}
+
+			/**
+			 * Creates an immutable ProviderDetails object representing the configuration for an Identity Provider, IDP
+			 * @return immutable ProviderDetails object
+			 */
+			public AssertingPartyDetails build() {
+				return new AssertingPartyDetails(
+						this.entityId,
+						this.wantAuthnRequestsSigned,
+						this.singleSignOnServiceLocation,
+						this.singleSignOnServiceBinding
+				);
+			}
+		}
+	}
+
+	/**
+	 * Configuration for IDP SSO endpoint configuration
+	 * @since 5.3
+	 * @deprecated Use {@link AssertingPartyDetails} instead
+	 */
+	@Deprecated
+	public final static class ProviderDetails {
+		private final AssertingPartyDetails assertingPartyDetails;
+
+		private ProviderDetails(AssertingPartyDetails assertingPartyDetails) {
+			Assert.notNull("assertingPartyDetails cannot be null");
+			this.assertingPartyDetails = assertingPartyDetails;
 		}
 
 		/**
@@ -264,7 +475,7 @@ public class RelyingPartyRegistration {
 		 * @return the entity ID of the IDP
 		 */
 		public String getEntityId() {
-			return entityId;
+			return this.assertingPartyDetails.getEntityId();
 		}
 
 		/**
@@ -273,7 +484,7 @@ public class RelyingPartyRegistration {
 		 * @return a IDP URL that accepts REDIRECT or POST binding for authentication requests
 		 */
 		public String getWebSsoUrl() {
-			return webSsoUrl;
+			return this.assertingPartyDetails.getSingleSignOnServiceLocation();
 		}
 
 		/**
@@ -281,34 +492,38 @@ public class RelyingPartyRegistration {
 		 * {@code false} if no signature is required.
 		 */
 		public boolean isSignAuthNRequest() {
-			return signAuthNRequest;
+			return this.assertingPartyDetails.getWantAuthnRequestsSigned();
 		}
 
 		/**
 		 * @return the type of SAML 2 Binding the AuthNRequest should be sent on
 		 */
 		public Saml2MessageBinding getBinding() {
-			return binding;
+			return this.assertingPartyDetails.getSingleSignOnServiceBinding();
 		}
 
 		/**
 		 * Builder for IDP SSO endpoint configuration
 		 * @since 5.3
+		 * @deprecated Use {@link AssertingPartyDetails.Builder} instead
 		 */
+		@Deprecated
 		public final static class Builder {
-			private String entityId;
-			private String webSsoUrl;
-			private boolean signAuthNRequest = true;
-			private Saml2MessageBinding binding = Saml2MessageBinding.REDIRECT;
+			private final AssertingPartyDetails.Builder assertingPartyDetailsBuilder =
+					new AssertingPartyDetails.Builder();
 
 			/**
-			 * Sets the {@code EntityID} for the remote asserting party, the Identity Provider.
+			 * Set the asserting party's
+			 * <a href="https://wiki.shibboleth.net/confluence/display/CONCEPT/EntityNaming">EntityID</a>.
+			 * Equivalent to the value found in the asserting party's
+			 * &lt;EntityDescriptor EntityID="..."/&gt;
 			 *
-			 * @param entityId - the EntityID of the IDP. May be a URL.
-			 * @return this object
+			 * @param entityId the asserting party's EntityID
+			 * @return the {@link Builder} for further configuration
+			 * @since 5.4
 			 */
 			public Builder entityId(String entityId) {
-				this.entityId = entityId;
+				this.assertingPartyDetailsBuilder.entityId(entityId);
 				return this;
 			}
 
@@ -319,7 +534,7 @@ public class RelyingPartyRegistration {
 			 * @return this object
 			 */
 			public Builder webSsoUrl(String url) {
-				this.webSsoUrl = url;
+				this.assertingPartyDetailsBuilder.singleSignOnServiceLocation(url);
 				return this;
 			}
 
@@ -330,7 +545,7 @@ public class RelyingPartyRegistration {
 			 * @return this object
 			 */
 			public Builder signAuthNRequest(boolean signAuthNRequest) {
-				this.signAuthNRequest = signAuthNRequest;
+				this.assertingPartyDetailsBuilder.wantAuthnRequestsSigned(signAuthNRequest);
 				return this;
 			}
 
@@ -342,7 +557,7 @@ public class RelyingPartyRegistration {
 			 * @return this object
 			 */
 			public Builder binding(Saml2MessageBinding binding) {
-				this.binding = binding;
+				this.assertingPartyDetailsBuilder.singleSignOnServiceBinding(binding);
 				return this;
 			}
 
@@ -351,22 +566,17 @@ public class RelyingPartyRegistration {
 			 * @return immutable ProviderDetails object
 			 */
 			public ProviderDetails build() {
-				return new ProviderDetails(
-						this.entityId,
-						this.webSsoUrl,
-						this.signAuthNRequest,
-						this.binding
-				);
+				return new ProviderDetails(this.assertingPartyDetailsBuilder.build());
 			}
 		}
 	}
 
 	public final static class Builder {
 		private String registrationId;
-		private String assertionConsumerServiceUrlTemplate;
-		private List<Saml2X509Credential> credentials = new LinkedList<>();
-		private String localEntityIdTemplate = "{baseUrl}/saml2/service-provider-metadata/{registrationId}";
+		private String entityId = "{baseUrl}/saml2/service-provider-metadata/{registrationId}";
+		private String assertionConsumerServiceLocation;
 		private ProviderDetails.Builder providerDetails = new ProviderDetails.Builder();
+		private List<Saml2X509Credential> credentials = new LinkedList<>();
 
 		private Builder(String registrationId) {
 			this.registrationId = registrationId;
@@ -384,49 +594,54 @@ public class RelyingPartyRegistration {
 		}
 
 		/**
-		 * Sets the {@code entityId} for the remote asserting party, the Identity Provider.
-		 * @param entityId the IDP entityId
-		 * @return this object
-		 * @deprecated use {@link #providerDetails(Consumer< ProviderDetails.Builder >)}
+		 * Set the relying party's
+		 * <a href="https://wiki.shibboleth.net/confluence/display/CONCEPT/EntityNaming">EntityID</a>.
+		 * Equivalent to the value found in the relying party's
+		 * &lt;EntityDescriptor EntityID="..."/&gt;
+		 *
+		 * This value may contain a number of placeholders.
+		 * They are {@code baseUrl}, {@code registrationId},
+		 * {@code baseScheme}, {@code baseHost}, and {@code basePort}.
+		 *
+		 * @return the {@link Builder} for further configuration
+		 * @since 5.4
 		 */
-		@Deprecated
-		public Builder remoteIdpEntityId(String entityId) {
-			this.providerDetails(idp -> idp.entityId(entityId));
+		public Builder entityId(String entityId) {
+			this.entityId = entityId;
 			return this;
 		}
 
 		/**
-		 * <a href="https://wiki.shibboleth.net/confluence/display/CONCEPT/AssertionConsumerService">Assertion Consumer
-		 * Service</a> URL template. It can contain variables {@code baseUrl}, {@code registrationId},
+		 * Set the <a href="https://wiki.shibboleth.net/confluence/display/CONCEPT/AssertionConsumerService">AssertionConsumerService</a>
+		 * Location.
+		 *
+		 * <p>
+		 * Equivalent to the value found in &lt;AssertionConsumerService Location="..."/&gt;
+		 * in the relying party's &lt;SPSSODescriptor&gt;
+		 *
+		 * <p>
+		 * This value may contain a number of placeholders.
+		 * They are {@code baseUrl}, {@code registrationId},
 		 * {@code baseScheme}, {@code baseHost}, and {@code basePort}.
-		 * @param assertionConsumerServiceUrlTemplate the Assertion Consumer Service URL template (i.e.
-		 * "{baseUrl}/login/saml2/sso/{registrationId}".
-		 * @return this object
+		 *
+		 * @param assertionConsumerServiceLocation
+		 * @return the {@link Builder} for further configuration
+		 * @since 5.4
 		 */
-		public Builder assertionConsumerServiceUrlTemplate(String assertionConsumerServiceUrlTemplate) {
-			this.assertionConsumerServiceUrlTemplate = assertionConsumerServiceUrlTemplate;
+		public Builder assertionConsumerServiceLocation(String assertionConsumerServiceLocation) {
+			this.assertionConsumerServiceLocation = assertionConsumerServiceLocation;
 			return this;
 		}
 
 		/**
-		 * Sets the {@code SSO URL} for the remote asserting party, the Identity Provider.
-		 * @param url - a URL that accepts authentication requests via REDIRECT or POST bindings
-		 * @return this object
-		 * @deprecated use {@link #providerDetails(Consumer< ProviderDetails.Builder >)}
+		 * Apply this {@link Consumer} to further configure the Asserting Party details
+		 *
+		 * @param assertingPartyDetails The {@link Consumer} to apply
+		 * @return the {@link Builder} for further configuration
+		 * @since 5.4
 		 */
-		@Deprecated
-		public Builder idpWebSsoUrl(String url) {
-			providerDetails(config -> config.webSsoUrl(url));
-			return this;
-		}
-
-		/**
-		 * Configures the IDP SSO endpoint
-		 * @param providerDetails a consumer that configures the IDP SSO endpoint
-		 * @return this object
-		 */
-		public Builder providerDetails(Consumer<ProviderDetails.Builder> providerDetails) {
-			providerDetails.accept(this.providerDetails);
+		public Builder assertingPartyDetails(Consumer<AssertingPartyDetails.Builder> assertingPartyDetails) {
+			assertingPartyDetails.accept(this.providerDetails.assertingPartyDetailsBuilder);
 			return this;
 		}
 
@@ -449,16 +664,68 @@ public class RelyingPartyRegistration {
 			return this;
 		}
 
+		/**
+		 * <a href="https://wiki.shibboleth.net/confluence/display/CONCEPT/AssertionConsumerService">Assertion Consumer
+		 * Service</a> URL template. It can contain variables {@code baseUrl}, {@code registrationId},
+		 * {@code baseScheme}, {@code baseHost}, and {@code basePort}.
+		 * @param assertionConsumerServiceUrlTemplate the Assertion Consumer Service URL template (i.e.
+		 * "{baseUrl}/login/saml2/sso/{registrationId}".
+		 * @return this object
+		 * @deprecated Use {@link #assertionConsumerServiceLocation} instead.
+		 */
+		@Deprecated
+		public Builder assertionConsumerServiceUrlTemplate(String assertionConsumerServiceUrlTemplate) {
+			this.assertionConsumerServiceLocation = assertionConsumerServiceUrlTemplate;
+			return this;
+		}
+
+		/**
+		 * Sets the {@code entityId} for the remote asserting party, the Identity Provider.
+		 * @param entityId the IDP entityId
+		 * @return this object
+		 * @deprecated use {@link #assertingPartyDetails(Consumer< AssertingPartyDetails.Builder >)}
+		 */
+		@Deprecated
+		public Builder remoteIdpEntityId(String entityId) {
+			assertingPartyDetails(idp -> idp.entityId(entityId));
+			return this;
+		}
+
+		/**
+		 * Sets the {@code SSO URL} for the remote asserting party, the Identity Provider.
+		 * @param url - a URL that accepts authentication requests via REDIRECT or POST bindings
+		 * @return this object
+		 * @deprecated use {@link #assertingPartyDetails(Consumer< AssertingPartyDetails.Builder >)}
+		 */
+		@Deprecated
+		public Builder idpWebSsoUrl(String url) {
+			assertingPartyDetails(config -> config.singleSignOnServiceLocation(url));
+			return this;
+		}
+
 		/**
 		 * Sets the local relying party, or Service Provider, entity Id template.
 		 * can generate it's entity ID based on possible variables of {@code baseUrl}, {@code registrationId},
 		 * {@code baseScheme}, {@code baseHost}, and {@code basePort}, for example
 		 * {@code {baseUrl}/saml2/service-provider-metadata/{registrationId}}
 		 * @return a string containing the entity ID or entity ID template
+		 * @deprecated Use {@link #entityId} instead
 		 */
-
+		@Deprecated
 		public Builder localEntityIdTemplate(String template) {
-			this.localEntityIdTemplate = template;
+			this.entityId = template;
+			return this;
+		}
+
+		/**
+		 * Configures the IDP SSO endpoint
+		 * @param providerDetails a consumer that configures the IDP SSO endpoint
+		 * @return this object
+		 * @deprecated Use {@link #assertingPartyDetails} instead
+		 */
+		@Deprecated
+		public Builder providerDetails(Consumer<ProviderDetails.Builder> providerDetails) {
+			providerDetails.accept(this.providerDetails);
 			return this;
 		}
 
@@ -469,10 +736,10 @@ public class RelyingPartyRegistration {
 		public RelyingPartyRegistration build() {
 			return new RelyingPartyRegistration(
 					this.registrationId,
-					this.assertionConsumerServiceUrlTemplate,
+					this.entityId,
+					this.assertionConsumerServiceLocation,
 					this.providerDetails.build(),
-					this.credentials,
-					this.localEntityIdTemplate
+					this.credentials
 			);
 		}
 	}

+ 1 - 1
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2ServletUtils.java

@@ -40,7 +40,7 @@ final class Saml2ServletUtils {
 			return baseUrl;
 		}
 
-		String entityId = relyingParty.getProviderDetails().getEntityId();
+		String entityId = relyingParty.getAssertingPartyDetails().getEntityId();
 		String registrationId = relyingParty.getRegistrationId();
 		Map<String, String> uriVariables = new HashMap<>();
 		UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl(baseUrl)

+ 2 - 2
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2WebSsoAuthenticationFilter.java

@@ -98,11 +98,11 @@ public class Saml2WebSsoAuthenticationFilter extends AbstractAuthenticationProce
 			throw new Saml2AuthenticationException(saml2Error);
 		}
 		String applicationUri = Saml2ServletUtils.getApplicationUri(request);
-		String localSpEntityId = Saml2ServletUtils.resolveUrlTemplate(rp.getLocalEntityIdTemplate(), applicationUri, rp);
+		String localSpEntityId = Saml2ServletUtils.resolveUrlTemplate(rp.getEntityId(), applicationUri, rp);
 		final Saml2AuthenticationToken authentication = new Saml2AuthenticationToken(
 				responseXml,
 				request.getRequestURL().toString(),
-				rp.getProviderDetails().getEntityId(),
+				rp.getAssertingPartyDetails().getEntityId(),
 				localSpEntityId,
 				rp.getCredentials()
 		);

+ 7 - 7
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/servlet/filter/Saml2WebSsoAuthenticationRequestFilter.java

@@ -16,6 +16,12 @@
 
 package org.springframework.security.saml2.provider.service.servlet.filter;
 
+import java.io.IOException;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
 import org.springframework.http.MediaType;
 import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationRequestContext;
 import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationRequestFactory;
@@ -36,12 +42,6 @@ import org.springframework.web.util.HtmlUtils;
 import org.springframework.web.util.UriComponentsBuilder;
 import org.springframework.web.util.UriUtils;
 
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-
 import static java.nio.charset.StandardCharsets.ISO_8859_1;
 
 /**
@@ -155,7 +155,7 @@ public class Saml2WebSsoAuthenticationRequestFilter extends OncePerRequestFilter
 			return;
 		}
 		Saml2AuthenticationRequestContext context = authenticationRequestContextResolver.resolve(request, relyingParty);
-		if (relyingParty.getProviderDetails().getBinding() == Saml2MessageBinding.REDIRECT) {
+		if (relyingParty.getAssertingPartyDetails().getSingleSignOnServiceBinding() == Saml2MessageBinding.REDIRECT) {
 			sendRedirect(response, context);
 		} else {
 			sendPost(response, context);

+ 3 - 3
saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/DefaultSaml2AuthenticationRequestContextResolver.java

@@ -67,8 +67,8 @@ public final class DefaultSaml2AuthenticationRequestContextResolver implements S
 
 		String applicationUri = getApplicationUri(request);
 		Function<String, String> resolver = templateResolver(applicationUri, relyingParty);
-		String localSpEntityId = resolver.apply(relyingParty.getLocalEntityIdTemplate());
-		String assertionConsumerServiceUrl = resolver.apply(relyingParty.getAssertionConsumerServiceUrlTemplate());
+		String localSpEntityId = resolver.apply(relyingParty.getEntityId());
+		String assertionConsumerServiceUrl = resolver.apply(relyingParty.getAssertionConsumerServiceLocation());
 		return Saml2AuthenticationRequestContext.builder()
 				.issuer(localSpEntityId)
 				.relyingPartyRegistration(relyingParty)
@@ -82,7 +82,7 @@ public final class DefaultSaml2AuthenticationRequestContextResolver implements S
 	}
 
 	private static String resolveUrlTemplate(String template, String baseUrl, RelyingPartyRegistration relyingParty) {
-		String entityId = relyingParty.getProviderDetails().getEntityId();
+		String entityId = relyingParty.getAssertingPartyDetails().getEntityId();
 		String registrationId = relyingParty.getRegistrationId();
 		Map<String, String> uriVariables = new HashMap<>();
 		UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl(baseUrl)

+ 1 - 1
saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationRequestFactoryTests.java

@@ -52,7 +52,7 @@ public class OpenSamlAuthenticationRequestFactoryTests {
 	@Before
 	public void setUp() {
 		relyingPartyRegistration = RelyingPartyRegistration.withRegistrationId("id")
-				.assertionConsumerServiceUrlTemplate("template")
+				.assertionConsumerServiceLocation("template")
 				.providerDetails(c -> c.webSsoUrl("https://destination/sso"))
 				.providerDetails(c -> c.entityId("remote-entity-id"))
 				.localEntityIdTemplate("local-entity-id")

+ 12 - 0
saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistrationTests.java

@@ -42,9 +42,13 @@ public class RelyingPartyRegistrationTests {
 				.isEqualTo("simplesamlphp");
 		assertThat(copy.getProviderDetails().getEntityId())
 				.isEqualTo(registration.getProviderDetails().getEntityId())
+				.isEqualTo(copy.getAssertingPartyDetails().getEntityId())
+				.isEqualTo(registration.getAssertingPartyDetails().getEntityId())
 				.isEqualTo("https://simplesaml-for-spring-saml.cfapps.io/saml2/idp/metadata.php");
 		assertThat(copy.getAssertionConsumerServiceUrlTemplate())
 				.isEqualTo(registration.getAssertionConsumerServiceUrlTemplate())
+				.isEqualTo(copy.getAssertionConsumerServiceLocation())
+				.isEqualTo(registration.getAssertionConsumerServiceLocation())
 				.isEqualTo("{baseUrl}" + Saml2WebSsoAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI);
 		assertThat(copy.getCredentials())
 				.containsAll(registration.getCredentials())
@@ -54,15 +58,23 @@ public class RelyingPartyRegistrationTests {
 				);
 		assertThat(copy.getLocalEntityIdTemplate())
 				.isEqualTo(registration.getLocalEntityIdTemplate())
+				.isEqualTo(copy.getEntityId())
+				.isEqualTo(registration.getEntityId())
 				.isEqualTo("{baseUrl}/saml2/service-provider-metadata/{registrationId}");
 		assertThat(copy.getProviderDetails().getWebSsoUrl())
 				.isEqualTo(registration.getProviderDetails().getWebSsoUrl())
+				.isEqualTo(copy.getAssertingPartyDetails().getSingleSignOnServiceLocation())
+				.isEqualTo(registration.getAssertingPartyDetails().getSingleSignOnServiceLocation())
 				.isEqualTo("https://simplesaml-for-spring-saml.cfapps.io/saml2/idp/SSOService.php");
 		assertThat(copy.getProviderDetails().getBinding())
 				.isEqualTo(registration.getProviderDetails().getBinding())
+				.isEqualTo(copy.getAssertingPartyDetails().getSingleSignOnServiceBinding())
+				.isEqualTo(registration.getAssertingPartyDetails().getSingleSignOnServiceBinding())
 				.isEqualTo(POST);
 		assertThat(copy.getProviderDetails().isSignAuthNRequest())
 				.isEqualTo(registration.getProviderDetails().isSignAuthNRequest())
+				.isEqualTo(copy.getAssertingPartyDetails().getWantAuthnRequestsSigned())
+				.isEqualTo(registration.getAssertingPartyDetails().getWantAuthnRequestsSigned())
 				.isFalse();
 	}
 }

+ 14 - 16
saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/registration/TestRelyingPartyRegistrations.java

@@ -28,26 +28,24 @@ import static org.springframework.security.saml2.credentials.TestSaml2X509Creden
 public class TestRelyingPartyRegistrations {
 
 	public static RelyingPartyRegistration.Builder relyingPartyRegistration() {
-		//remote IDP entity ID
-		String idpEntityId = "https://simplesaml-for-spring-saml.cfapps.io/saml2/idp/metadata.php";
-		//remote WebSSO Endpoint - Where to Send AuthNRequests to
-		String webSsoEndpoint = "https://simplesaml-for-spring-saml.cfapps.io/saml2/idp/SSOService.php";
-		//local registration ID
 		String registrationId = "simplesamlphp";
-		//local entity ID - autogenerated based on URL
-		String localEntityIdTemplate = "{baseUrl}/saml2/service-provider-metadata/{registrationId}";
-		//local signing (and decryption key)
+
+		String rpEntityId = "{baseUrl}/saml2/service-provider-metadata/{registrationId}";
 		Saml2X509Credential signingCredential = relyingPartySigningCredential();
-		//IDP certificate for verification of incoming messages
-		Saml2X509Credential idpVerificationCertificate = relyingPartyVerifyingCredential();
-		String acsUrlTemplate = "{baseUrl}" + Saml2WebSsoAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI;
+		String assertionConsumerServiceLocation = "{baseUrl}" + Saml2WebSsoAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI;
+
+		String apEntityId = "https://simplesaml-for-spring-saml.cfapps.io/saml2/idp/metadata.php";
+		Saml2X509Credential verificationCertificate = relyingPartyVerifyingCredential();
+		String singleSignOnServiceLocation = "https://simplesaml-for-spring-saml.cfapps.io/saml2/idp/SSOService.php";
+
 		return RelyingPartyRegistration.withRegistrationId(registrationId)
-				.providerDetails(c -> c.entityId(idpEntityId))
-				.providerDetails(c -> c.webSsoUrl(webSsoEndpoint))
+				.entityId(rpEntityId)
+				.assertionConsumerServiceLocation(assertionConsumerServiceLocation)
 				.credentials(c -> c.add(signingCredential))
-				.credentials(c -> c.add(idpVerificationCertificate))
-				.localEntityIdTemplate(localEntityIdTemplate)
-				.assertionConsumerServiceUrlTemplate(acsUrlTemplate);
+				.providerDetails(c -> c
+						.entityId(apEntityId)
+						.webSsoUrl(singleSignOnServiceLocation))
+						.credentials(c -> c.add(verificationCertificate));
 	}
 
 

+ 12 - 11
samples/javaconfig/saml2login/src/main/java/org/springframework/security/samples/config/SecurityConfig.java

@@ -15,6 +15,12 @@
  */
 package org.springframework.security.samples.config;
 
+import java.io.ByteArrayInputStream;
+import java.nio.charset.StandardCharsets;
+import java.security.PrivateKey;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+
 import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
@@ -25,12 +31,6 @@ import org.springframework.security.saml2.provider.service.registration.InMemory
 import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
 import org.springframework.security.saml2.provider.service.servlet.filter.Saml2WebSsoAuthenticationFilter;
 
-import java.io.ByteArrayInputStream;
-import java.nio.charset.StandardCharsets;
-import java.security.PrivateKey;
-import java.security.cert.CertificateFactory;
-import java.security.cert.X509Certificate;
-
 import static org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType.DECRYPTION;
 import static org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType.SIGNING;
 import static org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType.VERIFICATION;
@@ -54,12 +54,13 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
 		Saml2X509Credential idpVerificationCertificate = getVerificationCertificate();
 		String acsUrlTemplate = "{baseUrl}" + Saml2WebSsoAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI;
 		return RelyingPartyRegistration.withRegistrationId(registrationId)
-				.providerDetails(config -> config.entityId(idpEntityId))
-				.providerDetails(config -> config.webSsoUrl(webSsoEndpoint))
+				.entityId(localEntityIdTemplate)
+				.assertionConsumerServiceLocation(acsUrlTemplate)
 				.credentials(c -> c.add(signingCredential))
-				.credentials(c -> c.add(idpVerificationCertificate))
-				.localEntityIdTemplate(localEntityIdTemplate)
-				.assertionConsumerServiceUrlTemplate(acsUrlTemplate)
+				.assertingPartyDetails(config -> config
+						.entityId(idpEntityId)
+						.singleSignOnServiceLocation(webSsoEndpoint))
+						.credentials(c -> c.add(idpVerificationCertificate))
 				.build();
 	}