Use AssertingPartyMetadata
Issue gh-15394
This commit is contained in:
@@ -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)) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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"));
|
||||
}
|
||||
|
||||
@@ -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"));
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 : "");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,16 @@ 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()))
|
||||
@@ -192,4 +198,160 @@ public class RelyingPartyRegistrationTests {
|
||||
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()))
|
||||
.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);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user