From f5a525e740db864ea0f49cda1fad34e4f5880b20 Mon Sep 17 00:00:00 2001 From: Josh Cummings Date: Tue, 2 Mar 2021 07:54:18 -0700 Subject: [PATCH] Add Registration to Saml2Authentication Closes gh-9487 --- .../_includes/servlet/saml2/saml2-login.adoc | 6 ++++++ .../DefaultSaml2AuthenticatedPrincipal.java | 13 +++++++++++++ .../authentication/Saml2AuthenticatedPrincipal.java | 10 ++++++++++ .../service/authentication/Saml2Authentication.java | 6 ++++++ .../OpenSamlAuthenticationProvider.java | 13 +++++++++---- .../OpenSaml4AuthenticationProvider.java | 7 +++++-- 6 files changed, 49 insertions(+), 6 deletions(-) diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/saml2/saml2-login.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/saml2/saml2-login.adoc index 2a95f546bc..303351fb79 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/saml2/saml2-login.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/saml2/saml2-login.adoc @@ -107,6 +107,7 @@ where * `https://idp.example.com/issuer` is the value contained in the `Issuer` attribute of the SAML responses that the identity provider will issue * `classpath:idp.crt` is the location on the classpath for the identity provider's certificate for verifying SAML responses, and * `https://idp.example.com/issuer/sso` is the endpoint where the identity provider is expecting `AuthnRequest` s. +* `adfs` is <> And that's it! @@ -196,6 +197,7 @@ image:{icondir}/number_10.png[] And finally, it takes the `NameID` from the firs Then, it places that principal and the authorities into a `Saml2Authentication`. The resulting `Authentication#getPrincipal` is a Spring Security `Saml2AuthenticatedPrincipal` object, and `Authentication#getName` maps to the first assertion's `NameID` element. +`Saml2AuthenticatedPrincipal#getRelyingPartyRegistrationId` holds the <>. [[servlet-saml2login-opensaml-customization]] ==== Customizing OpenSAML Configuration @@ -410,6 +412,10 @@ open fun relyingPartyRegistrations(): RelyingPartyRegistrationRepository? { ---- ==== +[[servlet-saml2login-relyingpartyregistrationid]] +[NOTE] +The `registrationId` is an arbitrary value that you choose for differentiating between registrations. + Or you can provide each detail manually, as you can see below: .Relying Party Registration Repository Manual Configuration diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/DefaultSaml2AuthenticatedPrincipal.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/DefaultSaml2AuthenticatedPrincipal.java index 8e1ac9270b..22c12e1ebf 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/DefaultSaml2AuthenticatedPrincipal.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/DefaultSaml2AuthenticatedPrincipal.java @@ -34,11 +34,14 @@ public class DefaultSaml2AuthenticatedPrincipal implements Saml2AuthenticatedPri private final Map> attributes; + private String registrationId; + public DefaultSaml2AuthenticatedPrincipal(String name, Map> attributes) { Assert.notNull(name, "name cannot be null"); Assert.notNull(attributes, "attributes cannot be null"); this.name = name; this.attributes = attributes; + this.registrationId = null; } @Override @@ -51,4 +54,14 @@ public class DefaultSaml2AuthenticatedPrincipal implements Saml2AuthenticatedPri return this.attributes; } + @Override + public String getRelyingPartyRegistrationId() { + return this.registrationId; + } + + public void setRelyingPartyRegistrationId(String registrationId) { + Assert.notNull(registrationId, "relyingPartyRegistrationId cannot be null"); + this.registrationId = registrationId; + } + } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticatedPrincipal.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticatedPrincipal.java index 5996b0a4c5..c40015f94f 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticatedPrincipal.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2AuthenticatedPrincipal.java @@ -22,6 +22,7 @@ import java.util.Map; import org.springframework.lang.Nullable; import org.springframework.security.core.AuthenticatedPrincipal; +import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration; import org.springframework.util.CollectionUtils; /** @@ -66,4 +67,13 @@ public interface Saml2AuthenticatedPrincipal extends AuthenticatedPrincipal { return Collections.emptyMap(); } + /** + * Get the {@link RelyingPartyRegistration} identifier + * @return the {@link RelyingPartyRegistration} identifier + * @since 5.6 + */ + default String getRelyingPartyRegistrationId() { + return null; + } + } diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2Authentication.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2Authentication.java index d37792456b..d32c1f4469 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2Authentication.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/Saml2Authentication.java @@ -41,6 +41,12 @@ public class Saml2Authentication extends AbstractAuthenticationToken { private final String saml2Response; + /** + * Construct a {@link Saml2Authentication} using the provided parameters + * @param principal the logged in user + * @param saml2Response the SAML 2.0 response used to authenticate the user + * @param authorities the authorities for the logged in user + */ public Saml2Authentication(AuthenticatedPrincipal principal, String saml2Response, Collection authorities) { super(authorities); diff --git a/saml2/saml2-service-provider/src/opensaml3Main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationProvider.java b/saml2/saml2-service-provider/src/opensaml3Main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationProvider.java index e8531b1d39..18ec5f77eb 100644 --- a/saml2/saml2-service-provider/src/opensaml3Main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationProvider.java +++ b/saml2/saml2-service-provider/src/opensaml3Main/java/org/springframework/security/saml2/provider/service/authentication/OpenSamlAuthenticationProvider.java @@ -424,8 +424,11 @@ public final class OpenSamlAuthenticationProvider implements AuthenticationProvi Assertion assertion = CollectionUtils.firstElement(response.getAssertions()); String username = assertion.getSubject().getNameID().getValue(); Map> attributes = getAssertionAttributes(assertion); - return new Saml2Authentication(new DefaultSaml2AuthenticatedPrincipal(username, attributes), - token.getSaml2Response(), Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"))); + DefaultSaml2AuthenticatedPrincipal principal = new DefaultSaml2AuthenticatedPrincipal(username, attributes); + String registrationId = responseToken.token.getRelyingPartyRegistration().getRegistrationId(); + principal.setRelyingPartyRegistrationId(registrationId); + return new Saml2Authentication(principal, token.getSaml2Response(), + Collections.singleton(new SimpleGrantedAuthority("ROLE_USER"))); }; } @@ -626,8 +629,10 @@ public final class OpenSamlAuthenticationProvider implements AuthenticationProvi Assertion assertion = CollectionUtils.firstElement(response.getAssertions()); String username = assertion.getSubject().getNameID().getValue(); Map> attributes = getAssertionAttributes(assertion); - return new Saml2Authentication(new DefaultSaml2AuthenticatedPrincipal(username, attributes), - token.getSaml2Response(), + DefaultSaml2AuthenticatedPrincipal principal = new DefaultSaml2AuthenticatedPrincipal(username, attributes); + String registrationId = responseToken.token.getRelyingPartyRegistration().getRegistrationId(); + principal.setRelyingPartyRegistrationId(registrationId); + return new Saml2Authentication(principal, token.getSaml2Response(), this.authoritiesMapper.mapAuthorities(getAssertionAuthorities(assertion))); }; } diff --git a/saml2/saml2-service-provider/src/opensaml4Main/java/org/springframework/security/saml2/provider/service/authentication/OpenSaml4AuthenticationProvider.java b/saml2/saml2-service-provider/src/opensaml4Main/java/org/springframework/security/saml2/provider/service/authentication/OpenSaml4AuthenticationProvider.java index 74f5cde0d6..d83830e593 100644 --- a/saml2/saml2-service-provider/src/opensaml4Main/java/org/springframework/security/saml2/provider/service/authentication/OpenSaml4AuthenticationProvider.java +++ b/saml2/saml2-service-provider/src/opensaml4Main/java/org/springframework/security/saml2/provider/service/authentication/OpenSaml4AuthenticationProvider.java @@ -425,8 +425,11 @@ public final class OpenSaml4AuthenticationProvider implements AuthenticationProv Assertion assertion = CollectionUtils.firstElement(response.getAssertions()); String username = assertion.getSubject().getNameID().getValue(); Map> attributes = getAssertionAttributes(assertion); - return new Saml2Authentication(new DefaultSaml2AuthenticatedPrincipal(username, attributes), - token.getSaml2Response(), AuthorityUtils.createAuthorityList("ROLE_USER")); + DefaultSaml2AuthenticatedPrincipal principal = new DefaultSaml2AuthenticatedPrincipal(username, attributes); + String registrationId = responseToken.token.getRelyingPartyRegistration().getRegistrationId(); + principal.setRelyingPartyRegistrationId(registrationId); + return new Saml2Authentication(principal, token.getSaml2Response(), + AuthorityUtils.createAuthorityList("ROLE_USER")); }; }