|
|
|
@ -28,6 +28,7 @@ import org.opensaml.xmlsec.signature.support.SignatureConstants; |
|
|
|
|
|
|
|
|
|
|
|
import org.springframework.security.saml2.core.Saml2X509Credential; |
|
|
|
import org.springframework.security.saml2.core.Saml2X509Credential; |
|
|
|
import org.springframework.util.Assert; |
|
|
|
import org.springframework.util.Assert; |
|
|
|
|
|
|
|
import org.springframework.util.CollectionUtils; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Represents a configured relying party (aka Service Provider) and asserting party (aka |
|
|
|
* Represents a configured relying party (aka Service Provider) and asserting party (aka |
|
|
|
@ -81,7 +82,7 @@ public final class RelyingPartyRegistration { |
|
|
|
|
|
|
|
|
|
|
|
private final String singleLogoutServiceResponseLocation; |
|
|
|
private final String singleLogoutServiceResponseLocation; |
|
|
|
|
|
|
|
|
|
|
|
private final Saml2MessageBinding singleLogoutServiceBinding; |
|
|
|
private final Collection<Saml2MessageBinding> singleLogoutServiceBindings; |
|
|
|
|
|
|
|
|
|
|
|
private final String nameIdFormat; |
|
|
|
private final String nameIdFormat; |
|
|
|
|
|
|
|
|
|
|
|
@ -93,7 +94,7 @@ public final class RelyingPartyRegistration { |
|
|
|
|
|
|
|
|
|
|
|
private RelyingPartyRegistration(String registrationId, String entityId, String assertionConsumerServiceLocation, |
|
|
|
private RelyingPartyRegistration(String registrationId, String entityId, String assertionConsumerServiceLocation, |
|
|
|
Saml2MessageBinding assertionConsumerServiceBinding, String singleLogoutServiceLocation, |
|
|
|
Saml2MessageBinding assertionConsumerServiceBinding, String singleLogoutServiceLocation, |
|
|
|
String singleLogoutServiceResponseLocation, Saml2MessageBinding singleLogoutServiceBinding, |
|
|
|
String singleLogoutServiceResponseLocation, Collection<Saml2MessageBinding> singleLogoutServiceBindings, |
|
|
|
AssertingPartyDetails assertingPartyDetails, String nameIdFormat, |
|
|
|
AssertingPartyDetails assertingPartyDetails, String nameIdFormat, |
|
|
|
Collection<Saml2X509Credential> decryptionX509Credentials, |
|
|
|
Collection<Saml2X509Credential> decryptionX509Credentials, |
|
|
|
Collection<Saml2X509Credential> signingX509Credentials) { |
|
|
|
Collection<Saml2X509Credential> signingX509Credentials) { |
|
|
|
@ -101,8 +102,8 @@ public final class RelyingPartyRegistration { |
|
|
|
Assert.hasText(entityId, "entityId cannot be empty"); |
|
|
|
Assert.hasText(entityId, "entityId cannot be empty"); |
|
|
|
Assert.hasText(assertionConsumerServiceLocation, "assertionConsumerServiceLocation cannot be empty"); |
|
|
|
Assert.hasText(assertionConsumerServiceLocation, "assertionConsumerServiceLocation cannot be empty"); |
|
|
|
Assert.notNull(assertionConsumerServiceBinding, "assertionConsumerServiceBinding cannot be null"); |
|
|
|
Assert.notNull(assertionConsumerServiceBinding, "assertionConsumerServiceBinding cannot be null"); |
|
|
|
Assert.isTrue(singleLogoutServiceLocation == null || singleLogoutServiceBinding != null, |
|
|
|
Assert.isTrue(singleLogoutServiceLocation == null || !CollectionUtils.isEmpty(singleLogoutServiceBindings), |
|
|
|
"singleLogoutServiceBinding cannot be null when singleLogoutServiceLocation is set"); |
|
|
|
"singleLogoutServiceBindings cannot be null or empty when singleLogoutServiceLocation is set"); |
|
|
|
Assert.notNull(assertingPartyDetails, "assertingPartyDetails cannot be null"); |
|
|
|
Assert.notNull(assertingPartyDetails, "assertingPartyDetails cannot be null"); |
|
|
|
Assert.notNull(decryptionX509Credentials, "decryptionX509Credentials cannot be null"); |
|
|
|
Assert.notNull(decryptionX509Credentials, "decryptionX509Credentials cannot be null"); |
|
|
|
for (Saml2X509Credential c : decryptionX509Credentials) { |
|
|
|
for (Saml2X509Credential c : decryptionX509Credentials) { |
|
|
|
@ -121,7 +122,7 @@ public final class RelyingPartyRegistration { |
|
|
|
this.assertionConsumerServiceBinding = assertionConsumerServiceBinding; |
|
|
|
this.assertionConsumerServiceBinding = assertionConsumerServiceBinding; |
|
|
|
this.singleLogoutServiceLocation = singleLogoutServiceLocation; |
|
|
|
this.singleLogoutServiceLocation = singleLogoutServiceLocation; |
|
|
|
this.singleLogoutServiceResponseLocation = singleLogoutServiceResponseLocation; |
|
|
|
this.singleLogoutServiceResponseLocation = singleLogoutServiceResponseLocation; |
|
|
|
this.singleLogoutServiceBinding = singleLogoutServiceBinding; |
|
|
|
this.singleLogoutServiceBindings = Collections.unmodifiableList(new LinkedList<>(singleLogoutServiceBindings)); |
|
|
|
this.nameIdFormat = nameIdFormat; |
|
|
|
this.nameIdFormat = nameIdFormat; |
|
|
|
this.assertingPartyDetails = assertingPartyDetails; |
|
|
|
this.assertingPartyDetails = assertingPartyDetails; |
|
|
|
this.decryptionX509Credentials = Collections.unmodifiableList(new LinkedList<>(decryptionX509Credentials)); |
|
|
|
this.decryptionX509Credentials = Collections.unmodifiableList(new LinkedList<>(decryptionX509Credentials)); |
|
|
|
@ -194,7 +195,22 @@ public final class RelyingPartyRegistration { |
|
|
|
* @since 5.6 |
|
|
|
* @since 5.6 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public Saml2MessageBinding getSingleLogoutServiceBinding() { |
|
|
|
public Saml2MessageBinding getSingleLogoutServiceBinding() { |
|
|
|
return this.singleLogoutServiceBinding; |
|
|
|
Assert.state(this.singleLogoutServiceBindings.size() == 1, "Method does not support multiple bindings."); |
|
|
|
|
|
|
|
return this.singleLogoutServiceBindings.iterator().next(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* 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 |
|
|
|
|
|
|
|
* relying party's <SPSSODescriptor>. |
|
|
|
|
|
|
|
* @return the SingleLogoutService Binding |
|
|
|
|
|
|
|
* @since 5.8 |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public Collection<Saml2MessageBinding> getSingleLogoutServiceBindings() { |
|
|
|
|
|
|
|
return this.singleLogoutServiceBindings; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
@ -308,7 +324,7 @@ public final class RelyingPartyRegistration { |
|
|
|
.assertionConsumerServiceBinding(registration.getAssertionConsumerServiceBinding()) |
|
|
|
.assertionConsumerServiceBinding(registration.getAssertionConsumerServiceBinding()) |
|
|
|
.singleLogoutServiceLocation(registration.getSingleLogoutServiceLocation()) |
|
|
|
.singleLogoutServiceLocation(registration.getSingleLogoutServiceLocation()) |
|
|
|
.singleLogoutServiceResponseLocation(registration.getSingleLogoutServiceResponseLocation()) |
|
|
|
.singleLogoutServiceResponseLocation(registration.getSingleLogoutServiceResponseLocation()) |
|
|
|
.singleLogoutServiceBinding(registration.getSingleLogoutServiceBinding()) |
|
|
|
.singleLogoutServiceBindings((c) -> c.addAll(registration.getSingleLogoutServiceBindings())) |
|
|
|
.nameIdFormat(registration.getNameIdFormat()) |
|
|
|
.nameIdFormat(registration.getNameIdFormat()) |
|
|
|
.assertingPartyDetails((assertingParty) -> assertingParty |
|
|
|
.assertingPartyDetails((assertingParty) -> assertingParty |
|
|
|
.entityId(registration.getAssertingPartyDetails().getEntityId()) |
|
|
|
.entityId(registration.getAssertingPartyDetails().getEntityId()) |
|
|
|
@ -737,7 +753,7 @@ public final class RelyingPartyRegistration { |
|
|
|
|
|
|
|
|
|
|
|
private String singleLogoutServiceResponseLocation; |
|
|
|
private String singleLogoutServiceResponseLocation; |
|
|
|
|
|
|
|
|
|
|
|
private Saml2MessageBinding singleLogoutServiceBinding = Saml2MessageBinding.POST; |
|
|
|
private Collection<Saml2MessageBinding> singleLogoutServiceBindings = new LinkedHashSet<>(); |
|
|
|
|
|
|
|
|
|
|
|
private String nameIdFormat = null; |
|
|
|
private String nameIdFormat = null; |
|
|
|
|
|
|
|
|
|
|
|
@ -855,7 +871,28 @@ public final class RelyingPartyRegistration { |
|
|
|
* @since 5.6 |
|
|
|
* @since 5.6 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public Builder singleLogoutServiceBinding(Saml2MessageBinding singleLogoutServiceBinding) { |
|
|
|
public Builder singleLogoutServiceBinding(Saml2MessageBinding singleLogoutServiceBinding) { |
|
|
|
this.singleLogoutServiceBinding = singleLogoutServiceBinding; |
|
|
|
return this.singleLogoutServiceBindings((saml2MessageBindings) -> { |
|
|
|
|
|
|
|
saml2MessageBindings.clear(); |
|
|
|
|
|
|
|
saml2MessageBindings.add(singleLogoutServiceBinding); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Apply this {@link Consumer} to the {@link Collection} of |
|
|
|
|
|
|
|
* {@link Saml2MessageBinding}s for the purposes of modifying the <a href= |
|
|
|
|
|
|
|
* "https://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf#page=7">SingleLogoutService |
|
|
|
|
|
|
|
* Binding</a> {@link Collection}. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* <p> |
|
|
|
|
|
|
|
* Equivalent to the value found in <SingleLogoutService Binding="..."/> in |
|
|
|
|
|
|
|
* the relying party's <SPSSODescriptor>. |
|
|
|
|
|
|
|
* @param bindingsConsumer - the {@link Consumer} for modifying the |
|
|
|
|
|
|
|
* {@link Collection} |
|
|
|
|
|
|
|
* @return the {@link Builder} for further configuration |
|
|
|
|
|
|
|
* @since 5.8 |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public Builder singleLogoutServiceBindings(Consumer<Collection<Saml2MessageBinding>> bindingsConsumer) { |
|
|
|
|
|
|
|
bindingsConsumer.accept(this.singleLogoutServiceBindings); |
|
|
|
return this; |
|
|
|
return this; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -925,10 +962,15 @@ public final class RelyingPartyRegistration { |
|
|
|
if (this.singleLogoutServiceResponseLocation == null) { |
|
|
|
if (this.singleLogoutServiceResponseLocation == null) { |
|
|
|
this.singleLogoutServiceResponseLocation = this.singleLogoutServiceLocation; |
|
|
|
this.singleLogoutServiceResponseLocation = this.singleLogoutServiceLocation; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (this.singleLogoutServiceBindings.isEmpty()) { |
|
|
|
|
|
|
|
this.singleLogoutServiceBindings.add(Saml2MessageBinding.POST); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return new RelyingPartyRegistration(this.registrationId, this.entityId, |
|
|
|
return new RelyingPartyRegistration(this.registrationId, this.entityId, |
|
|
|
this.assertionConsumerServiceLocation, this.assertionConsumerServiceBinding, |
|
|
|
this.assertionConsumerServiceLocation, this.assertionConsumerServiceBinding, |
|
|
|
this.singleLogoutServiceLocation, this.singleLogoutServiceResponseLocation, |
|
|
|
this.singleLogoutServiceLocation, this.singleLogoutServiceResponseLocation, |
|
|
|
this.singleLogoutServiceBinding, this.assertingPartyDetailsBuilder.build(), this.nameIdFormat, |
|
|
|
this.singleLogoutServiceBindings, this.assertingPartyDetailsBuilder.build(), this.nameIdFormat, |
|
|
|
this.decryptionX509Credentials, this.signingX509Credentials); |
|
|
|
this.decryptionX509Credentials, this.signingX509Credentials); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|