/* * Copyright 2014 Federal Chancellery Austria * MOA-ID has been developed in a cooperation between BRZ, the Federal * Chancellery Austria - ICT staff unit, and Graz University of Technology. * * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by * the European Commission - subsequent versions of the EUPL (the "Licence"); * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: * http://www.osor.eu/eupl/ * * Unless required by applicable law or agreed to in writing, software * distributed under the Licence is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and * limitations under the Licence. * * This product combines work with different licenses. See the "NOTICE" text * file for details on the various modules and licenses. * The "NOTICE" text file is part of the distribution. Any derivative works * that you distribute must include a readable copy of the "NOTICE" text file. */ package at.gv.egovernment.moa.id.auth.modules.eidas.utils; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Set; import org.apache.commons.lang.StringUtils; import org.joda.time.DateTime; import org.joda.time.DurationFieldType; import org.opensaml.Configuration; import org.opensaml.common.xml.SAMLConstants; import org.opensaml.saml2.common.Extensions; import org.opensaml.saml2.common.impl.ExtensionsBuilder; import org.opensaml.saml2.core.Attribute; import org.opensaml.saml2.core.AttributeValue; import org.opensaml.saml2.metadata.AssertionConsumerService; import org.opensaml.saml2.metadata.Company; import org.opensaml.saml2.metadata.ContactPerson; import org.opensaml.saml2.metadata.ContactPersonTypeEnumeration; import org.opensaml.saml2.metadata.EmailAddress; import org.opensaml.saml2.metadata.EncryptionMethod; import org.opensaml.saml2.metadata.EntitiesDescriptor; import org.opensaml.saml2.metadata.EntityDescriptor; import org.opensaml.saml2.metadata.GivenName; import org.opensaml.saml2.metadata.IDPSSODescriptor; import org.opensaml.saml2.metadata.KeyDescriptor; import org.opensaml.saml2.metadata.LocalizedString; import org.opensaml.saml2.metadata.NameIDFormat; import org.opensaml.saml2.metadata.Organization; import org.opensaml.saml2.metadata.OrganizationDisplayName; import org.opensaml.saml2.metadata.OrganizationName; import org.opensaml.saml2.metadata.OrganizationURL; import org.opensaml.saml2.metadata.SPSSODescriptor; import org.opensaml.saml2.metadata.SSODescriptor; import org.opensaml.saml2.metadata.SingleSignOnService; import org.opensaml.saml2.metadata.SurName; import org.opensaml.saml2.metadata.TelephoneNumber; import org.opensaml.samlext.saml2mdattr.EntityAttributes; import org.opensaml.xml.XMLObject; import org.opensaml.xml.XMLObjectBuilderFactory; import org.opensaml.xml.schema.XSString; import org.opensaml.xml.schema.impl.XSStringBuilder; import org.opensaml.xml.security.SecurityException; import org.opensaml.xml.security.credential.Credential; import org.opensaml.xml.security.credential.UsageType; import org.opensaml.xml.security.keyinfo.KeyInfoGenerator; import org.opensaml.xml.security.x509.X509KeyInfoGeneratorFactory; import org.opensaml.xml.signature.KeyInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.Ordering; import at.gv.egovernment.moa.id.auth.modules.eidas.Constants; import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils; import eu.eidas.auth.commons.EIDASUtil; import eu.eidas.auth.commons.EidasStringUtil; import eu.eidas.auth.commons.attribute.AttributeDefinition; import eu.eidas.auth.commons.protocol.impl.SamlNameIdFormat; import eu.eidas.auth.commons.xml.opensaml.OpenSamlHelper; import eu.eidas.auth.engine.ProtocolEngineI; import eu.eidas.auth.engine.core.SAMLExtensionFormat; import eu.eidas.auth.engine.core.eidas.DigestMethod; import eu.eidas.auth.engine.core.eidas.EidasConstants; import eu.eidas.auth.engine.core.eidas.SPType; import eu.eidas.auth.engine.core.eidas.SigningMethod; import eu.eidas.auth.engine.metadata.Contact; import eu.eidas.auth.engine.metadata.EntityDescriptorContainer; import eu.eidas.auth.engine.metadata.MetadataConfigParams; import eu.eidas.auth.engine.metadata.MetadataGenerator; import eu.eidas.auth.engine.metadata.MetadataSignerI; import eu.eidas.auth.engine.xml.opensaml.BuilderFactoryUtil; import eu.eidas.auth.engine.xml.opensaml.CertificateUtil; import eu.eidas.encryption.exception.UnmarshallException; import eu.eidas.engine.exceptions.EIDASSAMLEngineException; import eu.eidas.engine.exceptions.SAMLEngineException; /** * @author tlenz * */ public class MOAeIDASMetadataGenerator extends MetadataGenerator { private static final Logger LOGGER = LoggerFactory.getLogger(MetadataGenerator.class.getName()); MetadataConfigParams params; XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory(); SPSSODescriptor spSSODescriptor = null; IDPSSODescriptor idpSSODescriptor = null; private String ssoLocation; /** * @return a String representation of the entityDescriptr built based on the attributes previously set */ public String generateMetadata() throws EIDASSAMLEngineException { EntityDescriptor entityDescriptor; try { entityDescriptor = (EntityDescriptor) builderFactory.getBuilder(EntityDescriptor.DEFAULT_ELEMENT_NAME) .buildObject(EntityDescriptor.DEFAULT_ELEMENT_NAME); entityDescriptor.setEntityID(params.getEntityID()); entityDescriptor.setOrganization(buildOrganization()); /**FIXME: * HOTFIX: do not add empty contactPerson elements */ ContactPerson contactSupport = buildContact(ContactPersonTypeEnumeration.SUPPORT); if (contactSupport != null) entityDescriptor.getContactPersons().add(contactSupport); ContactPerson contactTech = buildContact(ContactPersonTypeEnumeration.TECHNICAL); if (contactTech != null) entityDescriptor.getContactPersons().add(contactTech); entityDescriptor.setValidUntil(getExpireDate()); X509KeyInfoGeneratorFactory keyInfoGeneratorFactory = new X509KeyInfoGeneratorFactory(); keyInfoGeneratorFactory.setEmitEntityCertificate(true); Extensions e = generateExtensions(); if (!e.getUnknownXMLObjects().isEmpty()) { entityDescriptor.setExtensions(e); } if (spSSODescriptor != null) { generateSPSSODescriptor(entityDescriptor, keyInfoGeneratorFactory); } if (idpSSODescriptor != null) { generateIDPSSODescriptor(entityDescriptor, keyInfoGeneratorFactory); } if (params.getSpEngine() != null) { ProtocolEngineI spEngine = params.getSpEngine(); ((MetadataSignerI) spEngine.getSigner()).signMetadata(entityDescriptor); } else if (params.getIdpEngine() != null) { ProtocolEngineI idpEngine = params.getIdpEngine(); ((MetadataSignerI) idpEngine.getSigner()).signMetadata(entityDescriptor); } return EidasStringUtil.toString(OpenSamlHelper.marshall(entityDescriptor, false)); } catch (Exception ex) { LOGGER.info("ERROR : SAMLException ", ex.getMessage()); LOGGER.debug("ERROR : SAMLException ", ex); throw new IllegalStateException(ex); } } private void generateSPSSODescriptor(final EntityDescriptor entityDescriptor, final X509KeyInfoGeneratorFactory keyInfoGeneratorFactory) throws org.opensaml.xml.security.SecurityException, IllegalAccessException, NoSuchFieldException, SAMLEngineException, EIDASSAMLEngineException { //the node has SP role spSSODescriptor.setWantAssertionsSigned(params.isWantAssertionsSigned()); spSSODescriptor.setAuthnRequestsSigned(true); /**FIXME: * "SP" + params.getEntityID()) is not a valid XML ID attribute value */ //spSSODescriptor.setID(idpSSODescriptor == null ? params.getEntityID() : ("SP" + params.getEntityID())); spSSODescriptor.setID(SAML2Utils.getSecureIdentifier()); if (params.getSPSignature() != null) { spSSODescriptor.setSignature(params.getSPSignature()); } if (params.getSpSigningCredential() != null) { spSSODescriptor.getKeyDescriptors() .add(getKeyDescriptor(keyInfoGeneratorFactory, params.getSpSigningCredential(), UsageType.SIGNING)); } else if (params.getSigningCredential() != null) { spSSODescriptor.getKeyDescriptors() .add(getKeyDescriptor(keyInfoGeneratorFactory, params.getSigningCredential(), UsageType.SIGNING)); } if (params.getSpEncryptionCredential() != null) { spSSODescriptor.getKeyDescriptors() .add(getKeyDescriptor(keyInfoGeneratorFactory, params.getSpEncryptionCredential(), UsageType.ENCRYPTION)); } else if (params.getEncryptionCredential() != null) { spSSODescriptor.getKeyDescriptors() .add(getKeyDescriptor(keyInfoGeneratorFactory, params.getEncryptionCredential(), UsageType.ENCRYPTION)); } spSSODescriptor.addSupportedProtocol(params.getSpSamlProtocol()); if (!StringUtils.isEmpty(params.getAssertionConsumerUrl())) { addAssertionConsumerService(); } fillNameIDFormat(spSSODescriptor); if (params.getSpEngine() != null) { ProtocolEngineI spEngine = params.getSpEngine(); ((MetadataSignerI) spEngine.getSigner()).signMetadata(spSSODescriptor); } entityDescriptor.getRoleDescriptors().add(spSSODescriptor); } private void fillNameIDFormat(SSODescriptor ssoDescriptor) throws EIDASSAMLEngineException { NameIDFormat persistentFormat = (NameIDFormat) BuilderFactoryUtil.buildXmlObject(NameIDFormat.DEFAULT_ELEMENT_NAME); persistentFormat.setFormat(SamlNameIdFormat.PERSISTENT.getNameIdFormat()); ssoDescriptor.getNameIDFormats().add(persistentFormat); NameIDFormat transientFormat = (NameIDFormat) BuilderFactoryUtil.buildXmlObject(NameIDFormat.DEFAULT_ELEMENT_NAME); transientFormat.setFormat(SamlNameIdFormat.TRANSIENT.getNameIdFormat()); ssoDescriptor.getNameIDFormats().add(transientFormat); NameIDFormat unspecifiedFormat = (NameIDFormat) BuilderFactoryUtil.buildXmlObject(NameIDFormat.DEFAULT_ELEMENT_NAME); unspecifiedFormat.setFormat(SamlNameIdFormat.UNSPECIFIED.getNameIdFormat()); ssoDescriptor.getNameIDFormats().add(unspecifiedFormat); } private void generateIDPSSODescriptor(final EntityDescriptor entityDescriptor, final X509KeyInfoGeneratorFactory keyInfoGeneratorFactory) throws org.opensaml.xml.security.SecurityException, IllegalAccessException, NoSuchFieldException, SAMLEngineException, EIDASSAMLEngineException { //the node has IDP role idpSSODescriptor.setWantAuthnRequestsSigned(true); /**FIXME: * "IDP" + params.getEntityID()) is not a valid XML ID attribute value */ //idpSSODescriptor.setID(spSSODescriptor == null ? params.getEntityID() : ("IDP" + params.getEntityID())); idpSSODescriptor.setID(SAML2Utils.getSecureIdentifier()); if (params.getIDPSignature() != null) { idpSSODescriptor.setSignature(params.getIDPSignature()); } if (params.getIdpSigningCredential() != null) { idpSSODescriptor.getKeyDescriptors() .add(getKeyDescriptor(keyInfoGeneratorFactory, params.getIdpSigningCredential(), UsageType.SIGNING)); } else if (params.getSigningCredential() != null) { idpSSODescriptor.getKeyDescriptors() .add(getKeyDescriptor(keyInfoGeneratorFactory, params.getSigningCredential(), UsageType.SIGNING)); } if (params.getIdpEncryptionCredential() != null) { idpSSODescriptor.getKeyDescriptors() .add(getKeyDescriptor(keyInfoGeneratorFactory, params.getIdpEncryptionCredential(), UsageType.ENCRYPTION)); } else if (params.getEncryptionCredential() != null) { idpSSODescriptor.getKeyDescriptors() .add(getKeyDescriptor(keyInfoGeneratorFactory, params.getEncryptionCredential(), UsageType.ENCRYPTION)); } idpSSODescriptor.addSupportedProtocol(params.getIdpSamlProtocol()); fillNameIDFormat(idpSSODescriptor); if (params.getIdpEngine() != null) { if (params.getIdpEngine().getProtocolProcessor() != null && params.getIdpEngine().getProtocolProcessor().getFormat() == SAMLExtensionFormat.EIDAS10) { /*TODO: Only a work-around to add eIDAS attributes, which could be provided from MOA-ID, to IDP metadata * If we restrict the eIDAS Engine attribute definitions then also additional incoming attributes can not processed any more. * * INFO: Maybe, this code can be removed in a future version of the eIDAS engine */ generateSupportedAttributes(idpSSODescriptor, getAllSupportedAttributes()); } ProtocolEngineI idpEngine = params.getIdpEngine(); ((MetadataSignerI) idpEngine.getSigner()).signMetadata(idpSSODescriptor); } idpSSODescriptor.getSingleSignOnServices().addAll(buildSingleSignOnServicesBindingLocations()); entityDescriptor.getRoleDescriptors().add(idpSSODescriptor); } /*TODO: Only a work-around to add eIDAS attributes, which could be provided from MOA-ID, to IDP metadata * If we restrict the eIDAS Engine attribute definitions then also additional incoming attributes can not processed any more. */ public ImmutableSortedSet> getAllSupportedAttributes() { ImmutableSortedSet.Builder> builder = new ImmutableSortedSet.Builder<>(Ordering.>natural()); builder.addAll(Constants.MOA_IDP_ATTR_REGISTRY.getAttributes()); return builder.build(); } private ArrayList buildSingleSignOnServicesBindingLocations() throws NoSuchFieldException, IllegalAccessException { ArrayList singleSignOnServices = new ArrayList(); HashMap bindingLocations = params.getProtocolBindingLocation(); for (String binding : bindingLocations.keySet()) { SingleSignOnService ssos = BuilderFactoryUtil.buildXmlObject(SingleSignOnService.class); ssos.setBinding(binding); ssos.setLocation(bindingLocations.get(binding)); singleSignOnServices.add(ssos); } return singleSignOnServices; } /** * @param metadata * @return an EntityDescriptor parsed from the given String or null */ // TODO (commented by donydgr) Move to a eu.eidas.auth.engine.metadata.MetadataUtil ? Throw an exception if the metadata is invalid instead of returning null ? public static EntityDescriptorContainer deserializeEntityDescriptor(String metadata) { EntityDescriptorContainer result = new EntityDescriptorContainer(); try { byte[] metaDataBytes = EidasStringUtil.getBytes(metadata); XMLObject obj = OpenSamlHelper.unmarshall(metaDataBytes); if (obj instanceof EntityDescriptor) { result.addEntityDescriptor((EntityDescriptor) obj, metaDataBytes); } else if (obj instanceof EntitiesDescriptor) { EntitiesDescriptor ed = (EntitiesDescriptor) obj; result.setEntitiesDescriptor(ed); result.getEntityDescriptors().addAll(((EntitiesDescriptor) obj).getEntityDescriptors()); result.setSerializedEntitesDescriptor(metaDataBytes); } } catch (UnmarshallException ue) { LOGGER.info("ERROR : unmarshalling error", ue.getMessage()); LOGGER.debug("ERROR : unmarshalling error", ue); } return result; } private KeyDescriptor getKeyDescriptor(X509KeyInfoGeneratorFactory keyInfoGeneratorFactory, Credential credential, UsageType usage) throws NoSuchFieldException, IllegalAccessException, SecurityException, EIDASSAMLEngineException { KeyDescriptor keyDescriptor = null; if (credential != null) { keyDescriptor = BuilderFactoryUtil.buildXmlObject(KeyDescriptor.class); KeyInfoGenerator keyInfoGenerator = keyInfoGeneratorFactory.newInstance(); KeyInfo keyInfo = keyInfoGenerator.generate(credential); keyDescriptor.setUse(usage); keyDescriptor.setKeyInfo(keyInfo); if (usage == UsageType.ENCRYPTION && params.getEncryptionAlgorithms() != null) { Set encryptionAlgos = EIDASUtil.parseSemicolonSeparatedList(params.getEncryptionAlgorithms()); for (String encryptionAlgo : encryptionAlgos) { EncryptionMethod em = (EncryptionMethod) BuilderFactoryUtil.buildXmlObject(EncryptionMethod.DEFAULT_ELEMENT_NAME); em.setAlgorithm(encryptionAlgo); keyDescriptor.getEncryptionMethods().add(em); } } } return keyDescriptor; } private Organization buildOrganization() { Organization organization = null; try { organization = BuilderFactoryUtil.buildXmlObject(Organization.class); /**FIXME: * set correct OrganizationName value if it is not fixed in next eIDAS node version */ OrganizationName orgName = BuilderFactoryUtil.buildXmlObject(OrganizationName.class); orgName.setName(new LocalizedString(params.getNodeUrl(), "en")); organization.getOrganizationNames().add(orgName); OrganizationDisplayName odn = BuilderFactoryUtil.buildXmlObject(OrganizationDisplayName.class); odn.setName(new LocalizedString(params.getCountryName(), "en")); organization.getDisplayNames().add(odn); OrganizationURL url = BuilderFactoryUtil.buildXmlObject(OrganizationURL.class); url.setURL(new LocalizedString(params.getNodeUrl(), "en")); organization.getURLs().add(url); } catch (IllegalAccessException iae) { LOGGER.info("ERROR : error generating the Organization: {}", iae.getMessage()); LOGGER.debug("ERROR : error generating the Organization: {}", iae); } catch (NoSuchFieldException nfe) { LOGGER.info("ERROR : error generating the Organization: {}", nfe.getMessage()); LOGGER.debug("ERROR : error generating the Organization: {}", nfe); } return organization; } private ContactPerson buildContact(ContactPersonTypeEnumeration contactType) { ContactPerson contact = null; try { Contact currentContact = null; if (contactType == ContactPersonTypeEnumeration.SUPPORT) { currentContact = params.getSupportContact(); } else if (contactType == ContactPersonTypeEnumeration.TECHNICAL) { currentContact = params.getTechnicalContact(); } else { LOGGER.error("ERROR: unsupported contact type"); } contact = BuilderFactoryUtil.buildXmlObject(ContactPerson.class); if (currentContact == null) { LOGGER.error("ERROR: cannot retrieve contact from the configuration"); return null; } EmailAddress emailAddressObj = BuilderFactoryUtil.buildXmlObject(EmailAddress.class); Company company = BuilderFactoryUtil.buildXmlObject(Company.class); GivenName givenName = BuilderFactoryUtil.buildXmlObject(GivenName.class); SurName surName = BuilderFactoryUtil.buildXmlObject(SurName.class); TelephoneNumber phoneNumber = BuilderFactoryUtil.buildXmlObject(TelephoneNumber.class); contact.setType(contactType); emailAddressObj.setAddress(currentContact.getEmail()); company.setName(currentContact.getCompany()); givenName.setName(currentContact.getGivenName()); surName.setName(currentContact.getSurName()); phoneNumber.setNumber(currentContact.getPhone()); populateContact(contact, currentContact, emailAddressObj, company, givenName, surName, phoneNumber); } catch (IllegalAccessException iae) { LOGGER.info("ERROR : error generating the Organization: {}", iae.getMessage()); LOGGER.debug("ERROR : error generating the Organization: {}", iae); } catch (NoSuchFieldException nfe) { LOGGER.info("ERROR : error generating the Organization: {}", nfe.getMessage()); LOGGER.debug("ERROR : error generating the Organization: {}", nfe); } return contact; } private void populateContact(ContactPerson contact, Contact currentContact, EmailAddress emailAddressObj, Company company, GivenName givenName, SurName surName, TelephoneNumber phoneNumber) { if (!StringUtils.isEmpty(currentContact.getEmail())) { contact.getEmailAddresses().add(emailAddressObj); } if (!StringUtils.isEmpty(currentContact.getCompany())) { contact.setCompany(company); } if (!StringUtils.isEmpty(currentContact.getGivenName())) { contact.setGivenName(givenName); } if (!StringUtils.isEmpty(currentContact.getSurName())) { contact.setSurName(surName); } if (!StringUtils.isEmpty(currentContact.getPhone())) { contact.getTelephoneNumbers().add(phoneNumber); } } /** * @param engine a EIDASSamlEngine from which signing and encryption information is extracted */ public void initialize(ProtocolEngineI engine) throws EIDASSAMLEngineException { X509Certificate decryptionCertificate = engine.getDecryptionCertificate(); if (null != decryptionCertificate) { params.setEncryptionCredential(CertificateUtil.toCredential(decryptionCertificate)); } params.setSigningCredential(CertificateUtil.toCredential(engine.getSigningCertificate())); params.setIdpEngine(engine); params.setSpEngine(engine); } /** * @param spEngine a EIDASSamlEngine for the */ public void initialize(ProtocolEngineI spEngine, ProtocolEngineI idpEngine) throws EIDASSAMLEngineException { if (idpEngine != null) { idpEngine.getProtocolProcessor().configure(); params.setIdpSigningCredential(CertificateUtil.toCredential(idpEngine.getSigningCertificate())); final X509Certificate idpEngineDecryptionCertificate = idpEngine.getDecryptionCertificate(); if (idpEngineDecryptionCertificate != null) { params.setIdpEncryptionCredential(CertificateUtil.toCredential(idpEngineDecryptionCertificate)); } } if (spEngine != null) { spEngine.getProtocolProcessor().configure(); params.setSpSigningCredential(CertificateUtil.toCredential(spEngine.getSigningCertificate())); final X509Certificate spEngineDecryptionCertificate = spEngine.getDecryptionCertificate(); if (spEngineDecryptionCertificate != null) { params.setSpEncryptionCredential(CertificateUtil.toCredential(spEngineDecryptionCertificate)); } } params.setIdpEngine(idpEngine); params.setSpEngine(spEngine); } public void addSPRole() throws EIDASSAMLEngineException { try { if (spSSODescriptor == null) { spSSODescriptor = BuilderFactoryUtil.buildXmlObject(SPSSODescriptor.class); } } catch (IllegalAccessException iae) { throw new EIDASSAMLEngineException(iae); } catch (NoSuchFieldException nsfe) { throw new EIDASSAMLEngineException(nsfe); } } public void addIDPRole() throws EIDASSAMLEngineException { try { if (idpSSODescriptor == null) { idpSSODescriptor = BuilderFactoryUtil.buildXmlObject(IDPSSODescriptor.class); } } catch (IllegalAccessException iae) { throw new EIDASSAMLEngineException(iae); } catch (NoSuchFieldException nsfe) { throw new EIDASSAMLEngineException(nsfe); } } private void generateDigest(Extensions eidasExtensions) throws EIDASSAMLEngineException { if (!StringUtils.isEmpty(params.getDigestMethods())) { Set signatureMethods = EIDASUtil.parseSemicolonSeparatedList(params.getDigestMethods()); Set digestMethods = new HashSet(); for (String signatureMethod : signatureMethods) { digestMethods.add(CertificateUtil.validateDigestAlgorithm(signatureMethod)); } for (String digestMethod : digestMethods) { final DigestMethod dm = (DigestMethod) BuilderFactoryUtil.buildXmlObject(DigestMethod.DEF_ELEMENT_NAME); if (dm != null) { dm.setAlgorithm(digestMethod); eidasExtensions.getUnknownXMLObjects().add(dm); } else { LOGGER.info("BUSINESS EXCEPTION error adding DigestMethod extension"); } } } } private Extensions generateExtensions() throws EIDASSAMLEngineException { /**FIXME: BuilderFactoryUtil.generateExtension() generates extensions from SAML2 request namespace * but SAML2 metadata namespace is required **/ //Extensions eidasExtensions = BuilderFactoryUtil.generateExtension(); ExtensionsBuilder extensionsBuilder = new ExtensionsBuilder(); Extensions eidasExtensions = extensionsBuilder.buildObject("urn:oasis:names:tc:SAML:2.0:metadata", "Extensions", "md"); if (params.getAssuranceLevel() != null) { generateLoA(eidasExtensions); } if (!StringUtils.isEmpty(params.getSpType())) { final SPType spTypeObj = (SPType) BuilderFactoryUtil.buildXmlObject(SPType.DEF_ELEMENT_NAME); if (spTypeObj != null) { spTypeObj.setSPType(params.getSpType()); eidasExtensions.getUnknownXMLObjects().add(spTypeObj); } else { LOGGER.info("BUSINESS EXCEPTION error adding SPType extension"); } } generateDigest(eidasExtensions); if (!StringUtils.isEmpty(params.getSigningMethods())) { Set signMethods = EIDASUtil.parseSemicolonSeparatedList(params.getDigestMethods()); for (String signMethod : signMethods) { final SigningMethod sm = (SigningMethod) BuilderFactoryUtil.buildXmlObject(SigningMethod.DEF_ELEMENT_NAME); if (sm != null) { sm.setAlgorithm(signMethod); eidasExtensions.getUnknownXMLObjects().add(sm); } else { LOGGER.info("BUSINESS EXCEPTION error adding SigningMethod extension"); } } } return eidasExtensions; } private void generateLoA(Extensions eidasExtensions) throws EIDASSAMLEngineException { EntityAttributes loa = (EntityAttributes) BuilderFactoryUtil.buildXmlObject(EntityAttributes.DEFAULT_ELEMENT_NAME); Attribute loaAttrib = (Attribute) BuilderFactoryUtil.buildXmlObject(Attribute.DEFAULT_ELEMENT_NAME); loaAttrib.setName(EidasConstants.LEVEL_OF_ASSURANCE_NAME); loaAttrib.setNameFormat(Attribute.URI_REFERENCE); XSStringBuilder stringBuilder = (XSStringBuilder) Configuration.getBuilderFactory().getBuilder(XSString.TYPE_NAME); XSString stringValue = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME); stringValue.setValue(params.getAssuranceLevel()); loaAttrib.getAttributeValues().add(stringValue); loa.getAttributes().add(loaAttrib); eidasExtensions.getUnknownXMLObjects().add(loa); } private static final Set DEFAULT_BINDING = new HashSet() {{ this.add(SAMLConstants.SAML2_POST_BINDING_URI); }}; private void addAssertionConsumerService() throws EIDASSAMLEngineException { int index = 0; Set bindings = params.getProtocolBinding().isEmpty() ? DEFAULT_BINDING : params.getProtocolBinding(); for (String binding : bindings) { AssertionConsumerService asc = (AssertionConsumerService) BuilderFactoryUtil.buildXmlObject( AssertionConsumerService.DEFAULT_ELEMENT_NAME); asc.setLocation(params.getAssertionConsumerUrl()); asc.setBinding(checkBinding(binding)); asc.setIndex(index); if (index == 0) { asc.setIsDefault(true); } index++; spSSODescriptor.getAssertionConsumerServices().add(asc); } } private String checkBinding(String binding) { if (binding != null && (binding.equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI) || binding.equals( SAMLConstants.SAML2_POST_BINDING_URI))) { return binding; } return SAMLConstants.SAML2_POST_BINDING_URI; } private DateTime getExpireDate() { DateTime expiryDate = DateTime.now(); expiryDate = expiryDate.withFieldAdded(DurationFieldType.seconds(), (int) (getConfigParams().getValidityDuration())); return expiryDate; } private void generateSupportedAttributes(IDPSSODescriptor idpssoDescriptor, ImmutableSortedSet> attributeDefinitions) throws EIDASSAMLEngineException { List attributes = idpssoDescriptor.getAttributes(); for (AttributeDefinition attributeDefinition : attributeDefinitions) { Attribute a = (Attribute) BuilderFactoryUtil.buildXmlObject(Attribute.DEFAULT_ELEMENT_NAME); a.setName(attributeDefinition.getNameUri().toASCIIString()); a.setFriendlyName(attributeDefinition.getFriendlyName()); a.setNameFormat(Attribute.URI_REFERENCE); attributes.add(a); } } public MetadataConfigParams getConfigParams() { return params; } public void setConfigParams(MetadataConfigParams params) { this.params = params; } }