Add support for SAML2 relying party registration's decryption credentials
Closes gh-23705
This commit is contained in:
parent
10f887a5ad
commit
9ab3abb728
|
|
@ -63,6 +63,8 @@ public class Saml2RelyingPartyProperties {
|
|||
|
||||
private final Signing signing = new Signing();
|
||||
|
||||
private final Decryption decryption = new Decryption();
|
||||
|
||||
/**
|
||||
* Remote SAML Identity Provider.
|
||||
*/
|
||||
|
|
@ -84,6 +86,10 @@ public class Saml2RelyingPartyProperties {
|
|||
return this.signing;
|
||||
}
|
||||
|
||||
public Decryption getDecryption() {
|
||||
return this.decryption;
|
||||
}
|
||||
|
||||
public Identityprovider getIdentityprovider() {
|
||||
return this.identityprovider;
|
||||
}
|
||||
|
|
@ -123,8 +129,7 @@ public class Saml2RelyingPartyProperties {
|
|||
public static class Signing {
|
||||
|
||||
/**
|
||||
* Credentials used for signing and decrypting the SAML authentication
|
||||
* request.
|
||||
* Credentials used for signing the SAML authentication request.
|
||||
*/
|
||||
private List<Credential> credentials = new ArrayList<>();
|
||||
|
||||
|
|
@ -139,7 +144,7 @@ public class Saml2RelyingPartyProperties {
|
|||
public static class Credential {
|
||||
|
||||
/**
|
||||
* Private key used for signing or decrypting.
|
||||
* Private key used for signing.
|
||||
*/
|
||||
private Resource privateKeyLocation;
|
||||
|
||||
|
|
@ -170,6 +175,53 @@ public class Saml2RelyingPartyProperties {
|
|||
|
||||
}
|
||||
|
||||
public static class Decryption {
|
||||
|
||||
/**
|
||||
* Credentials used for decrypting the SAML authentication request.
|
||||
*/
|
||||
private List<Credential> credentials = new ArrayList<>();
|
||||
|
||||
public List<Credential> getCredentials() {
|
||||
return this.credentials;
|
||||
}
|
||||
|
||||
public void setCredentials(List<Credential> credentials) {
|
||||
this.credentials = credentials;
|
||||
}
|
||||
|
||||
public static class Credential {
|
||||
|
||||
/**
|
||||
* Private key used for decrypting.
|
||||
*/
|
||||
private Resource privateKeyLocation;
|
||||
|
||||
/**
|
||||
* Relying Party X509Certificate shared with the identity provider.
|
||||
*/
|
||||
private Resource certificateLocation;
|
||||
|
||||
public Resource getPrivateKeyLocation() {
|
||||
return this.privateKeyLocation;
|
||||
}
|
||||
|
||||
public void setPrivateKeyLocation(Resource privateKey) {
|
||||
this.privateKeyLocation = privateKey;
|
||||
}
|
||||
|
||||
public Resource getCertificateLocation() {
|
||||
return this.certificateLocation;
|
||||
}
|
||||
|
||||
public void setCertificateLocation(Resource certificate) {
|
||||
this.certificateLocation = certificate;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a remote Identity Provider.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import java.util.function.Consumer;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyProperties.Decryption;
|
||||
import org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyProperties.Identityprovider.Verification;
|
||||
import org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyProperties.Registration;
|
||||
import org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyProperties.Registration.Signing;
|
||||
|
|
@ -36,6 +37,7 @@ import org.springframework.context.annotation.Configuration;
|
|||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.security.converter.RsaKeyConverters;
|
||||
import org.springframework.security.saml2.core.Saml2X509Credential;
|
||||
import org.springframework.security.saml2.core.Saml2X509Credential.Saml2X509CredentialType;
|
||||
import org.springframework.security.saml2.provider.service.registration.InMemoryRelyingPartyRegistrationRepository;
|
||||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
|
||||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration.AssertingPartyDetails;
|
||||
|
|
@ -78,6 +80,8 @@ class Saml2RelyingPartyRegistrationConfiguration {
|
|||
builder.assertingPartyDetails(mapIdentityProvider(properties, usingMetadata));
|
||||
builder.signingX509Credentials((credentials) -> properties.getSigning().getCredentials().stream()
|
||||
.map(this::asSigningCredential).forEach(credentials::add));
|
||||
builder.decryptionX509Credentials((credentials) -> properties.getDecryption().getCredentials().stream()
|
||||
.map(this::asDecryptionCredential).forEach(credentials::add));
|
||||
builder.assertingPartyDetails((details) -> details
|
||||
.verificationX509Credentials((credentials) -> properties.getIdentityprovider().getVerification()
|
||||
.getCredentials().stream().map(this::asVerificationCredential).forEach(credentials::add)));
|
||||
|
|
@ -111,8 +115,13 @@ class Saml2RelyingPartyRegistrationConfiguration {
|
|||
private Saml2X509Credential asSigningCredential(Signing.Credential properties) {
|
||||
RSAPrivateKey privateKey = readPrivateKey(properties.getPrivateKeyLocation());
|
||||
X509Certificate certificate = readCertificate(properties.getCertificateLocation());
|
||||
return new Saml2X509Credential(privateKey, certificate, Saml2X509Credential.Saml2X509CredentialType.SIGNING,
|
||||
Saml2X509Credential.Saml2X509CredentialType.DECRYPTION);
|
||||
return new Saml2X509Credential(privateKey, certificate, Saml2X509CredentialType.SIGNING);
|
||||
}
|
||||
|
||||
private Saml2X509Credential asDecryptionCredential(Decryption.Credential properties) {
|
||||
RSAPrivateKey privateKey = readPrivateKey(properties.getPrivateKeyLocation());
|
||||
X509Certificate certificate = readCertificate(properties.getCertificateLocation());
|
||||
return new Saml2X509Credential(privateKey, certificate, Saml2X509CredentialType.DECRYPTION);
|
||||
}
|
||||
|
||||
private Saml2X509Credential asVerificationCredential(Verification.Credential properties) {
|
||||
|
|
|
|||
|
|
@ -98,7 +98,8 @@ class Saml2RelyingPartyAutoConfigurationTests {
|
|||
assertThat(registration.getAssertingPartyDetails().getSingleSignOnServiceBinding())
|
||||
.isEqualTo(Saml2MessageBinding.POST);
|
||||
assertThat(registration.getAssertingPartyDetails().getWantAuthnRequestsSigned()).isEqualTo(false);
|
||||
assertThat(registration.getSigningX509Credentials()).isNotNull();
|
||||
assertThat(registration.getSigningX509Credentials()).hasSize(1);
|
||||
assertThat(registration.getDecryptionX509Credentials()).hasSize(1);
|
||||
assertThat(registration.getAssertingPartyDetails().getVerificationX509Credentials()).isNotNull();
|
||||
assertThat(registration.getEntityId()).isEqualTo("{baseUrl}/saml2/foo-entity-id");
|
||||
});
|
||||
|
|
@ -182,6 +183,8 @@ class Saml2RelyingPartyAutoConfigurationTests {
|
|||
return new String[] {
|
||||
PREFIX + ".foo.signing.credentials[0].private-key-location=classpath:saml/private-key-location",
|
||||
PREFIX + ".foo.signing.credentials[0].certificate-location=classpath:saml/certificate-location",
|
||||
PREFIX + ".foo.decryption.credentials[0].private-key-location=classpath:saml/private-key-location",
|
||||
PREFIX + ".foo.decryption.credentials[0].certificate-location=classpath:saml/certificate-location",
|
||||
PREFIX + ".foo.identityprovider.singlesignon.url=https://simplesaml-for-spring-saml.cfapps.io/saml2/idp/SSOService.php",
|
||||
PREFIX + ".foo.identityprovider.singlesignon.binding=post",
|
||||
PREFIX + ".foo.identityprovider.singlesignon.sign-request=false",
|
||||
|
|
|
|||
|
|
@ -3866,21 +3866,29 @@ You can register multiple relying parties under the `spring.security.saml2.relyi
|
|||
relyingparty:
|
||||
registration:
|
||||
my-relying-party1:
|
||||
signing.credentials:
|
||||
- private-key-location: "path-to-private-key"
|
||||
certificate-location: "path-to-certificate"
|
||||
signing:
|
||||
credentials:
|
||||
- private-key-location: "path-to-private-key"
|
||||
certificate-location: "path-to-certificate"
|
||||
decryption:
|
||||
credentials:
|
||||
- private-key-location: "path-to-private-key"
|
||||
certificate-location: "path-to-certificate"
|
||||
identityprovider:
|
||||
verification:
|
||||
credentials:
|
||||
- certificate-location: "path-to-verification-cert"
|
||||
entity-id: "remote-idp-entity-id1"
|
||||
sso-url: "https://remoteidp1.sso.url"
|
||||
|
||||
my-relying-party2:
|
||||
signing:
|
||||
credentials:
|
||||
- private-key-location: "path-to-private-key"
|
||||
certificate-location: "path-to-certificate"
|
||||
decryption:
|
||||
credentials:
|
||||
- private-key-location: "path-to-private-key"
|
||||
certificate-location: "path-to-certificate"
|
||||
identityprovider:
|
||||
verification:
|
||||
credentials:
|
||||
|
|
|
|||
Loading…
Reference in New Issue