1
0
mirror of synced 2026-05-22 21:33:16 +00:00

Add OpenSamlAssertingPartyMetadataRepository

Closes gh-12116
Closes gh-15395
This commit is contained in:
Josh Cummings
2024-07-10 17:05:45 -06:00
parent 7ad9ee93cf
commit e6dfb63bdf
5 changed files with 940 additions and 4 deletions
@@ -27,11 +27,130 @@ Kotlin::
[source,kotlin,role="secondary"]
----
val details: OpenSamlAssertingPartyDetails =
registration.getAssertingPartyDetails() as OpenSamlAssertingPartyDetails;
val openSamlEntityDescriptor: EntityDescriptor = details.getEntityDescriptor();
registration.getAssertingPartyDetails() as OpenSamlAssertingPartyDetails
val openSamlEntityDescriptor: EntityDescriptor = details.getEntityDescriptor()
----
======
=== Using `AssertingPartyMetadataRepository`
You can also be more targeted than `RelyingPartyRegistrations` by using `AssertingPartyMetadataRepository`, an interface that allows for only retrieving the asserting party metadata.
This allows three valuable features:
* Implementations can refresh asserting party metadata in an expiry-aware fashion
* Implementations of `RelyingPartyRegistrationRepository` can more easily articulate a relationship between a relying party and its one or many corresponding asserting parties
* Implementations can verify metadata signatures
For example, `OpenSamlAssertingPartyMetadataRepository` uses OpenSAML's `MetadataResolver`, and API whose implementations regularly refresh the underlying metadata in an expiry-aware fashion.
This means that you can now create a refreshable `RelyingPartyRegistrationRepository` in just a few lines of code:
[tabs]
======
Java::
+
[source,java,role="primary"]
----
@Component
public class RefreshableRelyingPartyRegistrationRepository
implements IterableRelyingPartyRegistrationRepository {
private final AssertingPartyMetadataRepository metadata =
OpenSamlAssertingPartyMetadataRepository
.fromTrustedMetadataLocation("https://idp.example.org/metadata").build();
@Override
public RelyingPartyRegistration findByRegistrationId(String registrationId) {
AssertingPartyMetadata metadata = this.metadata.findByEntityId(registrationId);
if (metadata == null) {
return null;
}
return applyRelyingParty(metadata);
}
@Override
public Iterator<RelyingPartyRegistration> iterator() {
return StreamSupport.stream(this.metadata.spliterator(), false)
.map(this::applyRelyingParty).iterator();
}
private RelyingPartyRegistration applyRelyingParty(AssertingPartyMetadata metadata) {
AssertingPartyDetails details = (AssertingPartyDetails) metadata;
return RelyingPartyRegistration.withAssertingPartyDetails(details)
// apply any relying party configuration
.build();
}
}
----
Kotlin::
+
[source,kotlin,role="secondary"]
----
@Component
class RefreshableRelyingPartyRegistrationRepository : IterableRelyingPartyRegistrationRepository {
private val metadata: AssertingPartyMetadataRepository =
OpenSamlAssertingPartyMetadataRepository.fromTrustedMetadataLocation(
"https://idp.example.org/metadata").build()
fun findByRegistrationId(registrationId:String?): RelyingPartyRegistration {
val metadata = this.metadata.findByEntityId(registrationId)
if (metadata == null) {
return null
}
return applyRelyingParty(metadata)
}
fun iterator(): Iterator<RelyingPartyRegistration> {
return StreamSupport.stream(this.metadata.spliterator(), false)
.map(this::applyRelyingParty).iterator()
}
private fun applyRelyingParty(metadata: AssertingPartyMetadata): RelyingPartyRegistration {
val details: AssertingPartyDetails = metadata as AssertingPartyDetails
return RelyingPartyRegistration.withAssertingPartyDetails(details)
// apply any relying party configuration
.build()
}
}
----
======
[TIP]
`OpenSamlAssertingPartyMetadataRepository` also ships with a constructor so you can provide a custom `MetadataResolver`. Since the underlying `MetadataResolver` is doing the expirying and refreshing, if you use the constructor directly, you will only get these features by providing an implementation that does so.
=== Verifying Metadata Signatures
You can also verify metadata signatures using `OpenSamlAssertingPartyMetadataRepository` by providing the appropriate set of ``Saml2X509Credential``s as follows:
[tabs]
======
Java::
+
[source,java,role="primary"]
----
OpenSamlAssertingPartyMetadataRepository.withMetadataLocation("https://idp.example.org/metadata")
.verificationCredentials((c) -> c.add(myVerificationCredential))
.build();
----
Kotlin::
+
[source,kotlin,role="secondary"]
----
OpenSamlAssertingPartyMetadataRepository.withMetadataLocation("https://idp.example.org/metadata")
.verificationCredentials({ c : Collection<Saml2X509Credential> ->
c.add(myVerificationCredential) })
.build()
----
======
[NOTE]
If no credentials are provided, the component will not perform signature validation.
[[publishing-relying-party-metadata]]
== Producing `<saml2:SPSSODescriptor>` Metadata