Skip to content

Commit 9ab3abb

Browse files
committed
Add support for SAML2 relying party registration's decryption credentials
Closes gh-23705
1 parent 10f887a commit 9ab3abb

File tree

4 files changed

+82
-10
lines changed

4 files changed

+82
-10
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/saml2/Saml2RelyingPartyProperties.java

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ public static class Registration {
6363

6464
private final Signing signing = new Signing();
6565

66+
private final Decryption decryption = new Decryption();
67+
6668
/**
6769
* Remote SAML Identity Provider.
6870
*/
@@ -84,6 +86,10 @@ public Signing getSigning() {
8486
return this.signing;
8587
}
8688

89+
public Decryption getDecryption() {
90+
return this.decryption;
91+
}
92+
8793
public Identityprovider getIdentityprovider() {
8894
return this.identityprovider;
8995
}
@@ -123,8 +129,7 @@ public void setBinding(Saml2MessageBinding binding) {
123129
public static class Signing {
124130

125131
/**
126-
* Credentials used for signing and decrypting the SAML authentication
127-
* request.
132+
* Credentials used for signing the SAML authentication request.
128133
*/
129134
private List<Credential> credentials = new ArrayList<>();
130135

@@ -139,7 +144,7 @@ public void setCredentials(List<Credential> credentials) {
139144
public static class Credential {
140145

141146
/**
142-
* Private key used for signing or decrypting.
147+
* Private key used for signing.
143148
*/
144149
private Resource privateKeyLocation;
145150

@@ -170,6 +175,53 @@ public void setCertificateLocation(Resource certificate) {
170175

171176
}
172177

178+
public static class Decryption {
179+
180+
/**
181+
* Credentials used for decrypting the SAML authentication request.
182+
*/
183+
private List<Credential> credentials = new ArrayList<>();
184+
185+
public List<Credential> getCredentials() {
186+
return this.credentials;
187+
}
188+
189+
public void setCredentials(List<Credential> credentials) {
190+
this.credentials = credentials;
191+
}
192+
193+
public static class Credential {
194+
195+
/**
196+
* Private key used for decrypting.
197+
*/
198+
private Resource privateKeyLocation;
199+
200+
/**
201+
* Relying Party X509Certificate shared with the identity provider.
202+
*/
203+
private Resource certificateLocation;
204+
205+
public Resource getPrivateKeyLocation() {
206+
return this.privateKeyLocation;
207+
}
208+
209+
public void setPrivateKeyLocation(Resource privateKey) {
210+
this.privateKeyLocation = privateKey;
211+
}
212+
213+
public Resource getCertificateLocation() {
214+
return this.certificateLocation;
215+
}
216+
217+
public void setCertificateLocation(Resource certificate) {
218+
this.certificateLocation = certificate;
219+
}
220+
221+
}
222+
223+
}
224+
173225
/**
174226
* Represents a remote Identity Provider.
175227
*/

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/saml2/Saml2RelyingPartyRegistrationConfiguration.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.util.stream.Collectors;
2727

2828
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
29+
import org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyProperties.Decryption;
2930
import org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyProperties.Identityprovider.Verification;
3031
import org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyProperties.Registration;
3132
import org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyProperties.Registration.Signing;
@@ -36,6 +37,7 @@
3637
import org.springframework.core.io.Resource;
3738
import org.springframework.security.converter.RsaKeyConverters;
3839
import org.springframework.security.saml2.core.Saml2X509Credential;
40+
import org.springframework.security.saml2.core.Saml2X509Credential.Saml2X509CredentialType;
3941
import org.springframework.security.saml2.provider.service.registration.InMemoryRelyingPartyRegistrationRepository;
4042
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
4143
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration.AssertingPartyDetails;
@@ -78,6 +80,8 @@ private RelyingPartyRegistration asRegistration(String id, Registration properti
7880
builder.assertingPartyDetails(mapIdentityProvider(properties, usingMetadata));
7981
builder.signingX509Credentials((credentials) -> properties.getSigning().getCredentials().stream()
8082
.map(this::asSigningCredential).forEach(credentials::add));
83+
builder.decryptionX509Credentials((credentials) -> properties.getDecryption().getCredentials().stream()
84+
.map(this::asDecryptionCredential).forEach(credentials::add));
8185
builder.assertingPartyDetails((details) -> details
8286
.verificationX509Credentials((credentials) -> properties.getIdentityprovider().getVerification()
8387
.getCredentials().stream().map(this::asVerificationCredential).forEach(credentials::add)));
@@ -111,8 +115,13 @@ private void validateSigningCredentials(Registration properties, boolean signReq
111115
private Saml2X509Credential asSigningCredential(Signing.Credential properties) {
112116
RSAPrivateKey privateKey = readPrivateKey(properties.getPrivateKeyLocation());
113117
X509Certificate certificate = readCertificate(properties.getCertificateLocation());
114-
return new Saml2X509Credential(privateKey, certificate, Saml2X509Credential.Saml2X509CredentialType.SIGNING,
115-
Saml2X509Credential.Saml2X509CredentialType.DECRYPTION);
118+
return new Saml2X509Credential(privateKey, certificate, Saml2X509CredentialType.SIGNING);
119+
}
120+
121+
private Saml2X509Credential asDecryptionCredential(Decryption.Credential properties) {
122+
RSAPrivateKey privateKey = readPrivateKey(properties.getPrivateKeyLocation());
123+
X509Certificate certificate = readCertificate(properties.getCertificateLocation());
124+
return new Saml2X509Credential(privateKey, certificate, Saml2X509CredentialType.DECRYPTION);
116125
}
117126

118127
private Saml2X509Credential asVerificationCredential(Verification.Credential properties) {

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/saml2/Saml2RelyingPartyAutoConfigurationTests.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ void relyingPartyRegistrationRepositoryBeanShouldBeCreatedWhenPropertiesPresent(
9898
assertThat(registration.getAssertingPartyDetails().getSingleSignOnServiceBinding())
9999
.isEqualTo(Saml2MessageBinding.POST);
100100
assertThat(registration.getAssertingPartyDetails().getWantAuthnRequestsSigned()).isEqualTo(false);
101-
assertThat(registration.getSigningX509Credentials()).isNotNull();
101+
assertThat(registration.getSigningX509Credentials()).hasSize(1);
102+
assertThat(registration.getDecryptionX509Credentials()).hasSize(1);
102103
assertThat(registration.getAssertingPartyDetails().getVerificationX509Credentials()).isNotNull();
103104
assertThat(registration.getEntityId()).isEqualTo("{baseUrl}/saml2/foo-entity-id");
104105
});
@@ -182,6 +183,8 @@ private String[] getPropertyValues() {
182183
return new String[] {
183184
PREFIX + ".foo.signing.credentials[0].private-key-location=classpath:saml/private-key-location",
184185
PREFIX + ".foo.signing.credentials[0].certificate-location=classpath:saml/certificate-location",
186+
PREFIX + ".foo.decryption.credentials[0].private-key-location=classpath:saml/private-key-location",
187+
PREFIX + ".foo.decryption.credentials[0].certificate-location=classpath:saml/certificate-location",
185188
PREFIX + ".foo.identityprovider.singlesignon.url=https://simplesaml-for-spring-saml.cfapps.io/saml2/idp/SSOService.php",
186189
PREFIX + ".foo.identityprovider.singlesignon.binding=post",
187190
PREFIX + ".foo.identityprovider.singlesignon.sign-request=false",

spring-boot-project/spring-boot-docs/src/docs/asciidoc/spring-boot-features.adoc

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3866,21 +3866,29 @@ You can register multiple relying parties under the `spring.security.saml2.relyi
38663866
relyingparty:
38673867
registration:
38683868
my-relying-party1:
3869-
signing.credentials:
3870-
- private-key-location: "path-to-private-key"
3871-
certificate-location: "path-to-certificate"
3869+
signing:
3870+
credentials:
3871+
- private-key-location: "path-to-private-key"
3872+
certificate-location: "path-to-certificate"
3873+
decryption:
3874+
credentials:
3875+
- private-key-location: "path-to-private-key"
3876+
certificate-location: "path-to-certificate"
38723877
identityprovider:
38733878
verification:
38743879
credentials:
38753880
- certificate-location: "path-to-verification-cert"
38763881
entity-id: "remote-idp-entity-id1"
38773882
sso-url: "https://remoteidp1.sso.url"
3878-
38793883
my-relying-party2:
38803884
signing:
38813885
credentials:
38823886
- private-key-location: "path-to-private-key"
38833887
certificate-location: "path-to-certificate"
3888+
decryption:
3889+
credentials:
3890+
- private-key-location: "path-to-private-key"
3891+
certificate-location: "path-to-certificate"
38843892
identityprovider:
38853893
verification:
38863894
credentials:

0 commit comments

Comments
 (0)