parent
5c8972b7d5
commit
9900658c92
|
@ -274,7 +274,7 @@ public class OpenSamlAuthenticationRequestFactory implements Saml2Authentication
|
|||
|
||||
private SignatureSigningParameters resolveSigningParameters(RelyingPartyRegistration relyingPartyRegistration) {
|
||||
List<Credential> credentials = resolveSigningCredentials(relyingPartyRegistration);
|
||||
List<String> algorithms = Collections.singletonList(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256);
|
||||
List<String> algorithms = relyingPartyRegistration.getAssertingPartyDetails().getSigningMethodAlgorithms();
|
||||
List<String> digests = Collections.singletonList(SignatureConstants.ALGO_ID_DIGEST_SHA256);
|
||||
String canonicalization = SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS;
|
||||
SignatureSigningParametersResolver resolver = new SAMLMetadataSignatureSigningParametersResolver();
|
||||
|
|
|
@ -18,6 +18,8 @@ package org.springframework.security.saml2.provider.service.registration;
|
|||
|
||||
import java.security.PrivateKey;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
|
@ -27,6 +29,8 @@ import java.util.Set;
|
|||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.opensaml.xmlsec.signature.support.SignatureConstants;
|
||||
|
||||
import org.springframework.security.saml2.core.Saml2X509Credential;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
@ -438,10 +442,12 @@ public final class RelyingPartyRegistration {
|
|||
|
||||
private final Saml2MessageBinding singleSignOnServiceBinding;
|
||||
|
||||
private List<String> signingMethodAlgorithms;
|
||||
|
||||
private AssertingPartyDetails(String entityId, boolean wantAuthnRequestsSigned,
|
||||
Collection<Saml2X509Credential> verificationX509Credentials,
|
||||
Collection<Saml2X509Credential> encryptionX509Credentials, String singleSignOnServiceLocation,
|
||||
Saml2MessageBinding singleSignOnServiceBinding) {
|
||||
Saml2MessageBinding singleSignOnServiceBinding, List<String> signingMethodAlgorithms) {
|
||||
Assert.hasText(entityId, "entityId cannot be null or empty");
|
||||
Assert.notNull(verificationX509Credentials, "verificationX509Credentials cannot be null");
|
||||
for (Saml2X509Credential credential : verificationX509Credentials) {
|
||||
|
@ -457,12 +463,14 @@ public final class RelyingPartyRegistration {
|
|||
}
|
||||
Assert.notNull(singleSignOnServiceLocation, "singleSignOnServiceLocation cannot be null");
|
||||
Assert.notNull(singleSignOnServiceBinding, "singleSignOnServiceBinding cannot be null");
|
||||
Assert.notEmpty(signingMethodAlgorithms, "signingMethodAlgorithms cannot be empty");
|
||||
this.entityId = entityId;
|
||||
this.wantAuthnRequestsSigned = wantAuthnRequestsSigned;
|
||||
this.verificationX509Credentials = verificationX509Credentials;
|
||||
this.encryptionX509Credentials = encryptionX509Credentials;
|
||||
this.singleSignOnServiceLocation = singleSignOnServiceLocation;
|
||||
this.singleSignOnServiceBinding = singleSignOnServiceBinding;
|
||||
this.signingMethodAlgorithms = signingMethodAlgorithms;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -542,6 +550,15 @@ public final class RelyingPartyRegistration {
|
|||
return this.singleSignOnServiceBinding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of preferred signature algorithm URIs, in preference order.
|
||||
* @return the list of signature algorithm URIs
|
||||
* @since 5.5
|
||||
*/
|
||||
public List<String> getSigningMethodAlgorithms() {
|
||||
return this.signingMethodAlgorithms;
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
|
||||
private String entityId;
|
||||
|
@ -556,6 +573,8 @@ public final class RelyingPartyRegistration {
|
|||
|
||||
private Saml2MessageBinding singleSignOnServiceBinding = Saml2MessageBinding.REDIRECT;
|
||||
|
||||
private List<String> signingMethodAlgorithms = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Set the asserting party's <a href=
|
||||
* "https://wiki.shibboleth.net/confluence/display/CONCEPT/EntityNaming">EntityID</a>.
|
||||
|
@ -639,15 +658,31 @@ public final class RelyingPartyRegistration {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply this {@link Consumer} to the list of signature algorithm URIs
|
||||
* @param signingMethodAlgorithmsConsumer a {@link Consumer} of the list of
|
||||
* signature algorithm URIs
|
||||
* @return this {@code Builder}
|
||||
* @since 5.5
|
||||
*/
|
||||
public Builder signingMethodAlgorithms(Consumer<List<String>> signingMethodAlgorithmsConsumer) {
|
||||
signingMethodAlgorithmsConsumer.accept(this.signingMethodAlgorithms);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an immutable ProviderDetails object representing the configuration
|
||||
* for an Identity Provider, IDP
|
||||
* @return immutable ProviderDetails object
|
||||
*/
|
||||
public AssertingPartyDetails build() {
|
||||
List<String> signingMethodAlgorithmsCopy = this.signingMethodAlgorithms.isEmpty()
|
||||
? Arrays.asList(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256)
|
||||
: Collections.unmodifiableList(this.signingMethodAlgorithms);
|
||||
|
||||
return new AssertingPartyDetails(this.entityId, this.wantAuthnRequestsSigned,
|
||||
this.verificationX509Credentials, this.encryptionX509Credentials,
|
||||
this.singleSignOnServiceLocation, this.singleSignOnServiceBinding);
|
||||
this.singleSignOnServiceLocation, this.singleSignOnServiceBinding, signingMethodAlgorithmsCopy);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@ import org.opensaml.saml.saml2.core.impl.EncryptedAssertionBuilder;
|
|||
import org.opensaml.saml.saml2.core.impl.EncryptedIDBuilder;
|
||||
import org.opensaml.saml.saml2.core.impl.NameIDBuilder;
|
||||
import org.opensaml.xmlsec.encryption.impl.EncryptedDataBuilder;
|
||||
import org.opensaml.xmlsec.signature.support.SignatureConstants;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
|
@ -463,6 +464,17 @@ public class OpenSamlAuthenticationProviderTests {
|
|||
verify(context, atLeastOnce()).getStaticParameters();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWithSHA1SignatureThenItSucceeds() throws Exception {
|
||||
Response response = TestOpenSamlObjects.response();
|
||||
Assertion assertion = TestOpenSamlObjects.signed(TestOpenSamlObjects.assertion(),
|
||||
TestSaml2X509Credentials.assertingPartySigningCredential(), RELYING_PARTY_ENTITY_ID,
|
||||
SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1);
|
||||
response.getAssertions().add(assertion);
|
||||
Saml2AuthenticationToken token = token(response, verifying(registration()));
|
||||
this.provider.authenticate(token);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAssertionValidatorWhenNullThenIllegalArgument() {
|
||||
// @formatter:off
|
||||
|
|
|
@ -240,6 +240,22 @@ public class OpenSamlAuthenticationRequestFactoryTests {
|
|||
assertThat(inflated).contains("ProtocolBinding=\"" + SAMLConstants.SAML2_REDIRECT_BINDING_URI + "\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createRedirectAuthenticationRequestWhenSHA1SignRequestThenSignatureIsPresent() {
|
||||
RelyingPartyRegistration relyingPartyRegistration = this.relyingPartyRegistrationBuilder
|
||||
.assertingPartyDetails(
|
||||
(a) -> a.signingMethodAlgorithms((c) -> c.add(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1)))
|
||||
.build();
|
||||
Saml2AuthenticationRequestContext context = this.contextBuilder.relayState("Relay State Value")
|
||||
.relyingPartyRegistration(relyingPartyRegistration).build();
|
||||
Saml2RedirectAuthenticationRequest result = this.factory.createRedirectAuthenticationRequest(context);
|
||||
assertThat(result.getSamlRequest()).isNotEmpty();
|
||||
assertThat(result.getRelayState()).isEqualTo("Relay State Value");
|
||||
assertThat(result.getSigAlg()).isEqualTo(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1);
|
||||
assertThat(result.getSignature()).isNotNull();
|
||||
assertThat(result.getBinding()).isEqualTo(Saml2MessageBinding.REDIRECT);
|
||||
}
|
||||
|
||||
private AuthnRequest getAuthNRequest(Saml2MessageBinding binding) {
|
||||
AbstractSaml2AuthenticationRequest result = (binding == Saml2MessageBinding.REDIRECT)
|
||||
? this.factory.createRedirectAuthenticationRequest(this.context)
|
||||
|
|
|
@ -205,11 +205,12 @@ public final class TestOpenSamlObjects {
|
|||
return CredentialSupport.getSimpleCredential(credential.getCertificate(), credential.getPrivateKey());
|
||||
}
|
||||
|
||||
static <T extends SignableSAMLObject> T signed(T signable, Saml2X509Credential credential, String entityId) {
|
||||
static <T extends SignableSAMLObject> T signed(T signable, Saml2X509Credential credential, String entityId,
|
||||
String signAlgorithmUri) {
|
||||
SignatureSigningParameters parameters = new SignatureSigningParameters();
|
||||
Credential signingCredential = getSigningCredential(credential, entityId);
|
||||
parameters.setSigningCredential(signingCredential);
|
||||
parameters.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256);
|
||||
parameters.setSignatureAlgorithm(signAlgorithmUri);
|
||||
parameters.setSignatureReferenceDigestMethod(SignatureConstants.ALGO_ID_DIGEST_SHA256);
|
||||
parameters.setSignatureCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
|
||||
try {
|
||||
|
@ -221,6 +222,10 @@ public final class TestOpenSamlObjects {
|
|||
return signable;
|
||||
}
|
||||
|
||||
static <T extends SignableSAMLObject> T signed(T signable, Saml2X509Credential credential, String entityId) {
|
||||
return signed(signable, credential, entityId, SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256);
|
||||
}
|
||||
|
||||
static EncryptedAssertion encrypted(Assertion assertion, Saml2X509Credential credential) {
|
||||
X509Certificate certificate = credential.getCertificate();
|
||||
Encrypter encrypter = getEncrypter(certificate);
|
||||
|
|
Loading…
Reference in New Issue