mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-06-22 03:52:15 +00:00
Add AssertingPartyMetadataRepository
Closes gh-15394
This commit is contained in:
parent
437a45768c
commit
7ad9ee93cf
@ -0,0 +1,276 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2002-2024 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.security.saml2.provider.service.registration;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.springframework.security.saml2.core.Saml2X509Credential;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface representing SAML 2.0 Asserting Party metadata
|
||||||
|
*
|
||||||
|
* @author Josh Cummings
|
||||||
|
* @since 6.4
|
||||||
|
*/
|
||||||
|
public interface AssertingPartyMetadata {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the asserting party's <a href=
|
||||||
|
* "https://www.oasis-open.org/committees/download.php/51890/SAML%20MD%20simplified%20overview.pdf#2.9%20EntityDescriptor">EntityID</a>.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Equivalent to the value found in the asserting party's <EntityDescriptor
|
||||||
|
* EntityID="..."/>
|
||||||
|
*
|
||||||
|
* <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
|
||||||
|
*/
|
||||||
|
String getEntityId();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the WantAuthnRequestsSigned setting, indicating the asserting party's
|
||||||
|
* preference that relying parties should sign the AuthnRequest before sending.
|
||||||
|
* @return the WantAuthnRequestsSigned value
|
||||||
|
*/
|
||||||
|
boolean getWantAuthnRequestsSigned();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of org.opensaml.saml.ext.saml2alg.SigningMethod Algorithms for this
|
||||||
|
* asserting party, in preference order.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Equivalent to the values found in <SigningMethod Algorithm="..."/> in the
|
||||||
|
* asserting party's <IDPSSODescriptor>.
|
||||||
|
* @return the list of SigningMethod Algorithms
|
||||||
|
* @since 5.5
|
||||||
|
*/
|
||||||
|
List<String> getSigningAlgorithms();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all verification {@link Saml2X509Credential}s associated with this asserting
|
||||||
|
* party
|
||||||
|
* @return all verification {@link Saml2X509Credential}s associated with this
|
||||||
|
* asserting party
|
||||||
|
* @since 5.4
|
||||||
|
*/
|
||||||
|
Collection<Saml2X509Credential> getVerificationX509Credentials();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all encryption {@link Saml2X509Credential}s associated with this asserting
|
||||||
|
* party
|
||||||
|
* @return all encryption {@link Saml2X509Credential}s associated with this asserting
|
||||||
|
* party
|
||||||
|
* @since 5.4
|
||||||
|
*/
|
||||||
|
Collection<Saml2X509Credential> getEncryptionX509Credentials();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the <a href=
|
||||||
|
* "https://www.oasis-open.org/committees/download.php/51890/SAML%20MD%20simplified%20overview.pdf#2.5%20Endpoint">SingleSignOnService</a>
|
||||||
|
* Location.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Equivalent to the value found in <SingleSignOnService Location="..."/> in the
|
||||||
|
* asserting party's <IDPSSODescriptor>.
|
||||||
|
* @return the SingleSignOnService Location
|
||||||
|
*/
|
||||||
|
String getSingleSignOnServiceLocation();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the <a href=
|
||||||
|
* "https://www.oasis-open.org/committees/download.php/51890/SAML%20MD%20simplified%20overview.pdf#2.5%20Endpoint">SingleSignOnService</a>
|
||||||
|
* Binding.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Equivalent to the value found in <SingleSignOnService Binding="..."/> in the
|
||||||
|
* asserting party's <IDPSSODescriptor>.
|
||||||
|
* @return the SingleSignOnService Location
|
||||||
|
*/
|
||||||
|
Saml2MessageBinding getSingleSignOnServiceBinding();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the <a href=
|
||||||
|
* "https://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf#page=7">SingleLogoutService
|
||||||
|
* Location</a>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Equivalent to the value found in <SingleLogoutService Location="..."/> in the
|
||||||
|
* asserting party's <IDPSSODescriptor>.
|
||||||
|
* @return the SingleLogoutService Location
|
||||||
|
* @since 5.6
|
||||||
|
*/
|
||||||
|
String getSingleLogoutServiceLocation();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the <a href=
|
||||||
|
* "https://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf#page=7">SingleLogoutService
|
||||||
|
* Response Location</a>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Equivalent to the value found in <SingleLogoutService Location="..."/> in the
|
||||||
|
* asserting party's <IDPSSODescriptor>.
|
||||||
|
* @return the SingleLogoutService Response Location
|
||||||
|
* @since 5.6
|
||||||
|
*/
|
||||||
|
String getSingleLogoutServiceResponseLocation();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the <a href=
|
||||||
|
* "https://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf#page=7">SingleLogoutService
|
||||||
|
* Binding</a>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Equivalent to the value found in <SingleLogoutService Binding="..."/> in the
|
||||||
|
* asserting party's <IDPSSODescriptor>.
|
||||||
|
* @return the SingleLogoutService Binding
|
||||||
|
* @since 5.6
|
||||||
|
*/
|
||||||
|
Saml2MessageBinding getSingleLogoutServiceBinding();
|
||||||
|
|
||||||
|
Builder<?> mutate();
|
||||||
|
|
||||||
|
interface Builder<B extends Builder<B>> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the asserting party's <a href=
|
||||||
|
* "https://www.oasis-open.org/committees/download.php/51890/SAML%20MD%20simplified%20overview.pdf#2.9%20EntityDescriptor">EntityID</a>.
|
||||||
|
* Equivalent to the value found in the asserting party's <EntityDescriptor
|
||||||
|
* EntityID="..."/>
|
||||||
|
* @param entityId the asserting party's EntityID
|
||||||
|
* @return the {@link B} for further configuration
|
||||||
|
*/
|
||||||
|
B entityId(String entityId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 B} for further configuration
|
||||||
|
*/
|
||||||
|
B wantAuthnRequestsSigned(boolean wantAuthnRequestsSigned);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply this {@link Consumer} to the list of SigningMethod Algorithms
|
||||||
|
* @param signingMethodAlgorithmsConsumer a {@link Consumer} of the list of
|
||||||
|
* SigningMethod Algorithms
|
||||||
|
* @return this {@link B} for further configuration
|
||||||
|
* @since 5.5
|
||||||
|
*/
|
||||||
|
B signingAlgorithms(Consumer<List<String>> signingMethodAlgorithmsConsumer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply this {@link Consumer} to the list of {@link Saml2X509Credential}s
|
||||||
|
* @param credentialsConsumer a {@link Consumer} of the {@link List} of
|
||||||
|
* {@link Saml2X509Credential}s
|
||||||
|
* @return the {@link RelyingPartyRegistration.Builder} for further configuration
|
||||||
|
* @since 5.4
|
||||||
|
*/
|
||||||
|
B verificationX509Credentials(Consumer<Collection<Saml2X509Credential>> credentialsConsumer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply this {@link Consumer} to the list of {@link Saml2X509Credential}s
|
||||||
|
* @param credentialsConsumer a {@link Consumer} of the {@link List} of
|
||||||
|
* {@link Saml2X509Credential}s
|
||||||
|
* @return the {@link RelyingPartyRegistration.Builder} for further configuration
|
||||||
|
* @since 5.4
|
||||||
|
*/
|
||||||
|
B encryptionX509Credentials(Consumer<Collection<Saml2X509Credential>> credentialsConsumer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the <a href=
|
||||||
|
* "https://www.oasis-open.org/committees/download.php/51890/SAML%20MD%20simplified%20overview.pdf#2.5%20Endpoint">SingleSignOnService</a>
|
||||||
|
* Location.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Equivalent to the value found in <SingleSignOnService Location="..."/> in
|
||||||
|
* the asserting party's <IDPSSODescriptor>.
|
||||||
|
* @param singleSignOnServiceLocation the SingleSignOnService Location
|
||||||
|
* @return the {@link B} for further configuration
|
||||||
|
*/
|
||||||
|
B singleSignOnServiceLocation(String singleSignOnServiceLocation);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the <a href=
|
||||||
|
* "https://www.oasis-open.org/committees/download.php/51890/SAML%20MD%20simplified%20overview.pdf#2.5%20Endpoint">SingleSignOnService</a>
|
||||||
|
* Binding.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Equivalent to the value found in <SingleSignOnService Binding="..."/> in
|
||||||
|
* the asserting party's <IDPSSODescriptor>.
|
||||||
|
* @param singleSignOnServiceBinding the SingleSignOnService Binding
|
||||||
|
* @return the {@link B} for further configuration
|
||||||
|
*/
|
||||||
|
B singleSignOnServiceBinding(Saml2MessageBinding singleSignOnServiceBinding);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the <a href=
|
||||||
|
* "https://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf#page=7">SingleLogoutService
|
||||||
|
* Location</a>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Equivalent to the value found in <SingleLogoutService Location="..."/> in
|
||||||
|
* the asserting party's <IDPSSODescriptor>.
|
||||||
|
* @param singleLogoutServiceLocation the SingleLogoutService Location
|
||||||
|
* @return the {@link B} for further configuration
|
||||||
|
* @since 5.6
|
||||||
|
*/
|
||||||
|
B singleLogoutServiceLocation(String singleLogoutServiceLocation);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the <a href=
|
||||||
|
* "https://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf#page=7">SingleLogoutService
|
||||||
|
* Response Location</a>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Equivalent to the value found in <SingleLogoutService
|
||||||
|
* ResponseLocation="..."/> in the asserting party's <IDPSSODescriptor>.
|
||||||
|
* @param singleLogoutServiceResponseLocation the SingleLogoutService Response
|
||||||
|
* Location
|
||||||
|
* @return the {@link B} for further configuration
|
||||||
|
* @since 5.6
|
||||||
|
*/
|
||||||
|
B singleLogoutServiceResponseLocation(String singleLogoutServiceResponseLocation);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the <a href=
|
||||||
|
* "https://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf#page=7">SingleLogoutService
|
||||||
|
* Binding</a>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Equivalent to the value found in <SingleLogoutService Binding="..."/> in
|
||||||
|
* the asserting party's <IDPSSODescriptor>.
|
||||||
|
* @param singleLogoutServiceBinding the SingleLogoutService Binding
|
||||||
|
* @return the {@link B} for further configuration
|
||||||
|
* @since 5.6
|
||||||
|
*/
|
||||||
|
B singleLogoutServiceBinding(Saml2MessageBinding singleLogoutServiceBinding);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an immutable ProviderDetails object representing the configuration for
|
||||||
|
* an Identity Provider, IDP
|
||||||
|
* @return immutable ProviderDetails object
|
||||||
|
*/
|
||||||
|
AssertingPartyMetadata build();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2002-2024 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.security.saml2.provider.service.registration;
|
||||||
|
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A repository for retrieving SAML 2.0 Asserting Party Metadata
|
||||||
|
*
|
||||||
|
* @author Josh Cummings
|
||||||
|
* @since 6.4
|
||||||
|
* @see OpenSamlAssertingPartyMetadataRepository
|
||||||
|
* @see org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrations
|
||||||
|
*/
|
||||||
|
public interface AssertingPartyMetadataRepository extends Iterable<AssertingPartyMetadata> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve an {@link AssertingPartyMetadata} by its <a href=
|
||||||
|
* "https://www.oasis-open.org/committees/download.php/51890/SAML%20MD%20simplified%20overview.pdf#2.9%20EntityDescriptor">EntityID</a>.
|
||||||
|
* @param entityId the EntityID to lookup
|
||||||
|
* @return the found {@link AssertingPartyMetadata}, or {@code null} otherwise
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
default AssertingPartyMetadata findByEntityId(String entityId) {
|
||||||
|
for (AssertingPartyMetadata metadata : this) {
|
||||||
|
if (metadata.getEntityId().equals(entityId)) {
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -338,6 +338,25 @@ public class RelyingPartyRegistration {
|
|||||||
return new Builder(assertingPartyDetails.getEntityId(), assertingPartyDetails.mutate());
|
return new Builder(assertingPartyDetails.getEntityId(), assertingPartyDetails.mutate());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@code RelyingPartyRegistration} {@link Builder} with a
|
||||||
|
* {@code registrationId} equivalent to the asserting party entity id. Also
|
||||||
|
* initializes to the contents of the given {@link AssertingPartyMetadata}.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Presented as a convenience method when working with
|
||||||
|
* {@link AssertingPartyMetadataRepository} return values. As such, only supports
|
||||||
|
* {@link AssertingPartyMetadata} instances of type {@link AssertingPartyDetails}.
|
||||||
|
* @param metadata the metadata used to initialize the
|
||||||
|
* {@link RelyingPartyRegistration} {@link Builder}
|
||||||
|
* @return {@link Builder} to create a {@link RelyingPartyRegistration} object
|
||||||
|
* @since 6.4
|
||||||
|
*/
|
||||||
|
public static Builder withAssertingPartyMetadata(AssertingPartyMetadata metadata) {
|
||||||
|
Assert.isInstanceOf(AssertingPartyDetails.class, metadata, "metadata must be of type AssertingPartyDetails");
|
||||||
|
return withAssertingPartyDetails((AssertingPartyDetails) metadata);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@code RelyingPartyRegistration} {@link Builder} based on an existing
|
* Creates a {@code RelyingPartyRegistration} {@link Builder} based on an existing
|
||||||
* object
|
* object
|
||||||
@ -380,7 +399,7 @@ public class RelyingPartyRegistration {
|
|||||||
*
|
*
|
||||||
* @since 5.4
|
* @since 5.4
|
||||||
*/
|
*/
|
||||||
public static class AssertingPartyDetails {
|
public static class AssertingPartyDetails implements AssertingPartyMetadata {
|
||||||
|
|
||||||
private final String entityId;
|
private final String entityId;
|
||||||
|
|
||||||
@ -584,7 +603,7 @@ public class RelyingPartyRegistration {
|
|||||||
.singleLogoutServiceBinding(this.singleLogoutServiceBinding);
|
.singleLogoutServiceBinding(this.singleLogoutServiceBinding);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder implements AssertingPartyMetadata.Builder<Builder> {
|
||||||
|
|
||||||
private String entityId;
|
private String entityId;
|
||||||
|
|
||||||
|
@ -166,4 +166,30 @@ public class RelyingPartyRegistrationTests {
|
|||||||
.containsExactly(encryptingCredential, altApCredential);
|
.containsExactly(encryptingCredential, altApCredential);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void withAssertingPartyMetadataWhenDetailsThenBuilderCopies() {
|
||||||
|
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")))
|
||||||
|
.assertionConsumerServiceBinding(Saml2MessageBinding.REDIRECT)
|
||||||
|
.build();
|
||||||
|
RelyingPartyRegistration copied = RelyingPartyRegistration
|
||||||
|
.withAssertingPartyMetadata(registration.getAssertingPartyDetails())
|
||||||
|
.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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user