Skip to content

Commit 7678523

Browse files
committed
Support Creating EntitiesDescriptor
Clsoes gh-12844
1 parent 37b893a commit 7678523

File tree

3 files changed

+63
-5
lines changed

3 files changed

+63
-5
lines changed

saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/metadata/OpenSamlMetadataResolver.java

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,13 @@
3030
import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
3131
import org.opensaml.saml.common.xml.SAMLConstants;
3232
import org.opensaml.saml.saml2.metadata.AssertionConsumerService;
33+
import org.opensaml.saml.saml2.metadata.EntitiesDescriptor;
3334
import org.opensaml.saml.saml2.metadata.EntityDescriptor;
3435
import org.opensaml.saml.saml2.metadata.KeyDescriptor;
3536
import org.opensaml.saml.saml2.metadata.NameIDFormat;
3637
import org.opensaml.saml.saml2.metadata.SPSSODescriptor;
3738
import org.opensaml.saml.saml2.metadata.SingleLogoutService;
39+
import org.opensaml.saml.saml2.metadata.impl.EntitiesDescriptorMarshaller;
3840
import org.opensaml.saml.saml2.metadata.impl.EntityDescriptorMarshaller;
3941
import org.opensaml.security.credential.UsageType;
4042
import org.opensaml.xmlsec.signature.KeyInfo;
@@ -65,24 +67,47 @@ public final class OpenSamlMetadataResolver implements Saml2MetadataResolver {
6567

6668
private final EntityDescriptorMarshaller entityDescriptorMarshaller;
6769

70+
private final EntitiesDescriptorMarshaller entitiesDescriptorMarshaller;
71+
6872
private Consumer<EntityDescriptorParameters> entityDescriptorCustomizer = (parameters) -> {
6973
};
7074

7175
public OpenSamlMetadataResolver() {
7276
this.entityDescriptorMarshaller = (EntityDescriptorMarshaller) XMLObjectProviderRegistrySupport
7377
.getMarshallerFactory().getMarshaller(EntityDescriptor.DEFAULT_ELEMENT_NAME);
7478
Assert.notNull(this.entityDescriptorMarshaller, "entityDescriptorMarshaller cannot be null");
79+
this.entitiesDescriptorMarshaller = (EntitiesDescriptorMarshaller) XMLObjectProviderRegistrySupport
80+
.getMarshallerFactory().getMarshaller(EntitiesDescriptor.DEFAULT_ELEMENT_NAME);
81+
Assert.notNull(this.entitiesDescriptorMarshaller, "entitiesDescriptorMarshaller cannot be null");
7582
}
7683

7784
@Override
7885
public String resolve(RelyingPartyRegistration relyingPartyRegistration) {
86+
EntityDescriptor entityDescriptor = entityDescriptor(relyingPartyRegistration);
87+
return serialize(entityDescriptor);
88+
}
89+
90+
public String resolve(Iterable<RelyingPartyRegistration> relyingPartyRegistrations) {
91+
Collection<EntityDescriptor> entityDescriptors = new ArrayList<>();
92+
for (RelyingPartyRegistration registration : relyingPartyRegistrations) {
93+
EntityDescriptor entityDescriptor = entityDescriptor(registration);
94+
entityDescriptors.add(entityDescriptor);
95+
}
96+
if (entityDescriptors.size() == 1) {
97+
return serialize(entityDescriptors.iterator().next());
98+
}
99+
EntitiesDescriptor entities = build(EntitiesDescriptor.DEFAULT_ELEMENT_NAME);
100+
entities.getEntityDescriptors().addAll(entityDescriptors);
101+
return serialize(entities);
102+
}
103+
104+
private EntityDescriptor entityDescriptor(RelyingPartyRegistration registration) {
79105
EntityDescriptor entityDescriptor = build(EntityDescriptor.DEFAULT_ELEMENT_NAME);
80-
entityDescriptor.setEntityID(relyingPartyRegistration.getEntityId());
81-
SPSSODescriptor spSsoDescriptor = buildSpSsoDescriptor(relyingPartyRegistration);
106+
entityDescriptor.setEntityID(registration.getEntityId());
107+
SPSSODescriptor spSsoDescriptor = buildSpSsoDescriptor(registration);
82108
entityDescriptor.getRoleDescriptors(SPSSODescriptor.DEFAULT_ELEMENT_NAME).add(spSsoDescriptor);
83-
this.entityDescriptorCustomizer
84-
.accept(new EntityDescriptorParameters(entityDescriptor, relyingPartyRegistration));
85-
return serialize(entityDescriptor);
109+
this.entityDescriptorCustomizer.accept(new EntityDescriptorParameters(entityDescriptor, registration));
110+
return entityDescriptor;
86111
}
87112

88113
/**
@@ -184,6 +209,16 @@ private String serialize(EntityDescriptor entityDescriptor) {
184209
}
185210
}
186211

212+
private String serialize(EntitiesDescriptor entities) {
213+
try {
214+
Element element = this.entitiesDescriptorMarshaller.marshall(entities);
215+
return SerializeSupport.prettyPrintXML(element);
216+
}
217+
catch (Exception ex) {
218+
throw new Saml2Exception(ex);
219+
}
220+
}
221+
187222
/**
188223
* A tuple containing an OpenSAML {@link EntityDescriptor} and its associated
189224
* {@link RelyingPartyRegistration}

saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/metadata/Saml2MetadataResolver.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,8 @@ public interface Saml2MetadataResolver {
3535
*/
3636
String resolve(RelyingPartyRegistration relyingPartyRegistration);
3737

38+
default String resolve(Iterable<RelyingPartyRegistration> relyingPartyRegistrations) {
39+
return resolve(relyingPartyRegistrations.iterator().next());
40+
}
41+
3842
}

saml2/saml2-service-provider/src/test/java/org/springframework/security/saml2/provider/service/metadata/OpenSamlMetadataResolverTests.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.security.saml2.provider.service.metadata;
1818

19+
import java.util.List;
20+
1921
import org.junit.jupiter.api.Test;
2022

2123
import org.springframework.security.saml2.core.TestSaml2X509Credentials;
@@ -89,4 +91,21 @@ public void resolveWhenEntityDescriptorCustomizerThenUses() {
8991
assertThat(metadata).contains("<md:EntityDescriptor").contains("entityID=\"overriddenEntityId\"");
9092
}
9193

94+
@Test
95+
public void resolveIterableWhenRelyingPartiesThenMetadataMatches() {
96+
RelyingPartyRegistration one = TestRelyingPartyRegistrations.full()
97+
.assertionConsumerServiceBinding(Saml2MessageBinding.REDIRECT).build();
98+
RelyingPartyRegistration two = TestRelyingPartyRegistrations.full().entityId("two")
99+
.assertionConsumerServiceBinding(Saml2MessageBinding.REDIRECT).build();
100+
OpenSamlMetadataResolver openSamlMetadataResolver = new OpenSamlMetadataResolver();
101+
String metadata = openSamlMetadataResolver.resolve(List.of(one, two));
102+
assertThat(metadata).contains("<md:EntitiesDescriptor").contains("<md:EntityDescriptor")
103+
.contains("entityID=\"rp-entity-id\"").contains("two").contains("<md:KeyDescriptor use=\"signing\">")
104+
.contains("<md:KeyDescriptor use=\"encryption\">")
105+
.contains("<ds:X509Certificate>MIICgTCCAeoCCQCuVzyqFgMSyDANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBh")
106+
.contains("Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\"")
107+
.contains("Location=\"https://rp.example.org/acs\" index=\"1\"")
108+
.contains("ResponseLocation=\"https://rp.example.org/logout/saml2/response\"");
109+
}
110+
92111
}

0 commit comments

Comments
 (0)