Allow Creating RelyingPartyRegistration from Metadata InputStream

Update SAML2 Login reference documentation to reflect the changes

Closes gh-9558
This commit is contained in:
Marcus Hert da Coregio 2021-05-14 13:46:29 -03:00 committed by Marcus Hert Da Coregio
parent 58ebacc06f
commit 6474a9e76e
3 changed files with 84 additions and 4 deletions

View File

@ -536,7 +536,6 @@ RelyingPartyRegistration relyingPartyRegistration = RelyingPartyRegistrations
.registrationId("my-id")
.build();
----
.Kotlin
[source,kotlin,role="secondary"]
----
@ -547,6 +546,20 @@ val relyingPartyRegistration = RelyingPartyRegistrations
----
====
Note that you can also create a `RelyingPartyRegistration` from an arbitrary `InputStream` source.
One such example is when the metadata is stored in a database:
[source,java]
----
String xml = fromDatabase();
try (InputStream source = new ByteArrayInputStream(xml.getBytes())) {
RelyingPartyRegistration relyingPartyRegistration = RelyingPartyRegistrations
.fromMetadata(source)
.registrationId("my-id")
.build();
}
----
Though a more sophisticated setup is also possible, like so:
====

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 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.
@ -28,6 +28,7 @@ import org.springframework.security.saml2.Saml2Exception;
*
* @author Josh Cummings
* @author Ryan Cassar
* @author Marcus da Coregio
* @since 5.4
*/
public final class RelyingPartyRegistrations {
@ -73,7 +74,7 @@ public final class RelyingPartyRegistrations {
*/
public static RelyingPartyRegistration.Builder fromMetadataLocation(String metadataLocation) {
try (InputStream source = resourceLoader.getResource(metadataLocation).getInputStream()) {
return assertingPartyMetadataConverter.convert(source);
return fromMetadata(source);
}
catch (IOException ex) {
if (ex.getCause() instanceof Saml2Exception) {
@ -83,4 +84,45 @@ public final class RelyingPartyRegistrations {
}
}
/**
* Return a {@link RelyingPartyRegistration.Builder} based off of the given SAML 2.0
* Asserting Party (IDP) metadata.
*
* <p>
* This method is intended for scenarios when the metadata is looked up by a separate
* mechanism. One such example is when the metadata is stored in a database.
* </p>
*
* <p>
* <strong>The callers of this method are accountable for closing the
* {@code InputStream} source.</strong>
* </p>
*
* Note that by default the registrationId is set to be the given metadata location,
* but this will most often not be sufficient. To complete the configuration, most
* applications will also need to provide a registrationId, like so:
*
* <pre>
* String xml = fromDatabase();
* try (InputStream source = new ByteArrayInputStream(xml.getBytes())) {
* RelyingPartyRegistration registration = RelyingPartyRegistrations
* .fromMetadata(source)
* .registrationId("registration-id")
* .build();
* }
* </pre>
*
* Also note that an {@code IDPSSODescriptor} typically only contains information
* about the asserting party. Thus, you will need to remember to still populate
* anything about the relying party, like any private keys the relying party will use
* for signing AuthnRequests.
* @param source the {@link InputStream} source containing the asserting party
* metadata
* @return the {@link RelyingPartyRegistration.Builder} for further configuration
* @since 5.6
*/
public static RelyingPartyRegistration.Builder fromMetadata(InputStream source) {
return assertingPartyMetadataConverter.convert(source);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 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.
@ -17,7 +17,9 @@
package org.springframework.security.saml2.provider.service.registration;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.stream.Collectors;
@ -104,4 +106,27 @@ public class RelyingPartyRegistrationsTests {
.isThrownBy(() -> RelyingPartyRegistrations.fromMetadataLocation("filePath"));
}
@Test
public void fromMetadataInputStreamWhenResolvableThenPopulatesBuilder() throws Exception {
try (InputStream source = new ByteArrayInputStream(this.metadata.getBytes())) {
RelyingPartyRegistration registration = RelyingPartyRegistrations.fromMetadata(source).entityId("rp")
.build();
RelyingPartyRegistration.AssertingPartyDetails details = registration.getAssertingPartyDetails();
assertThat(details.getEntityId()).isEqualTo("https://idp.example.com/idp/shibboleth");
assertThat(details.getSingleSignOnServiceLocation())
.isEqualTo("https://idp.example.com/idp/profile/SAML2/POST/SSO");
assertThat(details.getSingleSignOnServiceBinding()).isEqualTo(Saml2MessageBinding.POST);
assertThat(details.getVerificationX509Credentials()).hasSize(1);
assertThat(details.getEncryptionX509Credentials()).hasSize(1);
}
}
@Test
public void fromMetadataInputStreamWhenEmptyThenSaml2Exception() throws Exception {
try (InputStream source = new ByteArrayInputStream("".getBytes())) {
assertThatExceptionOfType(Saml2Exception.class)
.isThrownBy(() -> RelyingPartyRegistrations.fromMetadata(source));
}
}
}