parent
37b893a0f5
commit
7678523b73
|
@ -30,11 +30,13 @@ import org.opensaml.core.xml.XMLObjectBuilder;
|
||||||
import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
|
import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
|
||||||
import org.opensaml.saml.common.xml.SAMLConstants;
|
import org.opensaml.saml.common.xml.SAMLConstants;
|
||||||
import org.opensaml.saml.saml2.metadata.AssertionConsumerService;
|
import org.opensaml.saml.saml2.metadata.AssertionConsumerService;
|
||||||
|
import org.opensaml.saml.saml2.metadata.EntitiesDescriptor;
|
||||||
import org.opensaml.saml.saml2.metadata.EntityDescriptor;
|
import org.opensaml.saml.saml2.metadata.EntityDescriptor;
|
||||||
import org.opensaml.saml.saml2.metadata.KeyDescriptor;
|
import org.opensaml.saml.saml2.metadata.KeyDescriptor;
|
||||||
import org.opensaml.saml.saml2.metadata.NameIDFormat;
|
import org.opensaml.saml.saml2.metadata.NameIDFormat;
|
||||||
import org.opensaml.saml.saml2.metadata.SPSSODescriptor;
|
import org.opensaml.saml.saml2.metadata.SPSSODescriptor;
|
||||||
import org.opensaml.saml.saml2.metadata.SingleLogoutService;
|
import org.opensaml.saml.saml2.metadata.SingleLogoutService;
|
||||||
|
import org.opensaml.saml.saml2.metadata.impl.EntitiesDescriptorMarshaller;
|
||||||
import org.opensaml.saml.saml2.metadata.impl.EntityDescriptorMarshaller;
|
import org.opensaml.saml.saml2.metadata.impl.EntityDescriptorMarshaller;
|
||||||
import org.opensaml.security.credential.UsageType;
|
import org.opensaml.security.credential.UsageType;
|
||||||
import org.opensaml.xmlsec.signature.KeyInfo;
|
import org.opensaml.xmlsec.signature.KeyInfo;
|
||||||
|
@ -65,6 +67,8 @@ public final class OpenSamlMetadataResolver implements Saml2MetadataResolver {
|
||||||
|
|
||||||
private final EntityDescriptorMarshaller entityDescriptorMarshaller;
|
private final EntityDescriptorMarshaller entityDescriptorMarshaller;
|
||||||
|
|
||||||
|
private final EntitiesDescriptorMarshaller entitiesDescriptorMarshaller;
|
||||||
|
|
||||||
private Consumer<EntityDescriptorParameters> entityDescriptorCustomizer = (parameters) -> {
|
private Consumer<EntityDescriptorParameters> entityDescriptorCustomizer = (parameters) -> {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -72,19 +76,40 @@ public final class OpenSamlMetadataResolver implements Saml2MetadataResolver {
|
||||||
this.entityDescriptorMarshaller = (EntityDescriptorMarshaller) XMLObjectProviderRegistrySupport
|
this.entityDescriptorMarshaller = (EntityDescriptorMarshaller) XMLObjectProviderRegistrySupport
|
||||||
.getMarshallerFactory().getMarshaller(EntityDescriptor.DEFAULT_ELEMENT_NAME);
|
.getMarshallerFactory().getMarshaller(EntityDescriptor.DEFAULT_ELEMENT_NAME);
|
||||||
Assert.notNull(this.entityDescriptorMarshaller, "entityDescriptorMarshaller cannot be null");
|
Assert.notNull(this.entityDescriptorMarshaller, "entityDescriptorMarshaller cannot be null");
|
||||||
|
this.entitiesDescriptorMarshaller = (EntitiesDescriptorMarshaller) XMLObjectProviderRegistrySupport
|
||||||
|
.getMarshallerFactory().getMarshaller(EntitiesDescriptor.DEFAULT_ELEMENT_NAME);
|
||||||
|
Assert.notNull(this.entitiesDescriptorMarshaller, "entitiesDescriptorMarshaller cannot be null");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String resolve(RelyingPartyRegistration relyingPartyRegistration) {
|
public String resolve(RelyingPartyRegistration relyingPartyRegistration) {
|
||||||
EntityDescriptor entityDescriptor = build(EntityDescriptor.DEFAULT_ELEMENT_NAME);
|
EntityDescriptor entityDescriptor = entityDescriptor(relyingPartyRegistration);
|
||||||
entityDescriptor.setEntityID(relyingPartyRegistration.getEntityId());
|
|
||||||
SPSSODescriptor spSsoDescriptor = buildSpSsoDescriptor(relyingPartyRegistration);
|
|
||||||
entityDescriptor.getRoleDescriptors(SPSSODescriptor.DEFAULT_ELEMENT_NAME).add(spSsoDescriptor);
|
|
||||||
this.entityDescriptorCustomizer
|
|
||||||
.accept(new EntityDescriptorParameters(entityDescriptor, relyingPartyRegistration));
|
|
||||||
return serialize(entityDescriptor);
|
return serialize(entityDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String resolve(Iterable<RelyingPartyRegistration> relyingPartyRegistrations) {
|
||||||
|
Collection<EntityDescriptor> entityDescriptors = new ArrayList<>();
|
||||||
|
for (RelyingPartyRegistration registration : relyingPartyRegistrations) {
|
||||||
|
EntityDescriptor entityDescriptor = entityDescriptor(registration);
|
||||||
|
entityDescriptors.add(entityDescriptor);
|
||||||
|
}
|
||||||
|
if (entityDescriptors.size() == 1) {
|
||||||
|
return serialize(entityDescriptors.iterator().next());
|
||||||
|
}
|
||||||
|
EntitiesDescriptor entities = build(EntitiesDescriptor.DEFAULT_ELEMENT_NAME);
|
||||||
|
entities.getEntityDescriptors().addAll(entityDescriptors);
|
||||||
|
return serialize(entities);
|
||||||
|
}
|
||||||
|
|
||||||
|
private EntityDescriptor entityDescriptor(RelyingPartyRegistration registration) {
|
||||||
|
EntityDescriptor entityDescriptor = build(EntityDescriptor.DEFAULT_ELEMENT_NAME);
|
||||||
|
entityDescriptor.setEntityID(registration.getEntityId());
|
||||||
|
SPSSODescriptor spSsoDescriptor = buildSpSsoDescriptor(registration);
|
||||||
|
entityDescriptor.getRoleDescriptors(SPSSODescriptor.DEFAULT_ELEMENT_NAME).add(spSsoDescriptor);
|
||||||
|
this.entityDescriptorCustomizer.accept(new EntityDescriptorParameters(entityDescriptor, registration));
|
||||||
|
return entityDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a {@link Consumer} for modifying the OpenSAML {@link EntityDescriptor}
|
* Set a {@link Consumer} for modifying the OpenSAML {@link EntityDescriptor}
|
||||||
* @param entityDescriptorCustomizer a consumer that accepts an
|
* @param entityDescriptorCustomizer a consumer that accepts an
|
||||||
|
@ -184,6 +209,16 @@ public final class OpenSamlMetadataResolver implements Saml2MetadataResolver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String serialize(EntitiesDescriptor entities) {
|
||||||
|
try {
|
||||||
|
Element element = this.entitiesDescriptorMarshaller.marshall(entities);
|
||||||
|
return SerializeSupport.prettyPrintXML(element);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
throw new Saml2Exception(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A tuple containing an OpenSAML {@link EntityDescriptor} and its associated
|
* A tuple containing an OpenSAML {@link EntityDescriptor} and its associated
|
||||||
* {@link RelyingPartyRegistration}
|
* {@link RelyingPartyRegistration}
|
||||||
|
|
|
@ -35,4 +35,8 @@ public interface Saml2MetadataResolver {
|
||||||
*/
|
*/
|
||||||
String resolve(RelyingPartyRegistration relyingPartyRegistration);
|
String resolve(RelyingPartyRegistration relyingPartyRegistration);
|
||||||
|
|
||||||
|
default String resolve(Iterable<RelyingPartyRegistration> relyingPartyRegistrations) {
|
||||||
|
return resolve(relyingPartyRegistrations.iterator().next());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
|
|
||||||
package org.springframework.security.saml2.provider.service.metadata;
|
package org.springframework.security.saml2.provider.service.metadata;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.springframework.security.saml2.core.TestSaml2X509Credentials;
|
import org.springframework.security.saml2.core.TestSaml2X509Credentials;
|
||||||
|
@ -89,4 +91,21 @@ public class OpenSamlMetadataResolverTests {
|
||||||
assertThat(metadata).contains("<md:EntityDescriptor").contains("entityID=\"overriddenEntityId\"");
|
assertThat(metadata).contains("<md:EntityDescriptor").contains("entityID=\"overriddenEntityId\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void resolveIterableWhenRelyingPartiesThenMetadataMatches() {
|
||||||
|
RelyingPartyRegistration one = TestRelyingPartyRegistrations.full()
|
||||||
|
.assertionConsumerServiceBinding(Saml2MessageBinding.REDIRECT).build();
|
||||||
|
RelyingPartyRegistration two = TestRelyingPartyRegistrations.full().entityId("two")
|
||||||
|
.assertionConsumerServiceBinding(Saml2MessageBinding.REDIRECT).build();
|
||||||
|
OpenSamlMetadataResolver openSamlMetadataResolver = new OpenSamlMetadataResolver();
|
||||||
|
String metadata = openSamlMetadataResolver.resolve(List.of(one, two));
|
||||||
|
assertThat(metadata).contains("<md:EntitiesDescriptor").contains("<md:EntityDescriptor")
|
||||||
|
.contains("entityID=\"rp-entity-id\"").contains("two").contains("<md:KeyDescriptor use=\"signing\">")
|
||||||
|
.contains("<md:KeyDescriptor use=\"encryption\">")
|
||||||
|
.contains("<ds:X509Certificate>MIICgTCCAeoCCQCuVzyqFgMSyDANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBh")
|
||||||
|
.contains("Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\"")
|
||||||
|
.contains("Location=\"https://rp.example.org/acs\" index=\"1\"")
|
||||||
|
.contains("ResponseLocation=\"https://rp.example.org/logout/saml2/response\"");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue