From a106188addb401303827ba747b507d41359f1bae Mon Sep 17 00:00:00 2001 From: Tatiana Slednikova Date: Sun, 12 Mar 2023 04:06:21 +0300 Subject: [PATCH] Add nameIdFormat processing to OpenSamlAuthenticationRequestResolver Closes gh-12825 --- .../OpenSamlAuthenticationRequestResolver.java | 14 +++++++++++++- .../TestRelyingPartyRegistrations.java | 4 ++-- ...OpenSamlAuthenticationRequestResolverTests.java | 6 +++++- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/OpenSamlAuthenticationRequestResolver.java b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/OpenSamlAuthenticationRequestResolver.java index 2cd7a230649..020c182643b 100644 --- a/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/OpenSamlAuthenticationRequestResolver.java +++ b/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/OpenSamlAuthenticationRequestResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,10 +31,12 @@ import org.opensaml.saml.saml2.core.AuthnRequest; import org.opensaml.saml.saml2.core.Issuer; import org.opensaml.saml.saml2.core.NameID; +import org.opensaml.saml.saml2.core.NameIDPolicy; import org.opensaml.saml.saml2.core.impl.AuthnRequestBuilder; import org.opensaml.saml.saml2.core.impl.AuthnRequestMarshaller; import org.opensaml.saml.saml2.core.impl.IssuerBuilder; import org.opensaml.saml.saml2.core.impl.NameIDBuilder; +import org.opensaml.saml.saml2.core.impl.NameIDPolicyBuilder; import org.w3c.dom.Element; import org.springframework.security.saml2.Saml2Exception; @@ -72,6 +74,8 @@ class OpenSamlAuthenticationRequestResolver { private final NameIDBuilder nameIdBuilder; + private final NameIDPolicyBuilder nameIdPolicyBuilder; + /** * Construct a {@link OpenSamlAuthenticationRequestResolver} using the provided * parameters @@ -92,6 +96,9 @@ class OpenSamlAuthenticationRequestResolver { Assert.notNull(this.issuerBuilder, "issuerBuilder must be configured in OpenSAML"); this.nameIdBuilder = (NameIDBuilder) registry.getBuilderFactory().getBuilder(NameID.DEFAULT_ELEMENT_NAME); Assert.notNull(this.nameIdBuilder, "nameIdBuilder must be configured in OpenSAML"); + this.nameIdPolicyBuilder = (NameIDPolicyBuilder) registry.getBuilderFactory() + .getBuilder(NameIDPolicy.DEFAULT_ELEMENT_NAME); + Assert.notNull(this.nameIdPolicyBuilder, "nameIdPolicyBuilder must be configured in OpenSAML"); } T resolve(HttpServletRequest request) { @@ -119,6 +126,11 @@ T resolve(HttpServletRequest requ authnRequest.setIssuer(iss); authnRequest.setDestination(registration.getAssertingPartyDetails().getSingleSignOnServiceLocation()); authnRequest.setAssertionConsumerServiceURL(registration.getAssertionConsumerServiceLocation()); + if (registration.getNameIdFormat() != null) { + NameIDPolicy nameIdPolicy = this.nameIdPolicyBuilder.buildObject(); + nameIdPolicy.setFormat(registration.getNameIdFormat()); + authnRequest.setNameIDPolicy(nameIdPolicy); + } authnRequestConsumer.accept(registration, authnRequest); if (authnRequest.getID() == null) { authnRequest.setID("ARQ" + UUID.randomUUID().toString().substring(1)); diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/registration/TestRelyingPartyRegistrations.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/registration/TestRelyingPartyRegistrations.java index c5626821fc7..54f1502bd99 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/registration/TestRelyingPartyRegistrations.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/registration/TestRelyingPartyRegistrations.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,7 +38,7 @@ public static RelyingPartyRegistration.Builder relyingPartyRegistration() { Saml2X509Credential verificationCertificate = TestSaml2X509Credentials.relyingPartyVerifyingCredential(); String singleSignOnServiceLocation = "https://simplesaml-for-spring-saml.apps.pcfone.io/saml2/idp/SSOService.php"; String singleLogoutServiceLocation = "{baseUrl}/logout/saml2/slo"; - return RelyingPartyRegistration.withRegistrationId(registrationId).entityId(rpEntityId) + return RelyingPartyRegistration.withRegistrationId(registrationId).entityId(rpEntityId).nameIdFormat("format") .assertionConsumerServiceLocation(assertionConsumerServiceLocation) .singleLogoutServiceLocation(singleLogoutServiceLocation).credentials((c) -> c.add(signingCredential)) .providerDetails((c) -> c.entityId(apEntityId).webSsoUrl(singleSignOnServiceLocation)) diff --git a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/OpenSamlAuthenticationRequestResolverTests.java b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/OpenSamlAuthenticationRequestResolverTests.java index b81e991b83c..7f32ec81427 100644 --- a/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/OpenSamlAuthenticationRequestResolverTests.java +++ b/saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/web/authentication/OpenSamlAuthenticationRequestResolverTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -52,6 +52,7 @@ public void resolveAuthenticationRequestWhenSignedRedirectThenSignsAndRedirects( RelyingPartyRegistration registration = this.relyingPartyRegistrationBuilder.build(); OpenSamlAuthenticationRequestResolver resolver = authenticationRequestResolver(registration); Saml2RedirectAuthenticationRequest result = resolver.resolve(request, (r, authnRequest) -> { + assertThat(authnRequest.getNameIDPolicy().getFormat()).isEqualTo(registration.getNameIdFormat()); assertThat(authnRequest.getAssertionConsumerServiceURL()) .isEqualTo(registration.getAssertionConsumerServiceLocation()); assertThat(authnRequest.getProtocolBinding()) @@ -75,6 +76,7 @@ public void resolveAuthenticationRequestWhenUnsignedRedirectThenRedirectsAndNoSi .assertingPartyDetails((party) -> party.wantAuthnRequestsSigned(false)).build(); OpenSamlAuthenticationRequestResolver resolver = authenticationRequestResolver(registration); Saml2RedirectAuthenticationRequest result = resolver.resolve(request, (r, authnRequest) -> { + assertThat(authnRequest.getNameIDPolicy().getFormat()).isEqualTo(registration.getNameIdFormat()); assertThat(authnRequest.getAssertionConsumerServiceURL()) .isEqualTo(registration.getAssertionConsumerServiceLocation()); assertThat(authnRequest.getProtocolBinding()) @@ -110,6 +112,7 @@ public void resolveAuthenticationRequestWhenUnsignedPostThenOnlyPosts() { .build(); OpenSamlAuthenticationRequestResolver resolver = authenticationRequestResolver(registration); Saml2PostAuthenticationRequest result = resolver.resolve(request, (r, authnRequest) -> { + assertThat(authnRequest.getNameIDPolicy().getFormat()).isEqualTo(registration.getNameIdFormat()); assertThat(authnRequest.getAssertionConsumerServiceURL()) .isEqualTo(registration.getAssertionConsumerServiceLocation()); assertThat(authnRequest.getProtocolBinding()) @@ -132,6 +135,7 @@ public void resolveAuthenticationRequestWhenSignedPostThenSignsAndPosts() { .assertingPartyDetails((party) -> party.singleSignOnServiceBinding(Saml2MessageBinding.POST)).build(); OpenSamlAuthenticationRequestResolver resolver = authenticationRequestResolver(registration); Saml2PostAuthenticationRequest result = resolver.resolve(request, (r, authnRequest) -> { + assertThat(authnRequest.getNameIDPolicy().getFormat()).isEqualTo(registration.getNameIdFormat()); assertThat(authnRequest.getAssertionConsumerServiceURL()) .isEqualTo(registration.getAssertionConsumerServiceLocation()); assertThat(authnRequest.getProtocolBinding())