mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-07-03 17:22:13 +00:00
Separate RP and AP Credentials
Closes gh-8788
This commit is contained in:
parent
87cd1d73df
commit
56928f61f0
@ -0,0 +1,200 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2002-2020 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.springframework.security.saml2.core;
|
||||||
|
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import static java.util.Arrays.asList;
|
||||||
|
import static org.springframework.util.Assert.notEmpty;
|
||||||
|
import static org.springframework.util.Assert.notNull;
|
||||||
|
import static org.springframework.util.Assert.state;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object for holding a public certificate, any associated private key, and its intended
|
||||||
|
* <a href="https://www.oasis-open.org/committees/download.php/8958/sstc-saml-implementation-guidelines-draft-01.pdf">
|
||||||
|
* usages
|
||||||
|
* </a>
|
||||||
|
* (Line 584, Section 4.3 Credentials).
|
||||||
|
*
|
||||||
|
* @since 5.4
|
||||||
|
* @author Filip Hanik
|
||||||
|
* @author Josh Cummings
|
||||||
|
*/
|
||||||
|
public final class Saml2X509Credential {
|
||||||
|
public enum Saml2X509CredentialType {
|
||||||
|
VERIFICATION,
|
||||||
|
ENCRYPTION,
|
||||||
|
SIGNING,
|
||||||
|
DECRYPTION,
|
||||||
|
}
|
||||||
|
|
||||||
|
private final PrivateKey privateKey;
|
||||||
|
private final X509Certificate certificate;
|
||||||
|
private final Set<Saml2X509CredentialType> credentialTypes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link Saml2X509Credential} using the provided parameters
|
||||||
|
*
|
||||||
|
* @param certificate the credential's public certificiate
|
||||||
|
* @param types the credential's intended usages, must be one of {@link Saml2X509CredentialType#VERIFICATION} or
|
||||||
|
* {@link Saml2X509CredentialType#ENCRYPTION} or both.
|
||||||
|
*/
|
||||||
|
public Saml2X509Credential(X509Certificate certificate, Saml2X509CredentialType... types) {
|
||||||
|
this(null, false, certificate, types);
|
||||||
|
validateUsages(types, Saml2X509CredentialType.VERIFICATION, Saml2X509CredentialType.ENCRYPTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link Saml2X509Credential} using the provided parameters
|
||||||
|
*
|
||||||
|
* @param privateKey the credential's private key
|
||||||
|
* @param certificate the credential's public certificate
|
||||||
|
* @param types the credential's intended usages, must be one of {@link Saml2X509CredentialType#SIGNING} or
|
||||||
|
* {@link Saml2X509CredentialType#DECRYPTION} or both.
|
||||||
|
*/
|
||||||
|
public Saml2X509Credential(PrivateKey privateKey, X509Certificate certificate, Saml2X509CredentialType... types) {
|
||||||
|
this(privateKey, true, certificate, types);
|
||||||
|
validateUsages(types, Saml2X509CredentialType.SIGNING, Saml2X509CredentialType.DECRYPTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link Saml2X509Credential} using the provided parameters
|
||||||
|
*
|
||||||
|
* @param privateKey the credential's private key
|
||||||
|
* @param certificate the credential's public certificate
|
||||||
|
* @param types the credential's intended usages
|
||||||
|
*/
|
||||||
|
public Saml2X509Credential(PrivateKey privateKey, X509Certificate certificate, Set<Saml2X509CredentialType> types) {
|
||||||
|
Assert.notNull(certificate, "certificate cannot be null");
|
||||||
|
Assert.notNull(types, "credentialTypes cannot be null");
|
||||||
|
this.privateKey = privateKey;
|
||||||
|
this.certificate = certificate;
|
||||||
|
this.credentialTypes = types;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Saml2X509Credential(
|
||||||
|
PrivateKey privateKey,
|
||||||
|
boolean keyRequired,
|
||||||
|
X509Certificate certificate,
|
||||||
|
Saml2X509CredentialType... types) {
|
||||||
|
notNull(certificate, "certificate cannot be null");
|
||||||
|
notEmpty(types, "credentials types cannot be empty");
|
||||||
|
if (keyRequired) {
|
||||||
|
notNull(privateKey, "privateKey cannot be null");
|
||||||
|
}
|
||||||
|
this.privateKey = privateKey;
|
||||||
|
this.certificate = certificate;
|
||||||
|
this.credentialTypes = new LinkedHashSet<>(asList(types));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the private key for this credential
|
||||||
|
*
|
||||||
|
* @return the private key, may be null
|
||||||
|
* @see {@link #Saml2X509Credential(PrivateKey, X509Certificate, Saml2X509CredentialType...)}
|
||||||
|
*/
|
||||||
|
public PrivateKey getPrivateKey() {
|
||||||
|
return this.privateKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the public certificate for this credential
|
||||||
|
*
|
||||||
|
* @return the public certificate
|
||||||
|
*/
|
||||||
|
public X509Certificate getCertificate() {
|
||||||
|
return this.certificate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate whether this credential can be used for signing
|
||||||
|
*
|
||||||
|
* @return true if the credential has a {@link Saml2X509CredentialType#SIGNING} type
|
||||||
|
*/
|
||||||
|
public boolean isSigningCredential() {
|
||||||
|
return getCredentialTypes().contains(Saml2X509CredentialType.SIGNING);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate whether this credential can be used for decryption
|
||||||
|
*
|
||||||
|
* @return true if the credential has a {@link Saml2X509CredentialType#DECRYPTION} type
|
||||||
|
*/
|
||||||
|
public boolean isDecryptionCredential() {
|
||||||
|
return getCredentialTypes().contains(Saml2X509CredentialType.DECRYPTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate whether this credential can be used for verification
|
||||||
|
*
|
||||||
|
* @return true if the credential has a {@link Saml2X509CredentialType#VERIFICATION} type
|
||||||
|
*/
|
||||||
|
public boolean isVerificationCredential() {
|
||||||
|
return getCredentialTypes().contains(Saml2X509CredentialType.VERIFICATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate whether this credential can be used for encryption
|
||||||
|
*
|
||||||
|
* @return true if the credential has a {@link Saml2X509CredentialType#ENCRYPTION} type
|
||||||
|
*/
|
||||||
|
public boolean isEncryptionCredential() {
|
||||||
|
return getCredentialTypes().contains(Saml2X509CredentialType.ENCRYPTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List all this credential's intended usages
|
||||||
|
*
|
||||||
|
* @return the set of this credential's intended usages
|
||||||
|
*/
|
||||||
|
public Set<Saml2X509CredentialType> getCredentialTypes() {
|
||||||
|
return this.credentialTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
Saml2X509Credential that = (Saml2X509Credential) o;
|
||||||
|
return Objects.equals(this.privateKey, that.privateKey) &&
|
||||||
|
this.certificate.equals(that.certificate) &&
|
||||||
|
this.credentialTypes.equals(that.credentialTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(this.privateKey, this.certificate, this.credentialTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateUsages(Saml2X509CredentialType[] usages, Saml2X509CredentialType... validUsages) {
|
||||||
|
for (Saml2X509CredentialType usage : usages) {
|
||||||
|
boolean valid = false;
|
||||||
|
for (Saml2X509CredentialType validUsage : validUsages) {
|
||||||
|
if (usage == validUsage) {
|
||||||
|
valid = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
state(valid, () -> usage +" is not a valid usage for this credential");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2019 the original author or authors.
|
* Copyright 2002-2020 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -18,8 +18,11 @@ package org.springframework.security.saml2.credentials;
|
|||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import static java.util.Arrays.asList;
|
import static java.util.Arrays.asList;
|
||||||
import static org.springframework.util.Assert.notEmpty;
|
import static org.springframework.util.Assert.notEmpty;
|
||||||
import static org.springframework.util.Assert.notNull;
|
import static org.springframework.util.Assert.notNull;
|
||||||
@ -32,8 +35,14 @@ import static org.springframework.util.Assert.state;
|
|||||||
* Line: 584, Section 4.3 Credentials Used for both signing, signature verification and encryption/decryption
|
* Line: 584, Section 4.3 Credentials Used for both signing, signature verification and encryption/decryption
|
||||||
*
|
*
|
||||||
* @since 5.2
|
* @since 5.2
|
||||||
|
* @deprecated Use {@link org.springframework.security.saml2.core.Saml2X509Credential} instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public class Saml2X509Credential {
|
public class Saml2X509Credential {
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link org.springframework.security.saml2.core.Saml2X509Credential.Saml2X509CredentialType} instead
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public enum Saml2X509CredentialType {
|
public enum Saml2X509CredentialType {
|
||||||
VERIFICATION,
|
VERIFICATION,
|
||||||
ENCRYPTION,
|
ENCRYPTION,
|
||||||
@ -70,6 +79,14 @@ public class Saml2X509Credential {
|
|||||||
validateUsages(types, Saml2X509CredentialType.SIGNING, Saml2X509CredentialType.DECRYPTION);
|
validateUsages(types, Saml2X509CredentialType.SIGNING, Saml2X509CredentialType.DECRYPTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Saml2X509Credential(PrivateKey privateKey, X509Certificate certificate, Set<Saml2X509CredentialType> types) {
|
||||||
|
Assert.notNull(certificate, "certificate cannot be null");
|
||||||
|
Assert.notEmpty(types, "credentialTypes cannot be empty");
|
||||||
|
this.privateKey = privateKey;
|
||||||
|
this.certificate = certificate;
|
||||||
|
this.credentialTypes = types;
|
||||||
|
}
|
||||||
|
|
||||||
private Saml2X509Credential(
|
private Saml2X509Credential(
|
||||||
PrivateKey privateKey,
|
PrivateKey privateKey,
|
||||||
boolean keyRequired,
|
boolean keyRequired,
|
||||||
@ -147,6 +164,21 @@ public class Saml2X509Credential {
|
|||||||
return this.certificate;
|
return this.certificate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
Saml2X509Credential that = (Saml2X509Credential) o;
|
||||||
|
return Objects.equals(this.privateKey, that.privateKey) &&
|
||||||
|
this.certificate.equals(that.certificate) &&
|
||||||
|
this.credentialTypes.equals(that.credentialTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(this.privateKey, this.certificate, this.credentialTypes);
|
||||||
|
}
|
||||||
|
|
||||||
private void validateUsages(Saml2X509CredentialType[] usages, Saml2X509CredentialType... validUsages) {
|
private void validateUsages(Saml2X509CredentialType[] usages, Saml2X509CredentialType... validUsages) {
|
||||||
for (Saml2X509CredentialType usage : usages) {
|
for (Saml2X509CredentialType usage : usages) {
|
||||||
boolean valid = false;
|
boolean valid = false;
|
||||||
|
@ -99,7 +99,7 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
|||||||
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
|
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
|
||||||
import org.springframework.security.saml2.Saml2Exception;
|
import org.springframework.security.saml2.Saml2Exception;
|
||||||
import org.springframework.security.saml2.core.Saml2Error;
|
import org.springframework.security.saml2.core.Saml2Error;
|
||||||
import org.springframework.security.saml2.credentials.Saml2X509Credential;
|
import org.springframework.security.saml2.core.Saml2X509Credential;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
@ -480,7 +480,8 @@ public final class OpenSamlAuthenticationProvider implements AuthenticationProvi
|
|||||||
|
|
||||||
private SignatureTrustEngine buildSignatureTrustEngine(Saml2AuthenticationToken token) {
|
private SignatureTrustEngine buildSignatureTrustEngine(Saml2AuthenticationToken token) {
|
||||||
Set<Credential> credentials = new HashSet<>();
|
Set<Credential> credentials = new HashSet<>();
|
||||||
for (Saml2X509Credential key : token.getRelyingPartyRegistration().getVerificationCredentials()) {
|
Collection<Saml2X509Credential> keys = token.getRelyingPartyRegistration().getAssertingPartyDetails().getVerificationX509Credentials();
|
||||||
|
for (Saml2X509Credential key : keys) {
|
||||||
BasicX509Credential cred = new BasicX509Credential(key.getCertificate());
|
BasicX509Credential cred = new BasicX509Credential(key.getCertificate());
|
||||||
cred.setUsageType(UsageType.SIGNING);
|
cred.setUsageType(UsageType.SIGNING);
|
||||||
cred.setEntityId(token.getRelyingPartyRegistration().getAssertingPartyDetails().getEntityId());
|
cred.setEntityId(token.getRelyingPartyRegistration().getAssertingPartyDetails().getEntityId());
|
||||||
@ -536,8 +537,8 @@ public final class OpenSamlAuthenticationProvider implements AuthenticationProvi
|
|||||||
return encrypted -> {
|
return encrypted -> {
|
||||||
Saml2AuthenticationException last =
|
Saml2AuthenticationException last =
|
||||||
authException(DECRYPTION_ERROR, "No valid decryption credentials found.");
|
authException(DECRYPTION_ERROR, "No valid decryption credentials found.");
|
||||||
List<Saml2X509Credential> decryptionCredentials = token.getRelyingPartyRegistration().getDecryptionCredentials();
|
Collection<Saml2X509Credential> keys = token.getRelyingPartyRegistration().getDecryptionX509Credentials();
|
||||||
for (Saml2X509Credential key : decryptionCredentials) {
|
for (Saml2X509Credential key : keys) {
|
||||||
Decrypter decrypter = getDecrypter(key);
|
Decrypter decrypter = getDecrypter(key);
|
||||||
try {
|
try {
|
||||||
return decrypter.decrypt(encrypted);
|
return decrypter.decrypt(encrypted);
|
||||||
@ -618,7 +619,8 @@ public final class OpenSamlAuthenticationProvider implements AuthenticationProvi
|
|||||||
|
|
||||||
private SignatureTrustEngine buildSignatureTrustEngine(Saml2AuthenticationToken token) {
|
private SignatureTrustEngine buildSignatureTrustEngine(Saml2AuthenticationToken token) {
|
||||||
Set<Credential> credentials = new HashSet<>();
|
Set<Credential> credentials = new HashSet<>();
|
||||||
for (Saml2X509Credential key : token.getRelyingPartyRegistration().getVerificationCredentials()) {
|
Collection<Saml2X509Credential> keys = token.getRelyingPartyRegistration().getAssertingPartyDetails().getVerificationX509Credentials();
|
||||||
|
for (Saml2X509Credential key : keys) {
|
||||||
BasicX509Credential cred = new BasicX509Credential(key.getCertificate());
|
BasicX509Credential cred = new BasicX509Credential(key.getCertificate());
|
||||||
cred.setUsageType(UsageType.SIGNING);
|
cred.setUsageType(UsageType.SIGNING);
|
||||||
cred.setEntityId(token.getRelyingPartyRegistration().getAssertingPartyDetails().getEntityId());
|
cred.setEntityId(token.getRelyingPartyRegistration().getAssertingPartyDetails().getEntityId());
|
||||||
@ -730,8 +732,8 @@ public final class OpenSamlAuthenticationProvider implements AuthenticationProvi
|
|||||||
return encrypted -> {
|
return encrypted -> {
|
||||||
Saml2AuthenticationException last =
|
Saml2AuthenticationException last =
|
||||||
authException(DECRYPTION_ERROR, "No valid decryption credentials found.");
|
authException(DECRYPTION_ERROR, "No valid decryption credentials found.");
|
||||||
List<Saml2X509Credential> decryptionCredentials = token.getRelyingPartyRegistration().getDecryptionCredentials();
|
Collection<Saml2X509Credential> keys = token.getRelyingPartyRegistration().getDecryptionX509Credentials();
|
||||||
for (Saml2X509Credential key : decryptionCredentials) {
|
for (Saml2X509Credential key : keys) {
|
||||||
Decrypter decrypter = getDecrypter(key);
|
Decrypter decrypter = getDecrypter(key);
|
||||||
try {
|
try {
|
||||||
return (NameID) decrypter.decrypt(encrypted);
|
return (NameID) decrypter.decrypt(encrypted);
|
||||||
|
@ -16,22 +16,36 @@
|
|||||||
|
|
||||||
package org.springframework.security.saml2.provider.service.authentication;
|
package org.springframework.security.saml2.provider.service.authentication;
|
||||||
|
|
||||||
|
import java.security.PrivateKey;
|
||||||
import java.time.Clock;
|
import java.time.Clock;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.List;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
|
import org.opensaml.core.xml.io.MarshallingException;
|
||||||
import org.opensaml.saml.common.xml.SAMLConstants;
|
import org.opensaml.saml.common.xml.SAMLConstants;
|
||||||
import org.opensaml.saml.saml2.core.AuthnRequest;
|
import org.opensaml.saml.saml2.core.AuthnRequest;
|
||||||
import org.opensaml.saml.saml2.core.Issuer;
|
import org.opensaml.saml.saml2.core.Issuer;
|
||||||
|
import org.opensaml.security.SecurityException;
|
||||||
|
import org.opensaml.security.credential.BasicCredential;
|
||||||
|
import org.opensaml.security.credential.Credential;
|
||||||
|
import org.opensaml.security.credential.CredentialSupport;
|
||||||
|
import org.opensaml.security.credential.UsageType;
|
||||||
|
import org.opensaml.xmlsec.SignatureSigningParameters;
|
||||||
|
import org.opensaml.xmlsec.signature.support.SignatureConstants;
|
||||||
|
import org.opensaml.xmlsec.signature.support.SignatureException;
|
||||||
|
import org.opensaml.xmlsec.signature.support.SignatureSupport;
|
||||||
|
|
||||||
import org.springframework.core.convert.converter.Converter;
|
import org.springframework.core.convert.converter.Converter;
|
||||||
import org.springframework.security.saml2.credentials.Saml2X509Credential;
|
import org.springframework.security.saml2.Saml2Exception;
|
||||||
|
import org.springframework.security.saml2.core.Saml2X509Credential;
|
||||||
import org.springframework.security.saml2.provider.service.authentication.Saml2RedirectAuthenticationRequest.Builder;
|
import org.springframework.security.saml2.provider.service.authentication.Saml2RedirectAuthenticationRequest.Builder;
|
||||||
|
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
@ -62,7 +76,14 @@ public class OpenSamlAuthenticationRequestFactory implements Saml2Authentication
|
|||||||
AuthnRequest authnRequest = createAuthnRequest(request.getIssuer(),
|
AuthnRequest authnRequest = createAuthnRequest(request.getIssuer(),
|
||||||
request.getDestination(), request.getAssertionConsumerServiceUrl(),
|
request.getDestination(), request.getAssertionConsumerServiceUrl(),
|
||||||
this.protocolBindingResolver.convert(null));
|
this.protocolBindingResolver.convert(null));
|
||||||
return this.saml.serialize(authnRequest, request.getCredentials());
|
for (org.springframework.security.saml2.credentials.Saml2X509Credential credential : request.getCredentials()) {
|
||||||
|
if (credential.isSigningCredential()) {
|
||||||
|
Credential cred = getSigningCredential(credential.getCertificate(), credential.getPrivateKey(), request.getIssuer());
|
||||||
|
signAuthnRequest(authnRequest, cred);
|
||||||
|
return this.saml.serialize(authnRequest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("No signing credential provided");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -72,7 +93,7 @@ public class OpenSamlAuthenticationRequestFactory implements Saml2Authentication
|
|||||||
public Saml2PostAuthenticationRequest createPostAuthenticationRequest(Saml2AuthenticationRequestContext context) {
|
public Saml2PostAuthenticationRequest createPostAuthenticationRequest(Saml2AuthenticationRequestContext context) {
|
||||||
AuthnRequest authnRequest = createAuthnRequest(context);
|
AuthnRequest authnRequest = createAuthnRequest(context);
|
||||||
String xml = context.getRelyingPartyRegistration().getAssertingPartyDetails().getWantAuthnRequestsSigned() ?
|
String xml = context.getRelyingPartyRegistration().getAssertingPartyDetails().getWantAuthnRequestsSigned() ?
|
||||||
this.saml.serialize(authnRequest, context.getRelyingPartyRegistration().getSigningCredentials()) :
|
signThenSerialize(authnRequest, context.getRelyingPartyRegistration()) :
|
||||||
this.saml.serialize(authnRequest);
|
this.saml.serialize(authnRequest);
|
||||||
|
|
||||||
return Saml2PostAuthenticationRequest.withAuthenticationRequestContext(context)
|
return Saml2PostAuthenticationRequest.withAuthenticationRequestContext(context)
|
||||||
@ -93,7 +114,7 @@ public class OpenSamlAuthenticationRequestFactory implements Saml2Authentication
|
|||||||
.relayState(context.getRelayState());
|
.relayState(context.getRelayState());
|
||||||
|
|
||||||
if (context.getRelyingPartyRegistration().getAssertingPartyDetails().getWantAuthnRequestsSigned()) {
|
if (context.getRelyingPartyRegistration().getAssertingPartyDetails().getWantAuthnRequestsSigned()) {
|
||||||
List<Saml2X509Credential> signingCredentials = context.getRelyingPartyRegistration().getSigningCredentials();
|
Collection<Saml2X509Credential> signingCredentials = context.getRelyingPartyRegistration().getSigningX509Credentials();
|
||||||
Map<String, String> signedParams = this.saml.signQueryParameters(
|
Map<String, String> signedParams = this.saml.signQueryParameters(
|
||||||
signingCredentials,
|
signingCredentials,
|
||||||
deflatedAndEncoded,
|
deflatedAndEncoded,
|
||||||
@ -178,4 +199,34 @@ public class OpenSamlAuthenticationRequestFactory implements Saml2Authentication
|
|||||||
}
|
}
|
||||||
this.protocolBindingResolver = context -> protocolBinding;
|
this.protocolBindingResolver = context -> protocolBinding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String signThenSerialize(AuthnRequest authnRequest, RelyingPartyRegistration relyingPartyRegistration) {
|
||||||
|
for (Saml2X509Credential credential : relyingPartyRegistration.getSigningX509Credentials()) {
|
||||||
|
Credential cred = getSigningCredential(
|
||||||
|
credential.getCertificate(), credential.getPrivateKey(), relyingPartyRegistration.getEntityId());
|
||||||
|
signAuthnRequest(authnRequest, cred);
|
||||||
|
return this.saml.serialize(authnRequest);
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("No signing credential provided");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void signAuthnRequest(AuthnRequest authnRequest, Credential credential) {
|
||||||
|
SignatureSigningParameters parameters = new SignatureSigningParameters();
|
||||||
|
parameters.setSigningCredential(credential);
|
||||||
|
parameters.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256);
|
||||||
|
parameters.setSignatureReferenceDigestMethod(SignatureConstants.ALGO_ID_DIGEST_SHA256);
|
||||||
|
parameters.setSignatureCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
|
||||||
|
try {
|
||||||
|
SignatureSupport.signObject(authnRequest, parameters);
|
||||||
|
} catch (MarshallingException | SignatureException | SecurityException e) {
|
||||||
|
throw new Saml2Exception(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Credential getSigningCredential(X509Certificate certificate, PrivateKey privateKey, String entityId) {
|
||||||
|
BasicCredential cred = CredentialSupport.getSimpleCredential(certificate, privateKey);
|
||||||
|
cred.setEntityId(entityId);
|
||||||
|
cred.setUsageType(UsageType.SIGNING);
|
||||||
|
return cred;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,9 +19,9 @@ package org.springframework.security.saml2.provider.service.authentication;
|
|||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.xml.XMLConstants;
|
import javax.xml.XMLConstants;
|
||||||
import javax.xml.namespace.QName;
|
import javax.xml.namespace.QName;
|
||||||
@ -62,7 +62,7 @@ import org.w3c.dom.Document;
|
|||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
import org.springframework.security.saml2.Saml2Exception;
|
import org.springframework.security.saml2.Saml2Exception;
|
||||||
import org.springframework.security.saml2.credentials.Saml2X509Credential;
|
import org.springframework.security.saml2.core.Saml2X509Credential;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.web.util.UriUtils;
|
import org.springframework.web.util.UriUtils;
|
||||||
|
|
||||||
@ -187,13 +187,6 @@ final class OpenSamlImplementation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String serialize(AuthnRequest authnRequest, List<Saml2X509Credential> signingCredentials) {
|
|
||||||
if (hasSigningCredential(signingCredentials) != null) {
|
|
||||||
signAuthnRequest(authnRequest, signingCredentials);
|
|
||||||
}
|
|
||||||
return serialize(authnRequest);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns query parameter after creating a Query String signature
|
* Returns query parameter after creating a Query String signature
|
||||||
* All return values are unencoded and will need to be encoded prior to sending
|
* All return values are unencoded and will need to be encoded prior to sending
|
||||||
@ -205,7 +198,7 @@ final class OpenSamlImplementation {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
Map<String, String> signQueryParameters(
|
Map<String, String> signQueryParameters(
|
||||||
List<Saml2X509Credential> signingCredentials,
|
Collection<Saml2X509Credential> signingCredentials,
|
||||||
String samlRequest,
|
String samlRequest,
|
||||||
String relayState) {
|
String relayState) {
|
||||||
Assert.notNull(samlRequest, "samlRequest cannot be null");
|
Assert.notNull(samlRequest, "samlRequest cannot be null");
|
||||||
@ -280,7 +273,7 @@ final class OpenSamlImplementation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private Saml2X509Credential hasSigningCredential(List<Saml2X509Credential> credentials) {
|
private Saml2X509Credential hasSigningCredential(Collection<Saml2X509Credential> credentials) {
|
||||||
for (Saml2X509Credential c : credentials) {
|
for (Saml2X509Credential c : credentials) {
|
||||||
if (c.isSigningCredential()) {
|
if (c.isSigningCredential()) {
|
||||||
return c;
|
return c;
|
||||||
@ -289,7 +282,7 @@ final class OpenSamlImplementation {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Credential getSigningCredential(List<Saml2X509Credential> signingCredential,
|
private Credential getSigningCredential(Collection<Saml2X509Credential> signingCredential,
|
||||||
String localSpEntityId
|
String localSpEntityId
|
||||||
) {
|
) {
|
||||||
Saml2X509Credential credential = hasSigningCredential(signingCredential);
|
Saml2X509Credential credential = hasSigningCredential(signingCredential);
|
||||||
@ -302,7 +295,7 @@ final class OpenSamlImplementation {
|
|||||||
return cred;
|
return cred;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void signAuthnRequest(AuthnRequest authnRequest, List<Saml2X509Credential> signingCredentials) {
|
private void signAuthnRequest(AuthnRequest authnRequest, Collection<Saml2X509Credential> signingCredentials) {
|
||||||
SignatureSigningParameters parameters = new SignatureSigningParameters();
|
SignatureSigningParameters parameters = new SignatureSigningParameters();
|
||||||
Credential credential = getSigningCredential(signingCredentials, authnRequest.getIssuer().getValue());
|
Credential credential = getSigningCredential(signingCredentials, authnRequest.getIssuer().getValue());
|
||||||
parameters.setSigningCredential(credential);
|
parameters.setSigningCredential(credential);
|
||||||
|
@ -16,12 +16,12 @@
|
|||||||
|
|
||||||
package org.springframework.security.saml2.provider.service.authentication;
|
package org.springframework.security.saml2.provider.service.authentication;
|
||||||
|
|
||||||
import org.springframework.security.saml2.Saml2Exception;
|
|
||||||
import org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType;
|
|
||||||
import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
|
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
import org.springframework.security.saml2.Saml2Exception;
|
||||||
|
import org.springframework.security.saml2.core.Saml2X509Credential.Saml2X509CredentialType;
|
||||||
|
import org.springframework.security.saml2.provider.service.registration.Saml2MessageBinding;
|
||||||
|
|
||||||
import static org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationRequest.withAuthenticationRequestContext;
|
import static org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationRequest.withAuthenticationRequestContext;
|
||||||
import static org.springframework.security.saml2.provider.service.authentication.Saml2Utils.samlDeflate;
|
import static org.springframework.security.saml2.provider.service.authentication.Saml2Utils.samlDeflate;
|
||||||
import static org.springframework.security.saml2.provider.service.authentication.Saml2Utils.samlEncode;
|
import static org.springframework.security.saml2.provider.service.authentication.Saml2Utils.samlEncode;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2019 the original author or authors.
|
* Copyright 2002-2020 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -16,15 +16,18 @@
|
|||||||
|
|
||||||
package org.springframework.security.saml2.provider.service.registration;
|
package org.springframework.security.saml2.provider.service.registration;
|
||||||
|
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import org.springframework.security.saml2.credentials.Saml2X509Credential;
|
import org.springframework.security.saml2.core.Saml2X509Credential;
|
||||||
import org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType;
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -51,11 +54,11 @@ import org.springframework.util.Assert;
|
|||||||
* RelyingPartyRegistration rp = RelyingPartyRegistration.withRegistrationId(registrationId)
|
* RelyingPartyRegistration rp = RelyingPartyRegistration.withRegistrationId(registrationId)
|
||||||
* .entityId(relyingPartyEntityId)
|
* .entityId(relyingPartyEntityId)
|
||||||
* .assertionConsumerServiceLocation(assertingConsumerServiceLocation)
|
* .assertionConsumerServiceLocation(assertingConsumerServiceLocation)
|
||||||
* .credentials(c -> c.add(relyingPartySigningCredential))
|
* .signingX509Credentials(c -> c.add(relyingPartySigningCredential))
|
||||||
* .assertingPartyDetails(details -> details
|
* .assertingPartyDetails(details -> details
|
||||||
* .entityId(assertingPartyEntityId));
|
* .entityId(assertingPartyEntityId));
|
||||||
* .singleSignOnServiceLocation(singleSignOnServiceLocation))
|
* .singleSignOnServiceLocation(singleSignOnServiceLocation))
|
||||||
* .credentials(c -> c.add(assertingPartyVerificationCredential))
|
* .verifyingX509Credentials(c -> c.add(assertingPartyVerificationCredential))
|
||||||
* .build();
|
* .build();
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
@ -70,7 +73,9 @@ public class RelyingPartyRegistration {
|
|||||||
private final String assertionConsumerServiceLocation;
|
private final String assertionConsumerServiceLocation;
|
||||||
private final Saml2MessageBinding assertionConsumerServiceBinding;
|
private final Saml2MessageBinding assertionConsumerServiceBinding;
|
||||||
private final ProviderDetails providerDetails;
|
private final ProviderDetails providerDetails;
|
||||||
private final List<Saml2X509Credential> credentials;
|
private final List<org.springframework.security.saml2.credentials.Saml2X509Credential> credentials;
|
||||||
|
private final Collection<Saml2X509Credential> decryptionX509Credentials;
|
||||||
|
private final Collection<Saml2X509Credential> signingX509Credentials;
|
||||||
|
|
||||||
private RelyingPartyRegistration(
|
private RelyingPartyRegistration(
|
||||||
String registrationId,
|
String registrationId,
|
||||||
@ -78,7 +83,9 @@ public class RelyingPartyRegistration {
|
|||||||
String assertionConsumerServiceLocation,
|
String assertionConsumerServiceLocation,
|
||||||
Saml2MessageBinding assertionConsumerServiceBinding,
|
Saml2MessageBinding assertionConsumerServiceBinding,
|
||||||
ProviderDetails providerDetails,
|
ProviderDetails providerDetails,
|
||||||
List<Saml2X509Credential> credentials) {
|
Collection<org.springframework.security.saml2.credentials.Saml2X509Credential> credentials,
|
||||||
|
Collection<Saml2X509Credential> decryptionX509Credentials,
|
||||||
|
Collection<Saml2X509Credential> signingX509Credentials) {
|
||||||
|
|
||||||
Assert.hasText(registrationId, "registrationId cannot be empty");
|
Assert.hasText(registrationId, "registrationId cannot be empty");
|
||||||
Assert.hasText(entityId, "entityId cannot be empty");
|
Assert.hasText(entityId, "entityId cannot be empty");
|
||||||
@ -86,15 +93,29 @@ public class RelyingPartyRegistration {
|
|||||||
Assert.notNull(assertionConsumerServiceBinding, "assertionConsumerServiceBinding cannot be null");
|
Assert.notNull(assertionConsumerServiceBinding, "assertionConsumerServiceBinding cannot be null");
|
||||||
Assert.notNull(providerDetails, "providerDetails cannot be null");
|
Assert.notNull(providerDetails, "providerDetails cannot be null");
|
||||||
Assert.notEmpty(credentials, "credentials cannot be empty");
|
Assert.notEmpty(credentials, "credentials cannot be empty");
|
||||||
for (Saml2X509Credential c : credentials) {
|
for (org.springframework.security.saml2.credentials.Saml2X509Credential c : credentials) {
|
||||||
Assert.notNull(c, "credentials cannot contain null elements");
|
Assert.notNull(c, "credentials cannot contain null elements");
|
||||||
}
|
}
|
||||||
|
Assert.notNull(decryptionX509Credentials, "decryptionX509Credentials cannot be null");
|
||||||
|
for (Saml2X509Credential c : decryptionX509Credentials) {
|
||||||
|
Assert.notNull(c, "decryptionX509Credentials cannot contain null elements");
|
||||||
|
Assert.isTrue(c.isDecryptionCredential(),
|
||||||
|
"All decryptionX509Credentials must have a usage of DECRYPTION set");
|
||||||
|
}
|
||||||
|
Assert.notNull(signingX509Credentials, "signingX509Credentials cannot be null");
|
||||||
|
for (Saml2X509Credential c : signingX509Credentials) {
|
||||||
|
Assert.notNull(c, "signingX509Credentials cannot contain null elements");
|
||||||
|
Assert.isTrue(c.isSigningCredential(),
|
||||||
|
"All signingX509Credentials must have a usage of SIGNING set");
|
||||||
|
}
|
||||||
this.registrationId = registrationId;
|
this.registrationId = registrationId;
|
||||||
this.entityId = entityId;
|
this.entityId = entityId;
|
||||||
this.assertionConsumerServiceLocation = assertionConsumerServiceLocation;
|
this.assertionConsumerServiceLocation = assertionConsumerServiceLocation;
|
||||||
this.assertionConsumerServiceBinding = assertionConsumerServiceBinding;
|
this.assertionConsumerServiceBinding = assertionConsumerServiceBinding;
|
||||||
this.providerDetails = providerDetails;
|
this.providerDetails = providerDetails;
|
||||||
this.credentials = Collections.unmodifiableList(new LinkedList<>(credentials));
|
this.credentials = Collections.unmodifiableList(new LinkedList<>(credentials));
|
||||||
|
this.decryptionX509Credentials = Collections.unmodifiableList(new LinkedList<>(decryptionX509Credentials));
|
||||||
|
this.signingX509Credentials = Collections.unmodifiableList(new LinkedList<>(signingX509Credentials));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -154,6 +175,26 @@ public class RelyingPartyRegistration {
|
|||||||
return this.assertionConsumerServiceBinding;
|
return this.assertionConsumerServiceBinding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the {@link Collection} of decryption {@link Saml2X509Credential}s associated with this relying party
|
||||||
|
*
|
||||||
|
* @return the {@link Collection} of decryption {@link Saml2X509Credential}s associated with this relying party
|
||||||
|
* @since 5.4
|
||||||
|
*/
|
||||||
|
public Collection<Saml2X509Credential> getDecryptionX509Credentials() {
|
||||||
|
return this.decryptionX509Credentials;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the {@link Collection} of signing {@link Saml2X509Credential}s associated with this relying party
|
||||||
|
*
|
||||||
|
* @return the {@link Collection} of signing {@link Saml2X509Credential}s associated with this relying party
|
||||||
|
* @since 5.4
|
||||||
|
*/
|
||||||
|
public Collection<Saml2X509Credential> getSigningX509Credentials() {
|
||||||
|
return this.signingX509Credentials;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the configuration details for the Asserting Party
|
* Get the configuration details for the Asserting Party
|
||||||
*
|
*
|
||||||
@ -225,50 +266,62 @@ public class RelyingPartyRegistration {
|
|||||||
* Returns a list of configured credentials to be used in message exchanges between relying party, SP, and
|
* Returns a list of configured credentials to be used in message exchanges between relying party, SP, and
|
||||||
* asserting party, IDP.
|
* asserting party, IDP.
|
||||||
* @return a list of credentials
|
* @return a list of credentials
|
||||||
|
* @deprecated Instead of retrieving all credentials, use the appropriate method for obtaining the correct type
|
||||||
*/
|
*/
|
||||||
public List<Saml2X509Credential> getCredentials() {
|
@Deprecated
|
||||||
|
public List<org.springframework.security.saml2.credentials.Saml2X509Credential> getCredentials() {
|
||||||
return this.credentials;
|
return this.credentials;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return a filtered list containing only credentials of type
|
* @return a filtered list containing only credentials of type
|
||||||
* {@link Saml2X509CredentialType#VERIFICATION}.
|
* {@link org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType#VERIFICATION}.
|
||||||
* Returns an empty list of credentials are not found
|
* Returns an empty list of credentials are not found
|
||||||
|
* @deprecated Use {@link #getAssertingPartyDetails().getSigningX509Credentials()} instead
|
||||||
*/
|
*/
|
||||||
public List<Saml2X509Credential> getVerificationCredentials() {
|
@Deprecated
|
||||||
return filterCredentials(c -> c.isSignatureVerficationCredential());
|
public List<org.springframework.security.saml2.credentials.Saml2X509Credential> getVerificationCredentials() {
|
||||||
|
return filterCredentials(org.springframework.security.saml2.credentials.Saml2X509Credential::isSignatureVerficationCredential);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return a filtered list containing only credentials of type
|
* @return a filtered list containing only credentials of type
|
||||||
* {@link Saml2X509CredentialType#SIGNING}.
|
* {@link org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType#SIGNING}.
|
||||||
* Returns an empty list of credentials are not found
|
* Returns an empty list of credentials are not found
|
||||||
|
* @deprecated Use {@link #getSigningX509Credentials()} instead
|
||||||
*/
|
*/
|
||||||
public List<Saml2X509Credential> getSigningCredentials() {
|
@Deprecated
|
||||||
return filterCredentials(c -> c.isSigningCredential());
|
public List<org.springframework.security.saml2.credentials.Saml2X509Credential> getSigningCredentials() {
|
||||||
|
return filterCredentials(org.springframework.security.saml2.credentials.Saml2X509Credential::isSigningCredential);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return a filtered list containing only credentials of type
|
* @return a filtered list containing only credentials of type
|
||||||
* {@link Saml2X509CredentialType#ENCRYPTION}.
|
* {@link org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType#ENCRYPTION}.
|
||||||
* Returns an empty list of credentials are not found
|
* Returns an empty list of credentials are not found
|
||||||
|
* @deprecated Use {@link AssertingPartyDetails#getEncryptionX509Credentials()} instead
|
||||||
*/
|
*/
|
||||||
public List<Saml2X509Credential> getEncryptionCredentials() {
|
@Deprecated
|
||||||
return filterCredentials(c -> c.isEncryptionCredential());
|
public List<org.springframework.security.saml2.credentials.Saml2X509Credential> getEncryptionCredentials() {
|
||||||
|
return filterCredentials(org.springframework.security.saml2.credentials.Saml2X509Credential::isEncryptionCredential);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return a filtered list containing only credentials of type
|
* @return a filtered list containing only credentials of type
|
||||||
* {@link Saml2X509CredentialType#DECRYPTION}.
|
* {@link org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType#DECRYPTION}.
|
||||||
* Returns an empty list of credentials are not found
|
* Returns an empty list of credentials are not found
|
||||||
|
* @deprecated Use {@link #getDecryptionX509Credentials()} instead
|
||||||
*/
|
*/
|
||||||
public List<Saml2X509Credential> getDecryptionCredentials() {
|
@Deprecated
|
||||||
return filterCredentials(c -> c.isDecryptionCredential());
|
public List<org.springframework.security.saml2.credentials.Saml2X509Credential> getDecryptionCredentials() {
|
||||||
|
return filterCredentials(org.springframework.security.saml2.credentials.Saml2X509Credential::isDecryptionCredential);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Saml2X509Credential> filterCredentials(Function<Saml2X509Credential, Boolean> filter) {
|
private List<org.springframework.security.saml2.credentials.Saml2X509Credential> filterCredentials(
|
||||||
List<Saml2X509Credential> result = new LinkedList<>();
|
Function<org.springframework.security.saml2.credentials.Saml2X509Credential, Boolean> filter) {
|
||||||
for (Saml2X509Credential c : getCredentials()) {
|
|
||||||
|
List<org.springframework.security.saml2.credentials.Saml2X509Credential> result = new LinkedList<>();
|
||||||
|
for (org.springframework.security.saml2.credentials.Saml2X509Credential c : this.credentials) {
|
||||||
if (filter.apply(c)) {
|
if (filter.apply(c)) {
|
||||||
result.add(c);
|
result.add(c);
|
||||||
}
|
}
|
||||||
@ -295,15 +348,18 @@ public class RelyingPartyRegistration {
|
|||||||
Assert.notNull(registration, "registration cannot be null");
|
Assert.notNull(registration, "registration cannot be null");
|
||||||
return withRegistrationId(registration.getRegistrationId())
|
return withRegistrationId(registration.getRegistrationId())
|
||||||
.entityId(registration.getEntityId())
|
.entityId(registration.getEntityId())
|
||||||
|
.signingX509Credentials(c -> c.addAll(registration.getSigningX509Credentials()))
|
||||||
|
.decryptionX509Credentials(c -> c.addAll(registration.getDecryptionX509Credentials()))
|
||||||
.assertionConsumerServiceLocation(registration.getAssertionConsumerServiceLocation())
|
.assertionConsumerServiceLocation(registration.getAssertionConsumerServiceLocation())
|
||||||
.assertionConsumerServiceBinding(registration.getAssertionConsumerServiceBinding())
|
.assertionConsumerServiceBinding(registration.getAssertionConsumerServiceBinding())
|
||||||
.assertingPartyDetails(c -> c
|
.assertingPartyDetails(assertingParty -> assertingParty
|
||||||
.entityId(registration.getAssertingPartyDetails().getEntityId())
|
.entityId(registration.getAssertingPartyDetails().getEntityId())
|
||||||
.wantAuthnRequestsSigned(registration.getAssertingPartyDetails().getWantAuthnRequestsSigned())
|
.wantAuthnRequestsSigned(registration.getAssertingPartyDetails().getWantAuthnRequestsSigned())
|
||||||
|
.verificationX509Credentials(c -> c.addAll(registration.getAssertingPartyDetails().getVerificationX509Credentials()))
|
||||||
|
.encryptionX509Credentials(c -> c.addAll(registration.getAssertingPartyDetails().getEncryptionX509Credentials()))
|
||||||
.singleSignOnServiceLocation(registration.getAssertingPartyDetails().getSingleSignOnServiceLocation())
|
.singleSignOnServiceLocation(registration.getAssertingPartyDetails().getSingleSignOnServiceLocation())
|
||||||
.singleSignOnServiceBinding(registration.getAssertingPartyDetails().getSingleSignOnServiceBinding())
|
.singleSignOnServiceBinding(registration.getAssertingPartyDetails().getSingleSignOnServiceBinding())
|
||||||
)
|
);
|
||||||
.credentials(c -> c.addAll(registration.getCredentials()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -315,20 +371,38 @@ public class RelyingPartyRegistration {
|
|||||||
public final static class AssertingPartyDetails {
|
public final static class AssertingPartyDetails {
|
||||||
private final String entityId;
|
private final String entityId;
|
||||||
private final boolean wantAuthnRequestsSigned;
|
private final boolean wantAuthnRequestsSigned;
|
||||||
|
private final Collection<Saml2X509Credential> verificationX509Credentials;
|
||||||
|
private final Collection<Saml2X509Credential> encryptionX509Credentials;
|
||||||
private final String singleSignOnServiceLocation;
|
private final String singleSignOnServiceLocation;
|
||||||
private final Saml2MessageBinding singleSignOnServiceBinding;
|
private final Saml2MessageBinding singleSignOnServiceBinding;
|
||||||
|
|
||||||
private AssertingPartyDetails(
|
private AssertingPartyDetails(
|
||||||
String entityId,
|
String entityId,
|
||||||
boolean wantAuthnRequestsSigned,
|
boolean wantAuthnRequestsSigned,
|
||||||
|
Collection<Saml2X509Credential> verificationX509Credentials,
|
||||||
|
Collection<Saml2X509Credential> encryptionX509Credentials,
|
||||||
String singleSignOnServiceLocation,
|
String singleSignOnServiceLocation,
|
||||||
Saml2MessageBinding singleSignOnServiceBinding) {
|
Saml2MessageBinding singleSignOnServiceBinding) {
|
||||||
|
|
||||||
Assert.hasText(entityId, "entityId cannot be null or empty");
|
Assert.hasText(entityId, "entityId cannot be null or empty");
|
||||||
|
Assert.notNull(verificationX509Credentials, "verificationX509Credentials cannot be null");
|
||||||
|
for (Saml2X509Credential credential : verificationX509Credentials) {
|
||||||
|
Assert.notNull(credential, "verificationX509Credentials cannot have null values");
|
||||||
|
Assert.isTrue(credential.isVerificationCredential(),
|
||||||
|
"All verificationX509Credentials must have a usage of VERIFICATION set");
|
||||||
|
}
|
||||||
|
Assert.notNull(encryptionX509Credentials, "encryptionX509Credentials cannot be null");
|
||||||
|
for (Saml2X509Credential credential : encryptionX509Credentials) {
|
||||||
|
Assert.notNull(credential, "encryptionX509Credentials cannot have null values");
|
||||||
|
Assert.isTrue(credential.isEncryptionCredential(),
|
||||||
|
"All encryptionX509Credentials must have a usage of ENCRYPTION set");
|
||||||
|
}
|
||||||
Assert.notNull(singleSignOnServiceLocation, "singleSignOnServiceLocation cannot be null");
|
Assert.notNull(singleSignOnServiceLocation, "singleSignOnServiceLocation cannot be null");
|
||||||
Assert.notNull(singleSignOnServiceBinding, "singleSignOnServiceBinding cannot be null");
|
Assert.notNull(singleSignOnServiceBinding, "singleSignOnServiceBinding cannot be null");
|
||||||
this.entityId = entityId;
|
this.entityId = entityId;
|
||||||
this.wantAuthnRequestsSigned = wantAuthnRequestsSigned;
|
this.wantAuthnRequestsSigned = wantAuthnRequestsSigned;
|
||||||
|
this.verificationX509Credentials = verificationX509Credentials;
|
||||||
|
this.encryptionX509Credentials = encryptionX509Credentials;
|
||||||
this.singleSignOnServiceLocation = singleSignOnServiceLocation;
|
this.singleSignOnServiceLocation = singleSignOnServiceLocation;
|
||||||
this.singleSignOnServiceBinding = singleSignOnServiceBinding;
|
this.singleSignOnServiceBinding = singleSignOnServiceBinding;
|
||||||
}
|
}
|
||||||
@ -362,6 +436,26 @@ public class RelyingPartyRegistration {
|
|||||||
return this.wantAuthnRequestsSigned;
|
return this.wantAuthnRequestsSigned;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all verification {@link Saml2X509Credential}s associated with this asserting party
|
||||||
|
*
|
||||||
|
* @return all verification {@link Saml2X509Credential}s associated with this asserting party
|
||||||
|
* @since 5.4
|
||||||
|
*/
|
||||||
|
public Collection<Saml2X509Credential> getVerificationX509Credentials() {
|
||||||
|
return this.verificationX509Credentials;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all encryption {@link Saml2X509Credential}s associated with this asserting party
|
||||||
|
*
|
||||||
|
* @return all encryption {@link Saml2X509Credential}s associated with this asserting party
|
||||||
|
* @since 5.4
|
||||||
|
*/
|
||||||
|
public Collection<Saml2X509Credential> getEncryptionX509Credentials() {
|
||||||
|
return this.encryptionX509Credentials;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the
|
* Get the
|
||||||
* <a href="https://wiki.shibboleth.net/confluence/display/CONCEPT/MetadataForIdP#MetadataForIdP-SingleSign-OnServices">SingleSignOnService</a>
|
* <a href="https://wiki.shibboleth.net/confluence/display/CONCEPT/MetadataForIdP#MetadataForIdP-SingleSign-OnServices">SingleSignOnService</a>
|
||||||
@ -395,6 +489,8 @@ public class RelyingPartyRegistration {
|
|||||||
public final static class Builder {
|
public final static class Builder {
|
||||||
private String entityId;
|
private String entityId;
|
||||||
private boolean wantAuthnRequestsSigned = true;
|
private boolean wantAuthnRequestsSigned = true;
|
||||||
|
private Collection<Saml2X509Credential> verificationX509Credentials = new HashSet<>();
|
||||||
|
private Collection<Saml2X509Credential> encryptionX509Credentials = new HashSet<>();
|
||||||
private String singleSignOnServiceLocation;
|
private String singleSignOnServiceLocation;
|
||||||
private Saml2MessageBinding singleSignOnServiceBinding = Saml2MessageBinding.REDIRECT;
|
private Saml2MessageBinding singleSignOnServiceBinding = Saml2MessageBinding.REDIRECT;
|
||||||
|
|
||||||
@ -424,6 +520,30 @@ public class RelyingPartyRegistration {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply this {@link Consumer} to the list of {@link Saml2X509Credential}s
|
||||||
|
*
|
||||||
|
* @param credentialsConsumer a {@link Consumer} of the {@link List} of {@link Saml2X509Credential}s
|
||||||
|
* @return the {@link RelyingPartyRegistration.Builder} for further configuration
|
||||||
|
* @since 5.4
|
||||||
|
*/
|
||||||
|
public Builder verificationX509Credentials(Consumer<Collection<Saml2X509Credential>> credentialsConsumer) {
|
||||||
|
credentialsConsumer.accept(this.verificationX509Credentials);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply this {@link Consumer} to the list of {@link Saml2X509Credential}s
|
||||||
|
*
|
||||||
|
* @param credentialsConsumer a {@link Consumer} of the {@link List} of {@link Saml2X509Credential}s
|
||||||
|
* @return the {@link RelyingPartyRegistration.Builder} for further configuration
|
||||||
|
* @since 5.4
|
||||||
|
*/
|
||||||
|
public Builder encryptionX509Credentials(Consumer<Collection<Saml2X509Credential>> credentialsConsumer) {
|
||||||
|
credentialsConsumer.accept(this.encryptionX509Credentials);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the
|
* Set the
|
||||||
* <a href="https://wiki.shibboleth.net/confluence/display/CONCEPT/MetadataForIdP#MetadataForIdP-SingleSign-OnServices">SingleSignOnService</a>
|
* <a href="https://wiki.shibboleth.net/confluence/display/CONCEPT/MetadataForIdP#MetadataForIdP-SingleSign-OnServices">SingleSignOnService</a>
|
||||||
@ -466,6 +586,8 @@ public class RelyingPartyRegistration {
|
|||||||
return new AssertingPartyDetails(
|
return new AssertingPartyDetails(
|
||||||
this.entityId,
|
this.entityId,
|
||||||
this.wantAuthnRequestsSigned,
|
this.wantAuthnRequestsSigned,
|
||||||
|
this.verificationX509Credentials,
|
||||||
|
this.encryptionX509Credentials,
|
||||||
this.singleSignOnServiceLocation,
|
this.singleSignOnServiceLocation,
|
||||||
this.singleSignOnServiceBinding
|
this.singleSignOnServiceBinding
|
||||||
);
|
);
|
||||||
@ -591,10 +713,12 @@ public class RelyingPartyRegistration {
|
|||||||
public final static class Builder {
|
public final static class Builder {
|
||||||
private String registrationId;
|
private String registrationId;
|
||||||
private String entityId = "{baseUrl}/saml2/service-provider-metadata/{registrationId}";
|
private String entityId = "{baseUrl}/saml2/service-provider-metadata/{registrationId}";
|
||||||
|
private Collection<Saml2X509Credential> signingX509Credentials = new HashSet<>();
|
||||||
|
private Collection<Saml2X509Credential> decryptionX509Credentials = new HashSet<>();
|
||||||
private String assertionConsumerServiceLocation;
|
private String assertionConsumerServiceLocation;
|
||||||
private Saml2MessageBinding assertionConsumerServiceBinding = Saml2MessageBinding.POST;
|
private Saml2MessageBinding assertionConsumerServiceBinding = Saml2MessageBinding.POST;
|
||||||
private ProviderDetails.Builder providerDetails = new ProviderDetails.Builder();
|
private ProviderDetails.Builder providerDetails = new ProviderDetails.Builder();
|
||||||
private List<Saml2X509Credential> credentials = new LinkedList<>();
|
private Collection<org.springframework.security.saml2.credentials.Saml2X509Credential> credentials = new HashSet<>();
|
||||||
|
|
||||||
private Builder(String registrationId) {
|
private Builder(String registrationId) {
|
||||||
this.registrationId = registrationId;
|
this.registrationId = registrationId;
|
||||||
@ -629,6 +753,32 @@ public class RelyingPartyRegistration {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply this {@link Consumer} to the {@link Collection} of {@link Saml2X509Credential}s
|
||||||
|
* for the purposes of modifying the {@link Collection}
|
||||||
|
*
|
||||||
|
* @param credentialsConsumer - the {@link Consumer} for modifying the {@link Collection}
|
||||||
|
* @return the {@link Builder} for further configuration
|
||||||
|
* @since 5.4
|
||||||
|
*/
|
||||||
|
public Builder signingX509Credentials(Consumer<Collection<Saml2X509Credential>> credentialsConsumer) {
|
||||||
|
credentialsConsumer.accept(this.signingX509Credentials);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply this {@link Consumer} to the {@link Collection} of {@link Saml2X509Credential}s
|
||||||
|
* for the purposes of modifying the {@link Collection}
|
||||||
|
*
|
||||||
|
* @param credentialsConsumer - the {@link Consumer} for modifying the {@link Collection}
|
||||||
|
* @return the {@link Builder} for further configuration
|
||||||
|
* @since 5.4
|
||||||
|
*/
|
||||||
|
public Builder decryptionX509Credentials(Consumer<Collection<Saml2X509Credential>> credentialsConsumer) {
|
||||||
|
credentialsConsumer.accept(this.decryptionX509Credentials);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the <a href="https://wiki.shibboleth.net/confluence/display/CONCEPT/AssertionConsumerService">AssertionConsumerService</a>
|
* Set the <a href="https://wiki.shibboleth.net/confluence/display/CONCEPT/AssertionConsumerService">AssertionConsumerService</a>
|
||||||
* Location.
|
* Location.
|
||||||
@ -693,8 +843,12 @@ public class RelyingPartyRegistration {
|
|||||||
* </code>
|
* </code>
|
||||||
* @param credentials - a consumer that can modify the collection of credentials
|
* @param credentials - a consumer that can modify the collection of credentials
|
||||||
* @return this object
|
* @return this object
|
||||||
|
* @deprecated Use {@link #signingX509Credentials} or {@link #decryptionX509Credentials} instead
|
||||||
|
* for relying party keys or {@link AssertingPartyDetails.Builder#verificationX509Credentials} or
|
||||||
|
* {@link AssertingPartyDetails.Builder#encryptionX509Credentials} for asserting party keys
|
||||||
*/
|
*/
|
||||||
public Builder credentials(Consumer<Collection<Saml2X509Credential>> credentials) {
|
@Deprecated
|
||||||
|
public Builder credentials(Consumer<Collection<org.springframework.security.saml2.credentials.Saml2X509Credential>> credentials) {
|
||||||
credentials.accept(this.credentials);
|
credentials.accept(this.credentials);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -769,15 +923,85 @@ public class RelyingPartyRegistration {
|
|||||||
* @return a RelyingPartyRegistration instance
|
* @return a RelyingPartyRegistration instance
|
||||||
*/
|
*/
|
||||||
public RelyingPartyRegistration build() {
|
public RelyingPartyRegistration build() {
|
||||||
|
for (org.springframework.security.saml2.credentials.Saml2X509Credential credential : this.credentials) {
|
||||||
|
Saml2X509Credential mapped = fromDeprecated(credential);
|
||||||
|
if (credential.isSigningCredential()) {
|
||||||
|
signingX509Credentials(c -> c.add(mapped));
|
||||||
|
}
|
||||||
|
if (credential.isDecryptionCredential()) {
|
||||||
|
decryptionX509Credentials(c -> c.add(mapped));
|
||||||
|
}
|
||||||
|
if (credential.isSignatureVerficationCredential()) {
|
||||||
|
this.providerDetails.assertingPartyDetailsBuilder
|
||||||
|
.verificationX509Credentials(c -> c.add(mapped));
|
||||||
|
}
|
||||||
|
if (credential.isEncryptionCredential()) {
|
||||||
|
this.providerDetails.assertingPartyDetailsBuilder
|
||||||
|
.encryptionX509Credentials(c -> c.add(mapped));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Saml2X509Credential credential : this.signingX509Credentials) {
|
||||||
|
this.credentials.add(toDeprecated(credential));
|
||||||
|
}
|
||||||
|
for (Saml2X509Credential credential : this.decryptionX509Credentials) {
|
||||||
|
this.credentials.add(toDeprecated(credential));
|
||||||
|
}
|
||||||
|
for (Saml2X509Credential credential : this.providerDetails.assertingPartyDetailsBuilder.verificationX509Credentials) {
|
||||||
|
this.credentials.add(toDeprecated(credential));
|
||||||
|
}
|
||||||
|
for (Saml2X509Credential credential : this.providerDetails.assertingPartyDetailsBuilder.encryptionX509Credentials) {
|
||||||
|
this.credentials.add(toDeprecated(credential));
|
||||||
|
}
|
||||||
|
|
||||||
return new RelyingPartyRegistration(
|
return new RelyingPartyRegistration(
|
||||||
this.registrationId,
|
this.registrationId,
|
||||||
this.entityId,
|
this.entityId,
|
||||||
this.assertionConsumerServiceLocation,
|
this.assertionConsumerServiceLocation,
|
||||||
this.assertionConsumerServiceBinding,
|
this.assertionConsumerServiceBinding,
|
||||||
this.providerDetails.build(),
|
this.providerDetails.build(),
|
||||||
this.credentials
|
this.credentials,
|
||||||
|
this.decryptionX509Credentials,
|
||||||
|
this.signingX509Credentials
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Saml2X509Credential fromDeprecated(org.springframework.security.saml2.credentials.Saml2X509Credential credential) {
|
||||||
|
PrivateKey privateKey = credential.getPrivateKey();
|
||||||
|
X509Certificate certificate = credential.getCertificate();
|
||||||
|
Set<Saml2X509Credential.Saml2X509CredentialType> credentialTypes = new HashSet<>();
|
||||||
|
if (credential.isSigningCredential()) {
|
||||||
|
credentialTypes.add(Saml2X509Credential.Saml2X509CredentialType.SIGNING);
|
||||||
|
}
|
||||||
|
if (credential.isSignatureVerficationCredential()) {
|
||||||
|
credentialTypes.add(Saml2X509Credential.Saml2X509CredentialType.VERIFICATION);
|
||||||
|
}
|
||||||
|
if (credential.isEncryptionCredential()) {
|
||||||
|
credentialTypes.add(Saml2X509Credential.Saml2X509CredentialType.ENCRYPTION);
|
||||||
|
}
|
||||||
|
if (credential.isDecryptionCredential()) {
|
||||||
|
credentialTypes.add(Saml2X509Credential.Saml2X509CredentialType.DECRYPTION);
|
||||||
|
}
|
||||||
|
return new Saml2X509Credential(privateKey, certificate, credentialTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static org.springframework.security.saml2.credentials.Saml2X509Credential toDeprecated(Saml2X509Credential credential) {
|
||||||
|
PrivateKey privateKey = credential.getPrivateKey();
|
||||||
|
X509Certificate certificate = credential.getCertificate();
|
||||||
|
Set<org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType> credentialTypes = new HashSet<>();
|
||||||
|
if (credential.isSigningCredential()) {
|
||||||
|
credentialTypes.add(org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType.SIGNING);
|
||||||
|
}
|
||||||
|
if (credential.isVerificationCredential()) {
|
||||||
|
credentialTypes.add(org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType.VERIFICATION);
|
||||||
|
}
|
||||||
|
if (credential.isEncryptionCredential()) {
|
||||||
|
credentialTypes.add(org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType.ENCRYPTION);
|
||||||
|
}
|
||||||
|
if (credential.isDecryptionCredential()) {
|
||||||
|
credentialTypes.add(org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType.DECRYPTION);
|
||||||
|
}
|
||||||
|
return new org.springframework.security.saml2.credentials.Saml2X509Credential(privateKey, certificate, credentialTypes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,179 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2002-2020 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.security.saml2.core;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.security.KeyException;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
import java.security.cert.CertificateFactory;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
|
||||||
|
import org.opensaml.security.crypto.KeySupport;
|
||||||
|
|
||||||
|
import org.springframework.security.saml2.Saml2Exception;
|
||||||
|
|
||||||
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
import static org.springframework.security.saml2.core.Saml2X509Credential.Saml2X509CredentialType.DECRYPTION;
|
||||||
|
import static org.springframework.security.saml2.core.Saml2X509Credential.Saml2X509CredentialType.ENCRYPTION;
|
||||||
|
import static org.springframework.security.saml2.core.Saml2X509Credential.Saml2X509CredentialType.SIGNING;
|
||||||
|
import static org.springframework.security.saml2.core.Saml2X509Credential.Saml2X509CredentialType.VERIFICATION;
|
||||||
|
|
||||||
|
public final class TestSaml2X509Credentials {
|
||||||
|
public static Saml2X509Credential assertingPartySigningCredential() {
|
||||||
|
return new Saml2X509Credential(idpPrivateKey(), idpCertificate(), SIGNING);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Saml2X509Credential assertingPartyEncryptingCredential() {
|
||||||
|
return new Saml2X509Credential(spCertificate(), ENCRYPTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Saml2X509Credential assertingPartyPrivateCredential() {
|
||||||
|
return new Saml2X509Credential(idpPrivateKey(), idpCertificate(), SIGNING, DECRYPTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Saml2X509Credential relyingPartyVerifyingCredential() {
|
||||||
|
return new Saml2X509Credential(idpCertificate(), VERIFICATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Saml2X509Credential relyingPartySigningCredential() {
|
||||||
|
return new Saml2X509Credential(spPrivateKey(), spCertificate(), SIGNING);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Saml2X509Credential relyingPartyDecryptingCredential() {
|
||||||
|
return new Saml2X509Credential(spPrivateKey(), spCertificate(), DECRYPTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static X509Certificate certificate(String cert) {
|
||||||
|
ByteArrayInputStream certBytes = new ByteArrayInputStream(cert.getBytes());
|
||||||
|
try {
|
||||||
|
return (X509Certificate) CertificateFactory
|
||||||
|
.getInstance("X.509")
|
||||||
|
.generateCertificate(certBytes);
|
||||||
|
}
|
||||||
|
catch (CertificateException e) {
|
||||||
|
throw new Saml2Exception(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PrivateKey privateKey(String key) {
|
||||||
|
try {
|
||||||
|
return KeySupport.decodePrivateKey(key.getBytes(UTF_8), new char[0]);
|
||||||
|
}
|
||||||
|
catch (KeyException e) {
|
||||||
|
throw new Saml2Exception(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static X509Certificate idpCertificate() {
|
||||||
|
return certificate("-----BEGIN CERTIFICATE-----\n"
|
||||||
|
+ "MIIEEzCCAvugAwIBAgIJAIc1qzLrv+5nMA0GCSqGSIb3DQEBCwUAMIGfMQswCQYD\n"
|
||||||
|
+ "VQQGEwJVUzELMAkGA1UECAwCQ08xFDASBgNVBAcMC0Nhc3RsZSBSb2NrMRwwGgYD\n"
|
||||||
|
+ "VQQKDBNTYW1sIFRlc3RpbmcgU2VydmVyMQswCQYDVQQLDAJJVDEgMB4GA1UEAwwX\n"
|
||||||
|
+ "c2ltcGxlc2FtbHBocC5jZmFwcHMuaW8xIDAeBgkqhkiG9w0BCQEWEWZoYW5pa0Bw\n"
|
||||||
|
+ "aXZvdGFsLmlvMB4XDTE1MDIyMzIyNDUwM1oXDTI1MDIyMjIyNDUwM1owgZ8xCzAJ\n"
|
||||||
|
+ "BgNVBAYTAlVTMQswCQYDVQQIDAJDTzEUMBIGA1UEBwwLQ2FzdGxlIFJvY2sxHDAa\n"
|
||||||
|
+ "BgNVBAoME1NhbWwgVGVzdGluZyBTZXJ2ZXIxCzAJBgNVBAsMAklUMSAwHgYDVQQD\n"
|
||||||
|
+ "DBdzaW1wbGVzYW1scGhwLmNmYXBwcy5pbzEgMB4GCSqGSIb3DQEJARYRZmhhbmlr\n"
|
||||||
|
+ "QHBpdm90YWwuaW8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC4cn62\n"
|
||||||
|
+ "E1xLqpN34PmbrKBbkOXFjzWgJ9b+pXuaRft6A339uuIQeoeH5qeSKRVTl32L0gdz\n"
|
||||||
|
+ "2ZivLwZXW+cqvftVW1tvEHvzJFyxeTW3fCUeCQsebLnA2qRa07RkxTo6Nf244mWW\n"
|
||||||
|
+ "RDodcoHEfDUSbxfTZ6IExSojSIU2RnD6WllYWFdD1GFpBJOmQB8rAc8wJIBdHFdQ\n"
|
||||||
|
+ "nX8Ttl7hZ6rtgqEYMzYVMuJ2F2r1HSU1zSAvwpdYP6rRGFRJEfdA9mm3WKfNLSc5\n"
|
||||||
|
+ "cljz0X/TXy0vVlAV95l9qcfFzPmrkNIst9FZSwpvB49LyAVke04FQPPwLgVH4gph\n"
|
||||||
|
+ "iJH3jvZ7I+J5lS8VAgMBAAGjUDBOMB0GA1UdDgQWBBTTyP6Cc5HlBJ5+ucVCwGc5\n"
|
||||||
|
+ "ogKNGzAfBgNVHSMEGDAWgBTTyP6Cc5HlBJ5+ucVCwGc5ogKNGzAMBgNVHRMEBTAD\n"
|
||||||
|
+ "AQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAvMS4EQeP/ipV4jOG5lO6/tYCb/iJeAduO\n"
|
||||||
|
+ "nRhkJk0DbX329lDLZhTTL/x/w/9muCVcvLrzEp6PN+VWfw5E5FWtZN0yhGtP9R+v\n"
|
||||||
|
+ "ZnrV+oc2zGD+no1/ySFOe3EiJCO5dehxKjYEmBRv5sU/LZFKZpozKN/BMEa6CqLu\n"
|
||||||
|
+ "xbzb7ykxVr7EVFXwltPxzE9TmL9OACNNyF5eJHWMRMllarUvkcXlh4pux4ks9e6z\n"
|
||||||
|
+ "V9DQBy2zds9f1I3qxg0eX6JnGrXi/ZiCT+lJgVe3ZFXiejiLAiKB04sXW3ti0LW3\n"
|
||||||
|
+ "lx13Y1YlQ4/tlpgTgfIJxKV6nyPiLoK0nywbMd+vpAirDt2Oc+hk\n"
|
||||||
|
+ "-----END CERTIFICATE-----\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static PrivateKey idpPrivateKey() {
|
||||||
|
return privateKey("-----BEGIN PRIVATE KEY-----\n"
|
||||||
|
+ "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC4cn62E1xLqpN3\n"
|
||||||
|
+ "4PmbrKBbkOXFjzWgJ9b+pXuaRft6A339uuIQeoeH5qeSKRVTl32L0gdz2ZivLwZX\n"
|
||||||
|
+ "W+cqvftVW1tvEHvzJFyxeTW3fCUeCQsebLnA2qRa07RkxTo6Nf244mWWRDodcoHE\n"
|
||||||
|
+ "fDUSbxfTZ6IExSojSIU2RnD6WllYWFdD1GFpBJOmQB8rAc8wJIBdHFdQnX8Ttl7h\n"
|
||||||
|
+ "Z6rtgqEYMzYVMuJ2F2r1HSU1zSAvwpdYP6rRGFRJEfdA9mm3WKfNLSc5cljz0X/T\n"
|
||||||
|
+ "Xy0vVlAV95l9qcfFzPmrkNIst9FZSwpvB49LyAVke04FQPPwLgVH4gphiJH3jvZ7\n"
|
||||||
|
+ "I+J5lS8VAgMBAAECggEBAKyxBlIS7mcp3chvq0RF7B3PHFJMMzkwE+t3pLJcs4cZ\n"
|
||||||
|
+ "nezh/KbREfP70QjXzk/llnZCvxeIs5vRu24vbdBm79qLHqBuHp8XfHHtuo2AfoAQ\n"
|
||||||
|
+ "l4h047Xc/+TKMivnPQ0jX9qqndKDLqZDf5wnbslDmlskvF0a/MjsLU0TxtOfo+dB\n"
|
||||||
|
+ "t55FW11cGqxZwhS5Gnr+cbw3OkHz23b9gEOt9qfwPVepeysbmm9FjU+k4yVa7rAN\n"
|
||||||
|
+ "xcbzVb6Y7GCITe2tgvvEHmjB9BLmWrH3mZ3Af17YU/iN6TrpPd6Sj3QoS+2wGtAe\n"
|
||||||
|
+ "HbUs3CKJu7bIHcj4poal6Kh8519S+erJTtqQ8M0ZiEECgYEA43hLYAPaUueFkdfh\n"
|
||||||
|
+ "9K/7ClH6436CUH3VdizwUXi26fdhhV/I/ot6zLfU2mgEHU22LBECWQGtAFm8kv0P\n"
|
||||||
|
+ "zPn+qjaR3e62l5PIlSYbnkIidzoDZ2ztu4jF5LgStlTJQPteFEGgZVl5o9DaSZOq\n"
|
||||||
|
+ "Yd7G3XqXuQ1VGMW58G5FYJPtA1cCgYEAz5TPUtK+R2KXHMjUwlGY9AefQYRYmyX2\n"
|
||||||
|
+ "Tn/OFgKvY8lpAkMrhPKONq7SMYc8E9v9G7A0dIOXvW7QOYSapNhKU+np3lUafR5F\n"
|
||||||
|
+ "4ZN0bxZ9qjHbn3AMYeraKjeutHvlLtbHdIc1j3sxe/EzltRsYmiqLdEBW0p6hwWg\n"
|
||||||
|
+ "tyGhYWVyaXMCgYAfDOKtHpmEy5nOCLwNXKBWDk7DExfSyPqEgSnk1SeS1HP5ctPK\n"
|
||||||
|
+ "+1st6sIhdiVpopwFc+TwJWxqKdW18tlfT5jVv1E2DEnccw3kXilS9xAhWkfwrEvf\n"
|
||||||
|
+ "V5I74GydewFl32o+NZ8hdo9GL1I8zO1rIq/et8dSOWGuWf9BtKu/vTGTTQKBgFxU\n"
|
||||||
|
+ "VjsCnbvmsEwPUAL2hE/WrBFaKocnxXx5AFNt8lEyHtDwy4Sg1nygGcIJ4sD6koQk\n"
|
||||||
|
+ "RdClT3LkvR04TAiSY80bN/i6ZcPNGUwSaDGZEWAIOSWbkwZijZNFnSGOEgxZX/IG\n"
|
||||||
|
+ "yd39766vREEMTwEeiMNEOZQ/dmxkJm4OOVe25cLdAoGACOtPnq1Fxay80UYBf4rQ\n"
|
||||||
|
+ "+bJ9yX1ulB8WIree1hD7OHSB2lRHxrVYWrglrTvkh63Lgx+EcsTV788OsvAVfPPz\n"
|
||||||
|
+ "BZrn8SdDlQqalMxUBYEFwnsYD3cQ8yOUnijFVC4xNcdDv8OIqVgSk4KKxU5AshaA\n" + "xk6Mox+u8Cc2eAK12H13i+8=\n"
|
||||||
|
+ "-----END PRIVATE KEY-----\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static X509Certificate spCertificate() {
|
||||||
|
|
||||||
|
return certificate("-----BEGIN CERTIFICATE-----\n" +
|
||||||
|
"MIICgTCCAeoCCQCuVzyqFgMSyDANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBhMC\n" +
|
||||||
|
"VVMxEzARBgNVBAgMCldhc2hpbmd0b24xEjAQBgNVBAcMCVZhbmNvdXZlcjEdMBsG\n" +
|
||||||
|
"A1UECgwUU3ByaW5nIFNlY3VyaXR5IFNBTUwxCzAJBgNVBAsMAnNwMSAwHgYDVQQD\n" +
|
||||||
|
"DBdzcC5zcHJpbmcuc2VjdXJpdHkuc2FtbDAeFw0xODA1MTQxNDMwNDRaFw0yODA1\n" +
|
||||||
|
"MTExNDMwNDRaMIGEMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjES\n" +
|
||||||
|
"MBAGA1UEBwwJVmFuY291dmVyMR0wGwYDVQQKDBRTcHJpbmcgU2VjdXJpdHkgU0FN\n" +
|
||||||
|
"TDELMAkGA1UECwwCc3AxIDAeBgNVBAMMF3NwLnNwcmluZy5zZWN1cml0eS5zYW1s\n" +
|
||||||
|
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRu7/EI0BlNzMEBFVAcbx+lLos\n" +
|
||||||
|
"vzIWU+01dGTY8gBdhMQNYKZ92lMceo2CuVJ66cUURPym3i7nGGzoSnAxAre+0YIM\n" +
|
||||||
|
"+U0razrWtAUE735bkcqELZkOTZLelaoOztmWqRbe5OuEmpewH7cx+kNgcVjdctOG\n" +
|
||||||
|
"y3Q6x+I4qakY/9qhBQIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAAeViTvHOyQopWEi\n" +
|
||||||
|
"XOfI2Z9eukwrSknDwq/zscR0YxwwqDBMt/QdAODfSwAfnciiYLkmEjlozWRtOeN+\n" +
|
||||||
|
"qK7UFgP1bRl5qksrYX5S0z2iGJh0GvonLUt3e20Ssfl5tTEDDnAEUMLfBkyaxEHD\n" +
|
||||||
|
"RZ/nbTJ7VTeZOSyRoVn5XHhpuJ0B\n" +
|
||||||
|
"-----END CERTIFICATE-----");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PrivateKey spPrivateKey() {
|
||||||
|
return privateKey("-----BEGIN PRIVATE KEY-----\n" +
|
||||||
|
"MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBANG7v8QjQGU3MwQE\n" +
|
||||||
|
"VUBxvH6Uuiy/MhZT7TV0ZNjyAF2ExA1gpn3aUxx6jYK5UnrpxRRE/KbeLucYbOhK\n" +
|
||||||
|
"cDECt77Rggz5TStrOta0BQTvfluRyoQtmQ5Nkt6Vqg7O2ZapFt7k64Sal7AftzH6\n" +
|
||||||
|
"Q2BxWN1y04bLdDrH4jipqRj/2qEFAgMBAAECgYEAj4ExY1jjdN3iEDuOwXuRB+Nn\n" +
|
||||||
|
"x7pC4TgntE2huzdKvLJdGvIouTArce8A6JM5NlTBvm69mMepvAHgcsiMH1zGr5J5\n" +
|
||||||
|
"wJz23mGOyhM1veON41/DJTVG+cxq4soUZhdYy3bpOuXGMAaJ8QLMbQQoivllNihd\n" +
|
||||||
|
"vwH0rNSK8LTYWWPZYIECQQDxct+TFX1VsQ1eo41K0T4fu2rWUaxlvjUGhK6HxTmY\n" +
|
||||||
|
"8OMJptunGRJL1CUjIb45Uz7SP8TPz5FwhXWsLfS182kRAkEA3l+Qd9C9gdpUh1uX\n" +
|
||||||
|
"oPSNIxn5hFUrSTW1EwP9QH9vhwb5Vr8Jrd5ei678WYDLjUcx648RjkjhU9jSMzIx\n" +
|
||||||
|
"EGvYtQJBAMm/i9NR7IVyyNIgZUpz5q4LI21rl1r4gUQuD8vA36zM81i4ROeuCly0\n" +
|
||||||
|
"KkfdxR4PUfnKcQCX11YnHjk9uTFj75ECQEFY/gBnxDjzqyF35hAzrYIiMPQVfznt\n" +
|
||||||
|
"YX/sDTE2AdVBVGaMj1Cb51bPHnNC6Q5kXKQnj/YrLqRQND09Q7ParX0CQQC5NxZr\n" +
|
||||||
|
"9jKqhHj8yQD6PlXTsY4Occ7DH6/IoDenfdEVD5qlet0zmd50HatN2Jiqm5ubN7CM\n" +
|
||||||
|
"INrtuLp4YHbgk1mi\n" +
|
||||||
|
"-----END PRIVATE KEY-----");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2019 the original author or authors.
|
* Copyright 2002-2020 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -22,7 +22,7 @@ import java.util.Map;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.opensaml.xmlsec.crypto.XMLSigningUtil;
|
import org.opensaml.xmlsec.crypto.XMLSigningUtil;
|
||||||
|
|
||||||
import org.springframework.security.saml2.credentials.Saml2X509Credential;
|
import org.springframework.security.saml2.core.Saml2X509Credential;
|
||||||
import org.springframework.web.util.UriUtils;
|
import org.springframework.web.util.UriUtils;
|
||||||
|
|
||||||
import static java.nio.charset.StandardCharsets.ISO_8859_1;
|
import static java.nio.charset.StandardCharsets.ISO_8859_1;
|
||||||
@ -30,8 +30,8 @@ import static java.nio.charset.StandardCharsets.UTF_8;
|
|||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.opensaml.xmlsec.signature.support.SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256;
|
import static org.opensaml.xmlsec.signature.support.SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256;
|
||||||
import static org.springframework.security.saml2.provider.service.authentication.TestOpenSamlObjects.getSigningCredential;
|
import static org.springframework.security.saml2.provider.service.authentication.TestOpenSamlObjects.getSigningCredential;
|
||||||
import static org.springframework.security.saml2.credentials.TestSaml2X509Credentials.assertingPartySigningCredential;
|
import static org.springframework.security.saml2.core.TestSaml2X509Credentials.assertingPartySigningCredential;
|
||||||
import static org.springframework.security.saml2.credentials.TestSaml2X509Credentials.relyingPartyVerifyingCredential;
|
import static org.springframework.security.saml2.core.TestSaml2X509Credentials.relyingPartyVerifyingCredential;
|
||||||
|
|
||||||
public class OpenSamlImplementationTests {
|
public class OpenSamlImplementationTests {
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ import org.opensaml.xmlsec.signature.support.SignatureException;
|
|||||||
import org.opensaml.xmlsec.signature.support.SignatureSupport;
|
import org.opensaml.xmlsec.signature.support.SignatureSupport;
|
||||||
|
|
||||||
import org.springframework.security.saml2.Saml2Exception;
|
import org.springframework.security.saml2.Saml2Exception;
|
||||||
import org.springframework.security.saml2.credentials.Saml2X509Credential;
|
import org.springframework.security.saml2.core.Saml2X509Credential;
|
||||||
|
|
||||||
final class TestOpenSamlObjects {
|
final class TestOpenSamlObjects {
|
||||||
private static OpenSamlImplementation saml = OpenSamlImplementation.getInstance();
|
private static OpenSamlImplementation saml = OpenSamlImplementation.getInstance();
|
||||||
@ -178,6 +178,13 @@ final class TestOpenSamlObjects {
|
|||||||
return cred;
|
return cred;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Credential getSigningCredential(org.springframework.security.saml2.credentials.Saml2X509Credential credential, String entityId) {
|
||||||
|
BasicCredential cred = getBasicCredential(credential);
|
||||||
|
cred.setEntityId(entityId);
|
||||||
|
cred.setUsageType(UsageType.SIGNING);
|
||||||
|
return cred;
|
||||||
|
}
|
||||||
|
|
||||||
static BasicCredential getBasicCredential(Saml2X509Credential credential) {
|
static BasicCredential getBasicCredential(Saml2X509Credential credential) {
|
||||||
return CredentialSupport.getSimpleCredential(
|
return CredentialSupport.getSimpleCredential(
|
||||||
credential.getCertificate(),
|
credential.getCertificate(),
|
||||||
@ -185,6 +192,13 @@ final class TestOpenSamlObjects {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BasicCredential getBasicCredential(org.springframework.security.saml2.credentials.Saml2X509Credential credential) {
|
||||||
|
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) {
|
||||||
SignatureSigningParameters parameters = new SignatureSigningParameters();
|
SignatureSigningParameters parameters = new SignatureSigningParameters();
|
||||||
Credential signingCredential = getSigningCredential(credential, entityId);
|
Credential signingCredential = getSigningCredential(credential, entityId);
|
||||||
@ -201,6 +215,22 @@ final class TestOpenSamlObjects {
|
|||||||
return signable;
|
return signable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static <T extends SignableSAMLObject> T signed(T signable, org.springframework.security.saml2.credentials.Saml2X509Credential credential, String entityId) {
|
||||||
|
SignatureSigningParameters parameters = new SignatureSigningParameters();
|
||||||
|
Credential signingCredential = getSigningCredential(credential, entityId);
|
||||||
|
parameters.setSigningCredential(signingCredential);
|
||||||
|
parameters.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256);
|
||||||
|
parameters.setSignatureReferenceDigestMethod(SignatureConstants.ALGO_ID_DIGEST_SHA256);
|
||||||
|
parameters.setSignatureCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
|
||||||
|
try {
|
||||||
|
SignatureSupport.signObject(signable, parameters);
|
||||||
|
} catch (MarshallingException | SignatureException | SecurityException e) {
|
||||||
|
throw new Saml2Exception(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return signable;
|
||||||
|
}
|
||||||
|
|
||||||
static EncryptedAssertion encrypted(Assertion assertion, Saml2X509Credential credential) {
|
static EncryptedAssertion encrypted(Assertion assertion, Saml2X509Credential credential) {
|
||||||
X509Certificate certificate = credential.getCertificate();
|
X509Certificate certificate = credential.getCertificate();
|
||||||
Encrypter encrypter = getEncrypter(certificate);
|
Encrypter encrypter = getEncrypter(certificate);
|
||||||
@ -212,6 +242,17 @@ final class TestOpenSamlObjects {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static EncryptedAssertion encrypted(Assertion assertion, org.springframework.security.saml2.credentials.Saml2X509Credential credential) {
|
||||||
|
X509Certificate certificate = credential.getCertificate();
|
||||||
|
Encrypter encrypter = getEncrypter(certificate);
|
||||||
|
try {
|
||||||
|
return encrypter.encrypt(assertion);
|
||||||
|
}
|
||||||
|
catch (EncryptionException e) {
|
||||||
|
throw new Saml2Exception("Unable to encrypt assertion.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static EncryptedID encrypted(NameID nameId, Saml2X509Credential credential) {
|
static EncryptedID encrypted(NameID nameId, Saml2X509Credential credential) {
|
||||||
X509Certificate certificate = credential.getCertificate();
|
X509Certificate certificate = credential.getCertificate();
|
||||||
Encrypter encrypter = getEncrypter(certificate);
|
Encrypter encrypter = getEncrypter(certificate);
|
||||||
@ -223,6 +264,17 @@ final class TestOpenSamlObjects {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static EncryptedID encrypted(NameID nameId, org.springframework.security.saml2.credentials.Saml2X509Credential credential) {
|
||||||
|
X509Certificate certificate = credential.getCertificate();
|
||||||
|
Encrypter encrypter = getEncrypter(certificate);
|
||||||
|
try {
|
||||||
|
return encrypter.encrypt(nameId);
|
||||||
|
}
|
||||||
|
catch (EncryptionException e) {
|
||||||
|
throw new Saml2Exception("Unable to encrypt nameID.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static Encrypter getEncrypter(X509Certificate certificate) {
|
private static Encrypter getEncrypter(X509Certificate certificate) {
|
||||||
String dataAlgorithm = XMLCipherParameters.AES_256;
|
String dataAlgorithm = XMLCipherParameters.AES_256;
|
||||||
String keyAlgorithm = XMLCipherParameters.RSA_1_5;
|
String keyAlgorithm = XMLCipherParameters.RSA_1_5;
|
||||||
|
@ -81,6 +81,14 @@ public class RelyingPartyRegistrationTests {
|
|||||||
.isFalse();
|
.isFalse();
|
||||||
assertThat(copy.getAssertionConsumerServiceBinding())
|
assertThat(copy.getAssertionConsumerServiceBinding())
|
||||||
.isEqualTo(registration.getAssertionConsumerServiceBinding());
|
.isEqualTo(registration.getAssertionConsumerServiceBinding());
|
||||||
|
assertThat(copy.getDecryptionX509Credentials())
|
||||||
|
.isEqualTo(registration.getDecryptionX509Credentials());
|
||||||
|
assertThat(copy.getSigningX509Credentials())
|
||||||
|
.isEqualTo(registration.getSigningX509Credentials());
|
||||||
|
assertThat(copy.getAssertingPartyDetails().getEncryptionX509Credentials())
|
||||||
|
.isEqualTo(registration.getAssertingPartyDetails().getEncryptionX509Credentials());
|
||||||
|
assertThat(copy.getAssertingPartyDetails().getVerificationX509Credentials())
|
||||||
|
.isEqualTo(registration.getAssertingPartyDetails().getVerificationX509Credentials());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -26,14 +26,14 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
|||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||||
import org.springframework.security.converter.RsaKeyConverters;
|
import org.springframework.security.converter.RsaKeyConverters;
|
||||||
import org.springframework.security.saml2.credentials.Saml2X509Credential;
|
import org.springframework.security.saml2.core.Saml2X509Credential;
|
||||||
import org.springframework.security.saml2.provider.service.registration.InMemoryRelyingPartyRegistrationRepository;
|
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;
|
||||||
import org.springframework.security.saml2.provider.service.servlet.filter.Saml2WebSsoAuthenticationFilter;
|
import org.springframework.security.saml2.provider.service.servlet.filter.Saml2WebSsoAuthenticationFilter;
|
||||||
|
|
||||||
import static org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType.DECRYPTION;
|
import static org.springframework.security.saml2.core.Saml2X509Credential.Saml2X509CredentialType.DECRYPTION;
|
||||||
import static org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType.SIGNING;
|
import static org.springframework.security.saml2.core.Saml2X509Credential.Saml2X509CredentialType.SIGNING;
|
||||||
import static org.springframework.security.saml2.credentials.Saml2X509Credential.Saml2X509CredentialType.VERIFICATION;
|
import static org.springframework.security.saml2.core.Saml2X509Credential.Saml2X509CredentialType.VERIFICATION;
|
||||||
|
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||||
@ -56,11 +56,11 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
|||||||
return RelyingPartyRegistration.withRegistrationId(registrationId)
|
return RelyingPartyRegistration.withRegistrationId(registrationId)
|
||||||
.entityId(localEntityIdTemplate)
|
.entityId(localEntityIdTemplate)
|
||||||
.assertionConsumerServiceLocation(acsUrlTemplate)
|
.assertionConsumerServiceLocation(acsUrlTemplate)
|
||||||
.credentials(c -> c.add(signingCredential))
|
.signingX509Credentials(c -> c.add(signingCredential))
|
||||||
.assertingPartyDetails(config -> config
|
.assertingPartyDetails(config -> config
|
||||||
.entityId(idpEntityId)
|
.entityId(idpEntityId)
|
||||||
.singleSignOnServiceLocation(webSsoEndpoint))
|
.singleSignOnServiceLocation(webSsoEndpoint)
|
||||||
.credentials(c -> c.add(idpVerificationCertificate))
|
.verificationX509Credentials(c -> c.add(idpVerificationCertificate)))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user