saml2 metadata creation for sp
This commit is contained in:
parent
ce50a72ac1
commit
4c9652abc3
|
@ -0,0 +1,59 @@
|
||||||
|
package eu.eudat.controllers;
|
||||||
|
|
||||||
|
import eu.eudat.logic.proxy.config.configloaders.ConfigLoader;
|
||||||
|
import eu.eudat.logic.security.customproviders.ConfigurableProvider.entities.saml2.Saml2ConfigurableProvider;
|
||||||
|
import eu.eudat.logic.security.validators.configurableProvider.Saml2SSOUtils;
|
||||||
|
import eu.eudat.logic.services.ApiContext;
|
||||||
|
import eu.eudat.models.data.helpers.responses.ResponseItem;
|
||||||
|
import eu.eudat.models.data.security.Principal;
|
||||||
|
import eu.eudat.types.ApiMessageCode;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@CrossOrigin
|
||||||
|
@RequestMapping(value = {"/api/saml2/metadata"})
|
||||||
|
public class Saml2MetadataController extends BaseController {
|
||||||
|
|
||||||
|
private final ConfigLoader configLoader;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public Saml2MetadataController(ApiContext apiContext, ConfigLoader configLoader) {
|
||||||
|
super(apiContext);
|
||||||
|
this.configLoader = configLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(method = RequestMethod.GET, value = {"/{configurableProviderId}"})
|
||||||
|
public @ResponseBody
|
||||||
|
ResponseEntity getMetadata(@PathVariable String configurableProviderId) {
|
||||||
|
Saml2ConfigurableProvider saml2ConfigurableProvider = (Saml2ConfigurableProvider) this.configLoader.getConfigurableProviders().getProviders().stream()
|
||||||
|
.filter(prov -> prov.getConfigurableLoginId().equals(configurableProviderId))
|
||||||
|
.findFirst().orElse(null);
|
||||||
|
if (saml2ConfigurableProvider != null) {
|
||||||
|
try {
|
||||||
|
String metadataXml = Saml2SSOUtils.getMetadata(saml2ConfigurableProvider);
|
||||||
|
HttpHeaders responseHeaders = new HttpHeaders();
|
||||||
|
responseHeaders.setContentLength(metadataXml.length());
|
||||||
|
responseHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
|
||||||
|
responseHeaders.set("Content-Disposition", "attachment;filename=" + configurableProviderId + ".xml");
|
||||||
|
responseHeaders.set("Access-Control-Expose-Headers", "Content-Disposition");
|
||||||
|
responseHeaders.get("Access-Control-Expose-Headers").add("Content-Type");
|
||||||
|
return new ResponseEntity<>(metadataXml.getBytes(StandardCharsets.UTF_8),
|
||||||
|
responseHeaders,
|
||||||
|
HttpStatus.OK);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem<String>().status(ApiMessageCode.ERROR_MESSAGE).message("Failed to fetch metadata."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem<String>().status(ApiMessageCode.ERROR_MESSAGE).message("Failed to fetch metadata."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
package eu.eudat.logic.security.customproviders.ConfigurableProvider.entities.saml2;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
|
||||||
|
public class CertificateInfo {
|
||||||
|
|
||||||
|
public enum KeyFormat {
|
||||||
|
JKS("JKS"), PKCS12("PKCS12");
|
||||||
|
|
||||||
|
private String type;
|
||||||
|
KeyFormat(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
@JsonValue
|
||||||
|
public String getType() { return type; }
|
||||||
|
|
||||||
|
public static KeyFormat fromType(String type) {
|
||||||
|
for (KeyFormat t: KeyFormat.values()) {
|
||||||
|
if (type.equals(t.getType())) {
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Unsupported Keystore format " + type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String alias;
|
||||||
|
private String password;
|
||||||
|
private String keystorePath;
|
||||||
|
private String keystorePassword;
|
||||||
|
private KeyFormat keyFormat;
|
||||||
|
|
||||||
|
public String getAlias() {
|
||||||
|
return alias;
|
||||||
|
}
|
||||||
|
public void setAlias(String alias) {
|
||||||
|
this.alias = alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
public void setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKeystorePath() {
|
||||||
|
return keystorePath;
|
||||||
|
}
|
||||||
|
public void setKeystorePath(String keystorePath) {
|
||||||
|
this.keystorePath = keystorePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKeystorePassword() {
|
||||||
|
return keystorePassword;
|
||||||
|
}
|
||||||
|
public void setKeystorePassword(String keystorePassword) {
|
||||||
|
this.keystorePassword = keystorePassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
public KeyFormat getKeyFormat() {
|
||||||
|
return keyFormat;
|
||||||
|
}
|
||||||
|
public void setKeyFormat(KeyFormat keyFormat) {
|
||||||
|
this.keyFormat = keyFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -47,49 +47,24 @@ public class Saml2ConfigurableProvider extends ConfigurableProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum KeyFormat {
|
|
||||||
JKS("JKS"), PKCS12("PKCS12");
|
|
||||||
|
|
||||||
private String type;
|
|
||||||
KeyFormat(String type) {
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
@JsonValue
|
|
||||||
public String getType() { return type; }
|
|
||||||
|
|
||||||
public static KeyFormat fromType(String type) {
|
|
||||||
for (KeyFormat t: KeyFormat.values()) {
|
|
||||||
if (type.equals(t.getType())) {
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new IllegalArgumentException("Unsupported Keystore format " + type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String spEntityId;
|
private String spEntityId;
|
||||||
private String idpEntityId;
|
private String idpEntityId;
|
||||||
private String idpUrl;
|
private String idpUrl;
|
||||||
private String idpArtifactUrl;
|
private String idpArtifactUrl;
|
||||||
private String idpMetadataUrl;
|
private String idpMetadataUrl;
|
||||||
private boolean assertionEncrypted;
|
private boolean assertionEncrypted;
|
||||||
private KeyFormat keyFormat;
|
private CertificateInfo encryptionCert;
|
||||||
private String keyAlias;
|
private CertificateInfo signingCert;
|
||||||
private String credentialPath;
|
|
||||||
private String archivePassword;
|
|
||||||
private String keyPassword;
|
|
||||||
private boolean responseSigned;
|
private boolean responseSigned;
|
||||||
private boolean assertionSigned;
|
private boolean assertionSigned;
|
||||||
private boolean signatureRequired;
|
private boolean signatureRequired;
|
||||||
private String signatureKeyAlias;
|
|
||||||
private String signaturePath;
|
|
||||||
private String signatureKeyStorePassword;
|
|
||||||
private String signatureKeyPassword;
|
|
||||||
private SAML2UsingFormat usingFormat;
|
private SAML2UsingFormat usingFormat;
|
||||||
private Map<String, SAML2AttributeType> attributeTypes;
|
private Map<String, SAML2AttributeType> attributeTypes;
|
||||||
private Map<String, String> configurableUserFromAttributes;
|
private Map<String, String> configurableUserFromAttributes;
|
||||||
private String binding;
|
private String binding;
|
||||||
private String assertionConsumerServiceUrl;
|
private String assertionConsumerServiceUrl;
|
||||||
|
private boolean wantAssertionsSigned;
|
||||||
|
private boolean authnRequestsSigned;
|
||||||
|
|
||||||
public String getSpEntityId() {
|
public String getSpEntityId() {
|
||||||
return spEntityId;
|
return spEntityId;
|
||||||
|
@ -133,39 +108,18 @@ public class Saml2ConfigurableProvider extends ConfigurableProvider {
|
||||||
this.assertionEncrypted = assertionEncrypted;
|
this.assertionEncrypted = assertionEncrypted;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeyFormat getKeyFormat() {
|
public CertificateInfo getEncryptionCert() {
|
||||||
return keyFormat;
|
return encryptionCert;
|
||||||
}
|
}
|
||||||
public void setKeyFormat(KeyFormat keyFormat) {
|
public void setEncryptionCert(CertificateInfo encryptionCert) {
|
||||||
this.keyFormat = keyFormat;
|
this.encryptionCert = encryptionCert;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getKeyAlias() {
|
public CertificateInfo getSigningCert() {
|
||||||
return keyAlias;
|
return signingCert;
|
||||||
}
|
}
|
||||||
public void setKeyAlias(String keyAlias) {
|
public void setSigningCert(CertificateInfo signingCert) {
|
||||||
this.keyAlias = keyAlias;
|
this.signingCert = signingCert;
|
||||||
}
|
|
||||||
|
|
||||||
public String getCredentialPath() {
|
|
||||||
return credentialPath;
|
|
||||||
}
|
|
||||||
public void setCredentialPath(String credentialPath) {
|
|
||||||
this.credentialPath = credentialPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getArchivePassword() {
|
|
||||||
return archivePassword;
|
|
||||||
}
|
|
||||||
public void setArchivePassword(String archivePassword) {
|
|
||||||
this.archivePassword = archivePassword;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getKeyPassword() {
|
|
||||||
return keyPassword;
|
|
||||||
}
|
|
||||||
public void setKeyPassword(String keyPassword) {
|
|
||||||
this.keyPassword = keyPassword;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isResponseSigned() {
|
public boolean isResponseSigned() {
|
||||||
|
@ -189,34 +143,6 @@ public class Saml2ConfigurableProvider extends ConfigurableProvider {
|
||||||
this.signatureRequired = signatureRequired;
|
this.signatureRequired = signatureRequired;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSignatureKeyAlias() {
|
|
||||||
return signatureKeyAlias;
|
|
||||||
}
|
|
||||||
public void setSignatureKeyAlias(String signatureKeyAlias) {
|
|
||||||
this.signatureKeyAlias = signatureKeyAlias;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSignaturePath() {
|
|
||||||
return signaturePath;
|
|
||||||
}
|
|
||||||
public void setSignaturePath(String signaturePath) {
|
|
||||||
this.signaturePath = signaturePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSignatureKeyStorePassword() {
|
|
||||||
return signatureKeyStorePassword;
|
|
||||||
}
|
|
||||||
public void setSignatureKeyStorePassword(String signatureKeyStorePassword) {
|
|
||||||
this.signatureKeyStorePassword = signatureKeyStorePassword;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSignatureKeyPassword() {
|
|
||||||
return signatureKeyPassword;
|
|
||||||
}
|
|
||||||
public void setSignatureKeyPassword(String signatureKeyPassword) {
|
|
||||||
this.signatureKeyPassword = signatureKeyPassword;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SAML2UsingFormat getUsingFormat() {
|
public SAML2UsingFormat getUsingFormat() {
|
||||||
return usingFormat;
|
return usingFormat;
|
||||||
}
|
}
|
||||||
|
@ -252,4 +178,17 @@ public class Saml2ConfigurableProvider extends ConfigurableProvider {
|
||||||
this.assertionConsumerServiceUrl = assertionConsumerServiceUrl;
|
this.assertionConsumerServiceUrl = assertionConsumerServiceUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isWantAssertionsSigned() {
|
||||||
|
return wantAssertionsSigned;
|
||||||
|
}
|
||||||
|
public void setWantAssertionsSigned(boolean wantAssertionsSigned) {
|
||||||
|
this.wantAssertionsSigned = wantAssertionsSigned;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAuthnRequestsSigned() {
|
||||||
|
return authnRequestsSigned;
|
||||||
|
}
|
||||||
|
public void setAuthnRequestsSigned(boolean authnRequestsSigned) {
|
||||||
|
this.authnRequestsSigned = authnRequestsSigned;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package eu.eudat.logic.security.validators.configurableProvider;
|
package eu.eudat.logic.security.validators.configurableProvider;
|
||||||
|
|
||||||
|
import eu.eudat.logic.security.customproviders.ConfigurableProvider.entities.saml2.CertificateInfo;
|
||||||
import eu.eudat.logic.security.customproviders.ConfigurableProvider.entities.saml2.Saml2ConfigurableProvider;
|
import eu.eudat.logic.security.customproviders.ConfigurableProvider.entities.saml2.Saml2ConfigurableProvider;
|
||||||
|
import eu.eudat.logic.utilities.builders.XmlBuilder;
|
||||||
import jakarta.xml.soap.*;
|
import jakarta.xml.soap.*;
|
||||||
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
|
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
|
||||||
import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
|
import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
|
||||||
|
@ -32,6 +34,7 @@ import org.opensaml.core.xml.config.XMLObjectProviderRegistry;
|
||||||
import org.opensaml.core.xml.io.*;
|
import org.opensaml.core.xml.io.*;
|
||||||
import org.opensaml.core.xml.schema.*;
|
import org.opensaml.core.xml.schema.*;
|
||||||
import org.opensaml.saml.common.SAMLObject;
|
import org.opensaml.saml.common.SAMLObject;
|
||||||
|
import org.opensaml.saml.common.SAMLObjectContentReference;
|
||||||
import org.opensaml.saml.common.SAMLVersion;
|
import org.opensaml.saml.common.SAMLVersion;
|
||||||
import org.opensaml.saml.common.xml.SAMLConstants;
|
import org.opensaml.saml.common.xml.SAMLConstants;
|
||||||
import org.opensaml.saml.criterion.EntityRoleCriterion;
|
import org.opensaml.saml.criterion.EntityRoleCriterion;
|
||||||
|
@ -40,7 +43,7 @@ import org.opensaml.saml.metadata.resolver.impl.HTTPMetadataResolver;
|
||||||
import org.opensaml.saml.metadata.resolver.impl.PredicateRoleDescriptorResolver;
|
import org.opensaml.saml.metadata.resolver.impl.PredicateRoleDescriptorResolver;
|
||||||
import org.opensaml.saml.saml2.core.*;
|
import org.opensaml.saml.saml2.core.*;
|
||||||
import org.opensaml.saml.saml2.encryption.Decrypter;
|
import org.opensaml.saml.saml2.encryption.Decrypter;
|
||||||
import org.opensaml.saml.saml2.metadata.IDPSSODescriptor;
|
import org.opensaml.saml.saml2.metadata.*;
|
||||||
import org.opensaml.saml.security.impl.MetadataCredentialResolver;
|
import org.opensaml.saml.security.impl.MetadataCredentialResolver;
|
||||||
import org.opensaml.security.credential.Credential;
|
import org.opensaml.security.credential.Credential;
|
||||||
import org.opensaml.security.credential.CredentialSupport;
|
import org.opensaml.security.credential.CredentialSupport;
|
||||||
|
@ -55,10 +58,14 @@ import org.opensaml.xml.util.Base64;
|
||||||
import org.opensaml.xmlsec.config.impl.DefaultSecurityConfigurationBootstrap;
|
import org.opensaml.xmlsec.config.impl.DefaultSecurityConfigurationBootstrap;
|
||||||
import org.opensaml.xmlsec.encryption.EncryptedKey;
|
import org.opensaml.xmlsec.encryption.EncryptedKey;
|
||||||
import org.opensaml.xmlsec.keyinfo.KeyInfoCredentialResolver;
|
import org.opensaml.xmlsec.keyinfo.KeyInfoCredentialResolver;
|
||||||
|
import org.opensaml.xmlsec.keyinfo.KeyInfoGenerator;
|
||||||
import org.opensaml.xmlsec.keyinfo.impl.StaticKeyInfoCredentialResolver;
|
import org.opensaml.xmlsec.keyinfo.impl.StaticKeyInfoCredentialResolver;
|
||||||
|
import org.opensaml.xmlsec.keyinfo.impl.X509KeyInfoGeneratorFactory;
|
||||||
import org.opensaml.xmlsec.signature.KeyInfo;
|
import org.opensaml.xmlsec.signature.KeyInfo;
|
||||||
import org.opensaml.xmlsec.signature.Signature;
|
import org.opensaml.xmlsec.signature.Signature;
|
||||||
import org.opensaml.xmlsec.signature.X509Data;
|
import org.opensaml.xmlsec.signature.X509Data;
|
||||||
|
import org.opensaml.xmlsec.signature.impl.SignatureBuilder;
|
||||||
|
import org.opensaml.xmlsec.signature.support.SignatureConstants;
|
||||||
import org.opensaml.xmlsec.signature.support.SignatureValidator;
|
import org.opensaml.xmlsec.signature.support.SignatureValidator;
|
||||||
import org.opensaml.xmlsec.signature.support.Signer;
|
import org.opensaml.xmlsec.signature.support.Signer;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -85,6 +92,7 @@ import java.net.UnknownHostException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.*;
|
import java.security.*;
|
||||||
import java.security.cert.CertificateEncodingException;
|
import java.security.cert.CertificateEncodingException;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
@ -264,7 +272,7 @@ public class Saml2SSOUtils {
|
||||||
|
|
||||||
ArtifactResolve artifactResolve = createArtifactResolveObject(samlArtReceived, saml2Provider.getSpEntityId());
|
ArtifactResolve artifactResolve = createArtifactResolveObject(samlArtReceived, saml2Provider.getSpEntityId());
|
||||||
if (saml2Provider.isSignatureRequired()) {
|
if (saml2Provider.isSignatureRequired()) {
|
||||||
signArtifactResolveReq(artifactResolve, saml2Provider);
|
signArtifactResolveReq(artifactResolve, saml2Provider.getSigningCert());
|
||||||
}
|
}
|
||||||
return artifactResolve;
|
return artifactResolve;
|
||||||
|
|
||||||
|
@ -290,14 +298,14 @@ public class Saml2SSOUtils {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void signArtifactResolveReq(ArtifactResolve artifactResolve, Saml2ConfigurableProvider saml2Provider) throws Exception {
|
private static void signArtifactResolveReq(ArtifactResolve artifactResolve, CertificateInfo singingCertificateInfo) throws Exception {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
KeyStore ks = KeyStore.getInstance("JKS");
|
KeyStore ks = KeyStore.getInstance("JKS");
|
||||||
String archivePassword = saml2Provider.getSignatureKeyStorePassword();
|
String archivePassword = singingCertificateInfo.getKeystorePassword();
|
||||||
char[] pwdArray = (archivePassword != null) ? archivePassword.toCharArray() : "changeit".toCharArray();
|
char[] pwdArray = (archivePassword != null) ? archivePassword.toCharArray() : "changeit".toCharArray();
|
||||||
ks.load(new FileInputStream(saml2Provider.getSignaturePath()), pwdArray);
|
ks.load(new FileInputStream(singingCertificateInfo.getKeystorePath()), pwdArray);
|
||||||
X509Credential cred = new KeyStoreX509CredentialAdapter(ks, saml2Provider.getSignatureKeyAlias(), saml2Provider.getSignatureKeyPassword().toCharArray());
|
X509Credential cred = new KeyStoreX509CredentialAdapter(ks, singingCertificateInfo.getAlias(), singingCertificateInfo.getPassword().toCharArray());
|
||||||
Signature signature = setSignatureRaw(XMLSignature.ALGO_ID_SIGNATURE_RSA, cred);
|
Signature signature = setSignatureRaw(XMLSignature.ALGO_ID_SIGNATURE_RSA, cred);
|
||||||
artifactResolve.setSignature(signature);
|
artifactResolve.setSignature(signature);
|
||||||
|
|
||||||
|
@ -541,7 +549,7 @@ public class Saml2SSOUtils {
|
||||||
if (!CollectionUtils.isEmpty(encryptedAssertions)) {
|
if (!CollectionUtils.isEmpty(encryptedAssertions)) {
|
||||||
encryptedAssertion = encryptedAssertions.get(0);
|
encryptedAssertion = encryptedAssertions.get(0);
|
||||||
try {
|
try {
|
||||||
assertion = getDecryptedAssertion(encryptedAssertion, saml2Provider);
|
assertion = getDecryptedAssertion(encryptedAssertion, saml2Provider.getEncryptionCert());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new Exception("Unable to decrypt the SAML2 Assertion");
|
throw new Exception("Unable to decrypt the SAML2 Assertion");
|
||||||
}
|
}
|
||||||
|
@ -601,15 +609,15 @@ public class Saml2SSOUtils {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Assertion getDecryptedAssertion(EncryptedAssertion encryptedAssertion, Saml2ConfigurableProvider saml2Provider) throws Exception {
|
private static Assertion getDecryptedAssertion(EncryptedAssertion encryptedAssertion, CertificateInfo encryptionCertificateInfo) throws Exception {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
KeyStore ks = (saml2Provider.getKeyFormat().getType().equals("JKS")) ? KeyStore.getInstance("JKS") : KeyStore.getInstance("PKCS12");
|
KeyStore ks = (encryptionCertificateInfo.getKeyFormat().getType().equals("JKS")) ? KeyStore.getInstance("JKS") : KeyStore.getInstance("PKCS12");
|
||||||
String archivePassword = saml2Provider.getArchivePassword();
|
String archivePassword = encryptionCertificateInfo.getKeystorePassword();
|
||||||
char[] pwdArray = (archivePassword != null) ? archivePassword.toCharArray() : "changeit".toCharArray();
|
char[] pwdArray = (archivePassword != null) ? archivePassword.toCharArray() : "changeit".toCharArray();
|
||||||
ks.load(new FileInputStream(saml2Provider.getCredentialPath()), pwdArray);
|
ks.load(new FileInputStream(encryptionCertificateInfo.getKeystorePath()), pwdArray);
|
||||||
X509Certificate cert = (X509Certificate)ks.getCertificate(saml2Provider.getKeyAlias());
|
X509Certificate cert = (X509Certificate)ks.getCertificate(encryptionCertificateInfo.getAlias());
|
||||||
PrivateKey pk = (PrivateKey) ks.getKey(saml2Provider.getKeyAlias(), saml2Provider.getKeyPassword().toCharArray());
|
PrivateKey pk = (PrivateKey) ks.getKey(encryptionCertificateInfo.getAlias(), encryptionCertificateInfo.getPassword().toCharArray());
|
||||||
KeyInfoCredentialResolver keyResolver = new StaticKeyInfoCredentialResolver(
|
KeyInfoCredentialResolver keyResolver = new StaticKeyInfoCredentialResolver(
|
||||||
new BasicX509Credential(cert, pk));
|
new BasicX509Credential(cert, pk));
|
||||||
EncryptedKey key = encryptedAssertion.getEncryptedData().getKeyInfo().getEncryptedKeys().get(0);
|
EncryptedKey key = encryptedAssertion.getEncryptedData().getKeyInfo().getEncryptedKeys().get(0);
|
||||||
|
@ -685,4 +693,105 @@ public class Saml2SSOUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Credential getCredential(CertificateInfo certificateInfo) throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException {
|
||||||
|
KeyStore ks = (certificateInfo.getKeyFormat().getType().equals("JKS")) ? KeyStore.getInstance("JKS") : KeyStore.getInstance("PKCS12");
|
||||||
|
String archivePassword = certificateInfo.getKeystorePassword();
|
||||||
|
char[] pwdArray = (archivePassword != null) ? archivePassword.toCharArray() : "changeit".toCharArray();
|
||||||
|
ks.load(new FileInputStream(certificateInfo.getKeystorePath()), pwdArray);
|
||||||
|
X509Certificate cert = (X509Certificate)ks.getCertificate(certificateInfo.getAlias());
|
||||||
|
PrivateKey pk = (PrivateKey) ks.getKey(certificateInfo.getAlias(), certificateInfo.getPassword().toCharArray());
|
||||||
|
return new BasicX509Credential(cert, pk);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getMetadata(Saml2ConfigurableProvider provider) throws Exception {
|
||||||
|
|
||||||
|
EntityDescriptor spEntityDescriptor = (EntityDescriptor) buildXMLObject(EntityDescriptor.DEFAULT_ELEMENT_NAME);
|
||||||
|
spEntityDescriptor.setEntityID(provider.getSpEntityId());
|
||||||
|
SPSSODescriptor spSSODescriptor = (SPSSODescriptor) buildXMLObject(SPSSODescriptor.DEFAULT_ELEMENT_NAME);
|
||||||
|
|
||||||
|
spSSODescriptor.setWantAssertionsSigned(provider.isWantAssertionsSigned()); spSSODescriptor.setAuthnRequestsSigned(provider.isAuthnRequestsSigned());
|
||||||
|
|
||||||
|
X509KeyInfoGeneratorFactory keyInfoGeneratorFactory = new X509KeyInfoGeneratorFactory();
|
||||||
|
keyInfoGeneratorFactory.setEmitEntityCertificate(true);
|
||||||
|
KeyInfoGenerator keyInfoGenerator = keyInfoGeneratorFactory.newInstance();
|
||||||
|
|
||||||
|
if (provider.isAssertionEncrypted()) {
|
||||||
|
|
||||||
|
KeyDescriptor encKeyDescriptor = (KeyDescriptor) buildXMLObject(KeyDescriptor.DEFAULT_ELEMENT_NAME);
|
||||||
|
|
||||||
|
encKeyDescriptor.setUse(UsageType.ENCRYPTION); //Set usage
|
||||||
|
|
||||||
|
// Generating key info. The element will contain the public key. The key is used to by the IDP to encrypt data
|
||||||
|
try {
|
||||||
|
encKeyDescriptor.setKeyInfo(keyInfoGenerator.generate(getCredential(provider.getEncryptionCert())));
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
logger.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
spSSODescriptor.getKeyDescriptors().add(encKeyDescriptor);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (provider.isWantAssertionsSigned()) {
|
||||||
|
|
||||||
|
KeyDescriptor signKeyDescriptor = (KeyDescriptor) buildXMLObject(KeyDescriptor.DEFAULT_ELEMENT_NAME);
|
||||||
|
|
||||||
|
signKeyDescriptor.setUse(UsageType.SIGNING); //Set usage
|
||||||
|
|
||||||
|
// Generating key info. The element will contain the public key. The key is used to by the IDP to verify signatures
|
||||||
|
try {
|
||||||
|
signKeyDescriptor.setKeyInfo(keyInfoGenerator.generate(getCredential(provider.getSigningCert())));
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
logger.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
spSSODescriptor.getKeyDescriptors().add(signKeyDescriptor);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
NameIDFormat nameIDFormat = (NameIDFormat) buildXMLObject(NameIDFormat.DEFAULT_ELEMENT_NAME);
|
||||||
|
nameIDFormat.setFormat("urn:oasis:names:tc:SAML:2.0:nameid-format:transient");
|
||||||
|
spSSODescriptor.getNameIDFormats().add(nameIDFormat);
|
||||||
|
|
||||||
|
|
||||||
|
AssertionConsumerService assertionConsumerService = (AssertionConsumerService) buildXMLObject(AssertionConsumerService.DEFAULT_ELEMENT_NAME);
|
||||||
|
assertionConsumerService.setIndex(0);
|
||||||
|
switch (provider.getBinding()) {
|
||||||
|
case "Redirect":
|
||||||
|
assertionConsumerService.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);
|
||||||
|
break;
|
||||||
|
case "Artifact":
|
||||||
|
assertionConsumerService.setBinding(SAMLConstants.SAML2_ARTIFACT_BINDING_URI);
|
||||||
|
break;
|
||||||
|
case "Post":
|
||||||
|
assertionConsumerService.setBinding(SAMLConstants.SAML2_POST_BINDING_URI);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
assertionConsumerService.setLocation(provider.getAssertionConsumerServiceUrl());
|
||||||
|
spSSODescriptor.getAssertionConsumerServices().add(assertionConsumerService);
|
||||||
|
|
||||||
|
|
||||||
|
spSSODescriptor.addSupportedProtocol(SAMLConstants.SAML20P_NS);
|
||||||
|
|
||||||
|
spEntityDescriptor.getRoleDescriptors().add(spSSODescriptor);
|
||||||
|
|
||||||
|
|
||||||
|
String metadataXML = null;
|
||||||
|
try {
|
||||||
|
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||||
|
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||||
|
Document document = builder.newDocument();
|
||||||
|
Marshaller out = registry.getMarshallerFactory().getMarshaller(spEntityDescriptor);
|
||||||
|
out.marshall(spEntityDescriptor, document);
|
||||||
|
|
||||||
|
metadataXML = XmlBuilder.generateXml(document);
|
||||||
|
}
|
||||||
|
catch (MarshallingException | ParserConfigurationException e) {
|
||||||
|
logger.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
return metadataXML;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -30,6 +30,43 @@
|
||||||
"type": "saml2",
|
"type": "saml2",
|
||||||
"configurableLoginId": "",
|
"configurableLoginId": "",
|
||||||
"name": ""
|
"name": ""
|
||||||
|
"name": "",
|
||||||
|
"spEntityId": "",
|
||||||
|
"idpEntityId": "",
|
||||||
|
"idpUrl": "",
|
||||||
|
"idpMetadataUrl": "",
|
||||||
|
"idpArtifactUrl": "",
|
||||||
|
"binding": "Redirect",
|
||||||
|
"logoUrl": "",
|
||||||
|
"responseSigned": true,
|
||||||
|
"assertionSigned": true,
|
||||||
|
"assertionEncrypted": true,
|
||||||
|
"encryptionCert" : {
|
||||||
|
"alias": "",
|
||||||
|
"password": "",
|
||||||
|
"keystorePath": "encryptionkeystore.jks",
|
||||||
|
"keystorePassword": "",
|
||||||
|
"keyFormat": "JKS"
|
||||||
|
},
|
||||||
|
"signingCert" : {
|
||||||
|
"alias": "",
|
||||||
|
"password": "",
|
||||||
|
"keystorePath": "signingkeystore.jks",
|
||||||
|
"keystorePassword": "",
|
||||||
|
"keyFormat": "JKS"
|
||||||
|
},
|
||||||
|
"assertionConsumerServiceUrl": "",
|
||||||
|
"wantAssertionsSigned": true,
|
||||||
|
"authnRequestsSigned": true,
|
||||||
|
"usingFormat": "friendly_name",
|
||||||
|
"configurableUserFromAttributes": {
|
||||||
|
"email": "email",
|
||||||
|
"name": "givenName"
|
||||||
|
},
|
||||||
|
"attributeTypes": {
|
||||||
|
"email": "XSString",
|
||||||
|
"givenName": "XSString"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue