aboutsummaryrefslogtreecommitdiff
path: root/id/server/modules/moa-id-module-eIDAS
diff options
context:
space:
mode:
Diffstat (limited to 'id/server/modules/moa-id-module-eIDAS')
-rw-r--r--id/server/modules/moa-id-module-eIDAS/pom.xml16
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java64
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAExtendedSWSigner.java479
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/ModifiedEncryptionSW.java8
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAEidasProtocolProcesser.java13
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAProtocolEngine.java68
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/GenerateAuthnRequestTask.java61
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java14
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAProtocolEngineFactory.java17
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAWhiteListConfigurator.java12
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAeIDASMetadataGenerator.java58
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java35
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/eIDASAttributeBuilder.java174
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/eIDASAttributeProcessingUtils.java75
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASData.java4
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java61
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EidasMetaDataRequest.java16
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/IeIDASAttribute.java33
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrDateOfBirth.java37
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrFamilyName.java61
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrGivenName.java61
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrLegalName.java37
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrLegalPersonIdentifier.java37
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrNaturalPersonalIdentifier.java116
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/eIDASAuthenticationRequest.java138
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/validator/eIDASResponseValidator.java130
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeBuilder6
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.IeIDASAttribute6
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/resources/resources/templates/eidas_postbinding_template.vm2
29 files changed, 1574 insertions, 265 deletions
diff --git a/id/server/modules/moa-id-module-eIDAS/pom.xml b/id/server/modules/moa-id-module-eIDAS/pom.xml
index 174ce40cb..55d02e82a 100644
--- a/id/server/modules/moa-id-module-eIDAS/pom.xml
+++ b/id/server/modules/moa-id-module-eIDAS/pom.xml
@@ -12,11 +12,11 @@
<properties>
<repositoryPath>${basedir}/../../../../repository</repositoryPath>
- <eidas-commons.version>1.1.0</eidas-commons.version>
- <eidas-light-commons.version>1.1.0</eidas-light-commons.version>
- <eidas-saml-engine.version>1.1.0</eidas-saml-engine.version>
- <eidas-encryption.version>1.1.0</eidas-encryption.version>
- <eidas-configmodule.version>1.1.0</eidas-configmodule.version>
+ <eidas-commons.version>1.2.0</eidas-commons.version>
+ <eidas-light-commons.version>1.2.0</eidas-light-commons.version>
+ <eidas-saml-engine.version>1.2.0</eidas-saml-engine.version>
+ <eidas-encryption.version>1.2.0</eidas-encryption.version>
+ <eidas-configmodule.version>1.2.0</eidas-configmodule.version>
</properties>
@@ -166,6 +166,12 @@
<!-- <scope>provided</scope> -->
</dependency>
+ <dependency>
+ <groupId>com.ibm.icu</groupId>
+ <artifactId>icu4j</artifactId>
+ <version>58.2</version>
+ </dependency>
+
</dependencies>
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java
index 02c9a8f5d..36323f3a5 100644
--- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java
@@ -22,12 +22,9 @@
*/
package at.gv.egovernment.moa.id.auth.modules.eidas;
+import org.apache.xml.security.signature.XMLSignature;
import org.opensaml.xml.encryption.EncryptionConstants;
import org.opensaml.xml.signature.SignatureConstants;
-//import eu.eidas.auth.engine.core.validator.eidas.EIDASAttributes;
-
-import eu.eidas.auth.commons.attribute.AttributeRegistries;
-import eu.eidas.auth.commons.attribute.AttributeRegistry;
/**
* @author tlenz
@@ -45,7 +42,8 @@ public class Constants {
public static final String eIDAS_SAML_ENGINE_NAME_ID_CLASS = "class";
//default implementations for eIDAS SAML-engine functionality
- public static final String SAML_SIGNING_IMPLENTATION = "at.gv.egovernment.moa.id.auth.modules.eidas.config.MOASWSigner";
+ //public static final String SAML_SIGNING_IMPLENTATION = "at.gv.egovernment.moa.id.auth.modules.eidas.config.MOASWSigner";
+ public static final String SAML_SIGNING_IMPLENTATION = "at.gv.egovernment.moa.id.auth.modules.eidas.config.MOAExtendedSWSigner";
public static final String SAML_ENCRYPTION_IMPLENTATION = "at.gv.egovernment.moa.id.auth.modules.eidas.config.ModifiedEncryptionSW";
//configuration property keys
@@ -59,12 +57,16 @@ public class Constants {
public static final String CONIG_PROPS_EIDAS_SAMLENGINE_SIGN_CONFIGFILE = CONIG_PROPS_EIDAS_SAMLENGINE_PREFIX + "."
+ CONIG_PROPS_EIDAS_SAMLENGINE_SIGN + ".config.file";
public static final String CONIG_PROPS_EIDAS_SAMLENGINE_ENC_CONFIGFILE = CONIG_PROPS_EIDAS_SAMLENGINE_PREFIX + "."
- + CONIG_PROPS_EIDAS_SAMLENGINE_ENCRYPT + ".config.file";
+ + CONIG_PROPS_EIDAS_SAMLENGINE_ENCRYPT + ".config.file";
+ public static final String CONIG_PROPS_EIDAS_SAMLENGINE_ATTIONAL_ATTRIBUTE_DEFINITIONS =
+ CONIG_PROPS_EIDAS_SAMLENGINE_PREFIX + ".attributes.addition.config";
public static final String CONIG_PROPS_EIDAS_METADATA_VALIDATION_TRUSTSTORE = CONIG_PROPS_EIDAS_PREFIX + ".metadata.validation.truststore";
+
public static final String CONIG_PROPS_EIDAS_NODE_COUNTRYCODE = CONIG_PROPS_EIDAS_NODE + ".countrycode";
public static final String CONIG_PROPS_EIDAS_NODE_COUNTRY = CONIG_PROPS_EIDAS_NODE + ".country";
- public static final String CONIG_PROPS_EIDAS_NODE_LoA = CONIG_PROPS_EIDAS_NODE + ".LoA";
+ public static final String CONIG_PROPS_EIDAS_NODE_LoA = CONIG_PROPS_EIDAS_NODE + ".LoA";
+
//timeouts and clock skews
@@ -86,8 +88,6 @@ public class Constants {
//http endpoint descriptions
public static final String eIDAS_HTTP_ENDPOINT_SP_POST = "/eidas/sp/post";
public static final String eIDAS_HTTP_ENDPOINT_SP_REDIRECT = "/eidas/sp/redirect";
- //public static final String eIDAS_HTTP_ENDPOINT_IDP_POST = "/eidas/idp/post";
- //public static final String eIDAS_HTTP_ENDPOINT_IDP_REDIRECT = "/eidas/idp/redirect";
public static final String eIDAS_HTTP_ENDPOINT_IDP_COLLEAGUEREQUEST = "/eidas/ColleagueRequest";
public static final String eIDAS_HTTP_ENDPOINT_METADATA = "/eidas/metadata";
@@ -96,53 +96,23 @@ public class Constants {
public static final int eIDAS_REVERSIONSLOG_METADATA = 3400;
public static final int eIDAS_REVERSIONSLOG_IDP_AUTHREQUEST = 3401;
public static final int eIDAS_REVERSIONSLOG_IDP_AUTHRESPONSE = 3402;
- public static final int eIDAS_REVERSIONSLOG_SP_AUTHREQUEST= 3403;
- public static final int eIDAS_REVERSIONSLOG_SP_AUTHRESPONSE= 3404;
- //metadata constants
-// public final static Map<String, EidasAttributesTypes> METADATA_POSSIBLE_ATTRIBUTES = Collections.unmodifiableMap(
-// new HashMap<String, EidasAttributesTypes>(){
-// private static final long serialVersionUID = 1L;
-// {
-// put(EIDASAttributes.ATTRIBUTE_GIVENNAME, EidasAttributesTypes.NATURAL_PERSON_MANDATORY);
-// put(EIDASAttributes.ATTRIBUTE_FIRSTNAME, EidasAttributesTypes.NATURAL_PERSON_MANDATORY);
-// put(EIDASAttributes.ATTRIBUTE_DATEOFBIRTH, EidasAttributesTypes.NATURAL_PERSON_MANDATORY);
-// put(EIDASAttributes.ATTRIBUTE_PERSONIDENTIFIER, EidasAttributesTypes.NATURAL_PERSON_MANDATORY);
-//
-// //TODO: add additional attributes for eIDAS with mandates
-// //put(EIDASAttributes.ATTRIBUTE_LEGALIDENTIFIER, EidasAttributesTypes.LEGAL_PERSON_MANDATORY);
-// //put(EIDASAttributes.ATTRIBUTE_LEGALNAME, EidasAttributesTypes.LEGAL_PERSON_MANDATORY);
-// }
-// }
-// );
-
- public static final AttributeRegistry NAT_ATTR =
- AttributeRegistries.of( eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.PERSON_IDENTIFIER,
- eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.CURRENT_FAMILY_NAME,
- eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.CURRENT_GIVEN_NAME,
- eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.DATE_OF_BIRTH
- );
-
- public static final AttributeRegistry LEGAL_ATTR =
- AttributeRegistries.of( eu.eidas.auth.engine.core.eidas.spec.LegalPersonSpec.Definitions.LEGAL_PERSON_IDENTIFIER,
- eu.eidas.auth.engine.core.eidas.spec.LegalPersonSpec.Definitions.LEGAL_NAME
- );
-
- public static final AttributeRegistry MOA_IDP_ATTR_REGISTRY =
- AttributeRegistries.copyOf(NAT_ATTR, LEGAL_ATTR);
-
public static final String METADATA_ALLOWED_ALG_DIGIST =
- SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256 + ";" +
- SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA512 ;
+ SignatureConstants.ALGO_ID_DIGEST_SHA256 + ";" +
+ SignatureConstants.ALGO_ID_DIGEST_SHA512 ;
public static final String METADATA_ALLOWED_ALG_SIGN =
SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256 + ";" +
- SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA512;
+ SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA512 + ";" +
+ XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256_MGF1 + ";" +
+ XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA512_MGF1;
public static final String METADATA_ALLOWED_ALG_ENCRYPT =
EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128_GCM + ";" +
EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES192_GCM + ";" +
- EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES256_GCM;
+ EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES256_GCM + ";" +
+ EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128 + ";" +
+ EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES256;
}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAExtendedSWSigner.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAExtendedSWSigner.java
new file mode 100644
index 000000000..c872bcfb6
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAExtendedSWSigner.java
@@ -0,0 +1,479 @@
+/*
+ * 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.config;
+
+import java.security.KeyStore;
+import java.security.cert.X509Certificate;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.xml.security.signature.XMLSignature;
+import org.opensaml.Configuration;
+import org.opensaml.common.impl.SAMLObjectContentReference;
+import org.opensaml.security.SAMLSignatureProfileValidator;
+import org.opensaml.xml.io.MarshallingException;
+import org.opensaml.xml.security.SecurityConfiguration;
+import org.opensaml.xml.security.SecurityException;
+import org.opensaml.xml.security.SecurityHelper;
+import org.opensaml.xml.security.credential.Credential;
+import org.opensaml.xml.security.keyinfo.KeyInfoGenerator;
+import org.opensaml.xml.security.keyinfo.KeyInfoGeneratorFactory;
+import org.opensaml.xml.security.keyinfo.KeyInfoGeneratorManager;
+import org.opensaml.xml.security.keyinfo.NamedKeyInfoGeneratorManager;
+import org.opensaml.xml.security.x509.X509Credential;
+import org.opensaml.xml.signature.KeyInfo;
+import org.opensaml.xml.signature.SignableXMLObject;
+import org.opensaml.xml.signature.Signature;
+import org.opensaml.xml.signature.SignatureException;
+import org.opensaml.xml.signature.SignatureValidator;
+import org.opensaml.xml.signature.Signer;
+import org.opensaml.xml.validation.ValidationException;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.sun.istack.Nullable;
+
+import at.gv.egovernment.moa.id.auth.modules.eidas.Constants;
+import at.gv.egovernment.moa.id.auth.modules.eidas.utils.MOAWhiteListConfigurator;
+import at.gv.egovernment.moa.logging.Logger;
+import eu.eidas.auth.commons.EidasErrorKey;
+import eu.eidas.auth.engine.configuration.SamlEngineConfigurationException;
+import eu.eidas.auth.engine.configuration.dom.ConfigurationAdapter;
+import eu.eidas.auth.engine.configuration.dom.ConfigurationKey;
+import eu.eidas.auth.engine.configuration.dom.KeyStoreSignatureConfigurator;
+import eu.eidas.auth.engine.configuration.dom.SignatureConfiguration;
+import eu.eidas.auth.engine.core.ProtocolSignerI;
+import eu.eidas.auth.engine.core.impl.BouncyCastleBootstrap;
+import eu.eidas.auth.engine.core.impl.CertificateValidator;
+import eu.eidas.auth.engine.metadata.MetadataSignerI;
+import eu.eidas.auth.engine.xml.opensaml.CertificateUtil;
+import eu.eidas.engine.exceptions.EIDASSAMLEngineException;
+import eu.eidas.samlengineconfig.CertificateConfigurationManager;
+import eu.eidas.util.Preconditions;
+
+/**
+ * @author tlenz
+ *
+ */
+public class MOAExtendedSWSigner implements ProtocolSignerI, MetadataSignerI {
+
+ private static final String DEFAULT_SIGNATURE_ALGORITHM = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512";
+ private static final ImmutableSet<String> ALLOWED_ALGORITHMS_FOR_SIGNING;
+ private static final ImmutableSet<String> ALLOWED_ALGORITHMS_FOR_VERIFYING;
+ private static final ImmutableSet<String> DEFAULT_ALGORITHM_WHITE_LIST;
+ private static final String DEFAULT_DIGEST_ALGORITHM = "http://www.w3.org/2001/04/xmlenc#sha512";
+ private static final ImmutableMap<Object, Object> SIGNATURE_TO_DIGEST_ALGORITHM_MAP;
+ private final boolean checkedValidityPeriod;
+ private final boolean disallowedSelfSignedCertificate;
+ private final boolean responseSignAssertions;
+ private final ImmutableSet<String> signatureAlgorithmWhiteList;
+ private final X509Credential privateSigningCredential;
+ private final X509Credential publicSigningCredential;
+ private final X509Credential privateMetadataSigningCredential;
+ private final X509Credential publicMetadataSigningCredential;
+ private final ImmutableList<X509Credential> trustedCredentials;
+ private final String signatureAlgorithm;
+
+ public MOAExtendedSWSigner(Map<String, String> properties) throws SamlEngineConfigurationException {
+ this(new KeyStoreSignatureConfigurator().getSignatureConfiguration(properties));
+
+ }
+
+ /**
+ * @param configManager
+ * @throws SamlEngineConfigurationException
+ */
+ public MOAExtendedSWSigner(CertificateConfigurationManager configManager) throws SamlEngineConfigurationException {
+ this(new KeyStoreSignatureConfigurator().getSignatureConfiguration(
+ ConfigurationAdapter.adapt(configManager).getInstances().get(Constants.eIDAS_SAML_ENGINE_NAME).getConfigurationEntries().get(ConfigurationKey.SIGNATURE_CONFIGURATION.getKey()).getParameters()));
+
+ }
+
+ protected MOAExtendedSWSigner(SignatureConfiguration signatureConfiguration)
+ throws SamlEngineConfigurationException {
+ this(signatureConfiguration.isCheckedValidityPeriod(),
+ signatureConfiguration.isDisallowedSelfSignedCertificate(),
+ signatureConfiguration.isResponseSignAssertions(),
+ signatureConfiguration.getSignatureKeyAndCertificate(), signatureConfiguration.getTrustedCertificates(),
+ signatureConfiguration.getSignatureAlgorithm(), signatureConfiguration.getSignatureAlgorithmWhiteList(),
+ signatureConfiguration.getMetadataSigningKeyAndCertificate());
+ }
+
+ protected MOAExtendedSWSigner(boolean checkedValidityPeriod, boolean disallowedSelfSignedCertificate,
+ boolean responseSignAssertions, KeyStore.PrivateKeyEntry signatureKeyAndCertificate,
+ ImmutableSet<X509Certificate> trustedCertificates, String signatureAlgorithmVal,
+ String signatureAlgorithmWhiteListStr,
+ KeyStore.PrivateKeyEntry metadataSigningKeyAndCertificate)
+ throws SamlEngineConfigurationException {
+ Preconditions.checkNotNull(signatureKeyAndCertificate, "signatureKeyAndCertificate");
+ Preconditions.checkNotNull(trustedCertificates, "trustedCertificates");
+ String signatureAlg = signatureAlgorithmVal;
+
+ if (StringUtils.isBlank(signatureAlg))
+ signatureAlg = DEFAULT_SIGNATURE_ALGORITHM;
+
+ else {
+ signatureAlg = validateSigningAlgorithm(signatureAlg);
+
+ }
+
+ ImmutableSet signatureAlgorithmWhiteSet = MOAWhiteListConfigurator.getAllowedAlgorithms(
+ DEFAULT_ALGORITHM_WHITE_LIST, ALLOWED_ALGORITHMS_FOR_VERIFYING, signatureAlgorithmWhiteListStr);
+
+ this.checkedValidityPeriod = checkedValidityPeriod;
+ this.disallowedSelfSignedCertificate = disallowedSelfSignedCertificate;
+ this.responseSignAssertions = responseSignAssertions;
+ this.trustedCredentials = CertificateUtil.getListOfCredential(trustedCertificates);
+ this.signatureAlgorithmWhiteList = signatureAlgorithmWhiteSet;
+ this.signatureAlgorithm = signatureAlg;
+ this.privateSigningCredential = CertificateUtil.createCredential(signatureKeyAndCertificate);
+ this.publicSigningCredential = CertificateUtil
+ .toCredential((X509Certificate) signatureKeyAndCertificate.getCertificate());
+
+ if (null != metadataSigningKeyAndCertificate) {
+ this.privateMetadataSigningCredential = CertificateUtil.createCredential(metadataSigningKeyAndCertificate);
+ this.publicMetadataSigningCredential = CertificateUtil
+ .toCredential((X509Certificate) metadataSigningKeyAndCertificate.getCertificate());
+ } else {
+ this.privateMetadataSigningCredential = null;
+ this.publicMetadataSigningCredential = null;
+ }
+ }
+
+ private static X509Certificate getSignatureCertificate(Signature signature) throws EIDASSAMLEngineException {
+ KeyInfo keyInfo = signature.getKeyInfo();
+ return CertificateUtil.toCertificate(keyInfo);
+ }
+
+ public static String validateDigestAlgorithm(String signatureAlgorithmName)
+ throws SamlEngineConfigurationException {
+
+ if (StringUtils.isBlank(signatureAlgorithmName)) {
+ return DEFAULT_DIGEST_ALGORITHM;
+
+ }
+
+ //BUGFIX: toLowerCase from original eIDAS SAML-engine produce problems with MGF1 signature algorithms
+ String canonicalAlgorithm = signatureAlgorithmName.trim();
+ String digestAlgorithm = (String) SIGNATURE_TO_DIGEST_ALGORITHM_MAP.get(canonicalAlgorithm);
+ if (null != digestAlgorithm) {
+ return digestAlgorithm;
+
+ }
+ String msg = "Signing algorithm \"" + signatureAlgorithmName
+ + "\" does not contain an allowed digest algorithm";
+
+ Logger.error(msg);
+ throw new SamlEngineConfigurationException(msg);
+
+ }
+
+ public static String validateSigningAlgorithm(@Nullable String signatureAlgorithmName)
+ throws SamlEngineConfigurationException {
+ if ((signatureAlgorithmName == null) || (StringUtils.isBlank(signatureAlgorithmName))) {
+ return DEFAULT_SIGNATURE_ALGORITHM;
+
+ }
+
+ //BUGFIX:: toLowerCase from original eIDAS SAML-engine produce problems with MGF1 signature algorithms
+ String canonicalAlgorithm = signatureAlgorithmName.trim();
+ if (ALLOWED_ALGORITHMS_FOR_SIGNING.contains(canonicalAlgorithm)) {
+ return canonicalAlgorithm;
+
+ }
+ String msg = "Signing algorithm \"" + signatureAlgorithmName + "\" is not allowed";
+ Logger.error(msg);
+ throw new SamlEngineConfigurationException(msg);
+
+ }
+
+ protected void checkCertificateIssuer(X509Certificate certificate) throws EIDASSAMLEngineException {
+ CertificateValidator.checkCertificateIssuer(this.disallowedSelfSignedCertificate, certificate);
+
+ }
+
+ protected void checkCertificateValidityPeriod(X509Certificate certificate) throws EIDASSAMLEngineException {
+ CertificateValidator.checkCertificateValidityPeriod(this.checkedValidityPeriod, certificate);
+
+ }
+
+ protected Signature createSignature(X509Credential credential) throws EIDASSAMLEngineException {
+ checkCertificateValidityPeriod(credential.getEntityCertificate());
+ checkCertificateIssuer(credential.getEntityCertificate());
+ Signature signature;
+ try {
+ Logger.trace("Creating an OpenSAML signature object");
+
+ signature = (Signature) Configuration.getBuilderFactory().getBuilder(Signature.DEFAULT_ELEMENT_NAME)
+ .buildObject(Signature.DEFAULT_ELEMENT_NAME);
+
+ signature.setSigningCredential(credential);
+
+ signature.setSignatureAlgorithm(getSignatureAlgorithm());
+
+ SecurityConfiguration secConfiguration = Configuration.getGlobalSecurityConfiguration();
+ NamedKeyInfoGeneratorManager keyInfoManager = secConfiguration.getKeyInfoGeneratorManager();
+ KeyInfoGeneratorManager keyInfoGenManager = keyInfoManager.getDefaultManager();
+ KeyInfoGeneratorFactory keyInfoGenFac = keyInfoGenManager.getFactory(credential);
+ KeyInfoGenerator keyInfoGenerator = keyInfoGenFac.newInstance();
+
+ KeyInfo keyInfo = keyInfoGenerator.generate(credential);
+
+ signature.setKeyInfo(keyInfo);
+ signature.setCanonicalizationAlgorithm("http://www.w3.org/2001/10/xml-exc-c14n#");
+ } catch (SecurityException e) {
+ Logger.error("ERROR : Security exception: " + e, e);
+ throw new EIDASSAMLEngineException(e);
+
+ }
+ return signature;
+ }
+
+ public X509Credential getPublicMetadataSigningCredential() {
+ return this.publicMetadataSigningCredential;
+
+ }
+
+ public X509Credential getPublicSigningCredential() {
+ return this.publicSigningCredential;
+
+ }
+
+ protected String getSignatureAlgorithm() {
+ return this.signatureAlgorithm;
+
+ }
+
+ protected ImmutableSet<String> getSignatureAlgorithmWhiteList() {
+ return this.signatureAlgorithmWhiteList;
+
+ }
+
+ private X509Credential getTrustedCertificate(Signature signature,
+ List<? extends Credential> trustedCredentialList) throws EIDASSAMLEngineException {
+ X509Certificate cert = getSignatureCertificate(signature);
+
+ X509Credential entityX509Cred = CertificateUtil.toCredential(cert);
+
+ CertificateUtil.checkTrust(entityX509Cred, trustedCredentialList);
+ checkCertificateValidityPeriod(cert);
+ checkCertificateIssuer(cert);
+ return entityX509Cred;
+
+ }
+
+ protected ImmutableList<X509Credential> getTrustedCredentials() {
+ return this.trustedCredentials;
+
+ }
+
+ private boolean isAlgorithmAllowedForVerifying(String signatureAlgorithm) {
+ return ((StringUtils.isNotBlank(signatureAlgorithm))
+ && (getSignatureAlgorithmWhiteList().contains(signatureAlgorithm.trim())));
+
+ }
+
+ public <T extends SignableXMLObject> T sign(T signableObject) throws EIDASSAMLEngineException {
+ return sign(signableObject, this.privateSigningCredential);
+
+ }
+
+ protected <T extends SignableXMLObject> T sign(T signableObject, X509Credential signingCredential)
+ throws EIDASSAMLEngineException {
+ Logger.trace("Start Sign process.");
+ try {
+ Signature signature = createSignature(signingCredential);
+ signableObject.setSignature(signature);
+
+ String digestAlgorithm = validateDigestAlgorithm(getSignatureAlgorithm());
+ List contentReferences = signature.getContentReferences();
+ if (CollectionUtils.isNotEmpty(contentReferences))
+ ((SAMLObjectContentReference) contentReferences.get(0)).setDigestAlgorithm(digestAlgorithm);
+
+ else {
+ Logger.error("Unable to set DigestMethodAlgorithm - algorithm " + digestAlgorithm + " not set");
+
+ }
+
+ Logger.trace("Marshall samlToken.");
+ Configuration.getMarshallerFactory().getMarshaller(signableObject).marshall(signableObject);
+
+ Logger.trace("Sign samlToken.");
+ Signer.signObject(signature);
+
+ } catch (MarshallingException e) {
+ Logger.error("ERROR : MarshallingException: " + e, e);
+ throw new EIDASSAMLEngineException(e);
+
+ } catch (SignatureException e) {
+ Logger.error("ERROR : Signature exception: " + e, e);
+ throw new EIDASSAMLEngineException(e);
+
+ }
+
+ return signableObject;
+ }
+
+ public <T extends SignableXMLObject> T signMetadata(T signableObject) throws EIDASSAMLEngineException {
+ if (null == this.privateMetadataSigningCredential) {
+ throw new SamlEngineConfigurationException("No metadataSigningCredential configured");
+
+ }
+ return sign(signableObject, this.privateMetadataSigningCredential);
+ }
+
+ public <T extends SignableXMLObject> T validateMetadataSignature(T signedMetadata)
+ throws EIDASSAMLEngineException {
+ return validateSignature(signedMetadata, null);
+
+ }
+
+ private SAMLSignatureProfileValidator validateSamlSignatureStructure(SignableXMLObject signableObject)
+ throws EIDASSAMLEngineException {
+ SAMLSignatureProfileValidator sigProfValidator = new SAMLSignatureProfileValidator();
+ try {
+ sigProfValidator.validate(signableObject.getSignature());
+
+ } catch (ValidationException e) {
+ Logger.error("ERROR : ValidationException: signature isn't conform to SAML Signature profile: " + e, e);
+ throw new EIDASSAMLEngineException(e);
+
+ }
+ return sigProfValidator;
+ }
+
+ public <T extends SignableXMLObject> T validateSignature(T signedObject,
+ Collection<X509Certificate> trustedCertificateCollection) throws EIDASSAMLEngineException {
+ List trustedCreds;
+ if (CollectionUtils.isEmpty(trustedCertificateCollection))
+ trustedCreds = getTrustedCredentials();
+
+ else {
+ trustedCreds = CertificateUtil.getListOfCredential(trustedCertificateCollection);
+
+ }
+ return (T) validateSignatureWithCredentials(signedObject, trustedCreds);
+ }
+
+ private <T extends SignableXMLObject> T validateSignatureWithCredentials(T signedObject,
+ List<? extends Credential> trustedCredentialList) throws EIDASSAMLEngineException {
+ Logger.debug("Start signature validation.");
+
+ validateSamlSignatureStructure(signedObject);
+
+ verifyCryptographicSignature(signedObject.getSignature(), trustedCredentialList);
+
+ return signedObject;
+
+ }
+
+ private void verifyCryptographicSignature(Signature signature,
+ List<? extends Credential> trustedCredentialList) throws EIDASSAMLEngineException {
+ String signatureAlgorithmVal = signature.getSignatureAlgorithm();
+ Logger.trace("Key algorithm " + SecurityHelper.getKeyAlgorithmFromURI(signatureAlgorithmVal));
+
+ if (!(isAlgorithmAllowedForVerifying(signatureAlgorithmVal))) {
+ Logger.error("ERROR : the algorithm " + signatureAlgorithmVal + " used by the signature is not allowed");
+ throw new EIDASSAMLEngineException(EidasErrorKey.INVALID_SIGNATURE_ALGORITHM.errorCode());
+
+ }
+
+ X509Credential entityX509Cred = getTrustedCertificate(signature, trustedCredentialList);
+ SignatureValidator sigValidator = new SignatureValidator(entityX509Cred);
+
+ try {
+ sigValidator.validate(signature);
+
+ } catch (ValidationException e) {
+ Logger.error("ERROR : Signature Validation Exception: " + e, e);
+ throw new EIDASSAMLEngineException(e);
+
+ }
+ }
+
+ public boolean isResponseSignAssertions() {
+ return this.responseSignAssertions;
+ }
+
+ static {
+ BouncyCastleBootstrap.bootstrap();
+
+ ALLOWED_ALGORITHMS_FOR_SIGNING = ImmutableSet.of("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256",
+ "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384",
+ "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512",
+ "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256",
+ "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384",
+ "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512",
+
+ //Set other algorithms which are not supported by openSAML in default
+ XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256_MGF1,
+ XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA512_MGF1);
+
+ ALLOWED_ALGORITHMS_FOR_VERIFYING = ImmutableSet.of("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256",
+ "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384",
+ "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512",
+ "http://www.w3.org/2001/04/xmldsig-more#rsa-ripemd160",
+ "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256",
+ "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384",
+ "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512",
+
+ //Set other algorithms which are not supported by openSAML in default
+ XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1_MGF1,
+ XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA224_MGF1,
+ XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256_MGF1,
+ XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA384_MGF1,
+ XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA512_MGF1);
+
+ DEFAULT_ALGORITHM_WHITE_LIST = ImmutableSet.of("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256",
+ "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384",
+ "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512",
+ "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256",
+ "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384",
+ "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512",
+
+ //Set other algorithms which are not supported by openSAML in default
+ XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256_MGF1);
+
+ SIGNATURE_TO_DIGEST_ALGORITHM_MAP = ImmutableMap.builder()
+ .put("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", "http://www.w3.org/2001/04/xmlenc#sha256")
+ .put("http://www.w3.org/2001/04/xmldsig-more#rsa-sha384",
+ "http://www.w3.org/2001/04/xmldsig-more#sha384")
+ .put("http://www.w3.org/2001/04/xmldsig-more#rsa-sha512", "http://www.w3.org/2001/04/xmlenc#sha512")
+ .put("http://www.w3.org/2001/04/xmldsig-more#rsa-ripemd160",
+ "http://www.w3.org/2001/04/xmlenc#ripemd160")
+ .put("http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256", "http://www.w3.org/2001/04/xmlenc#sha256")
+ .put("http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384",
+ "http://www.w3.org/2001/04/xmldsig-more#sha384")
+ .put("http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512", "http://www.w3.org/2001/04/xmlenc#sha512")
+
+ //Set other algorithms which are not supported by openSAML in default
+ .put(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256_MGF1, "http://www.w3.org/2001/04/xmlenc#sha256")
+ .put(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA512_MGF1, "http://www.w3.org/2001/04/xmlenc#sha512")
+
+ .build();
+ }
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/ModifiedEncryptionSW.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/ModifiedEncryptionSW.java
index 9ad5f0db3..de4f3fc9c 100644
--- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/ModifiedEncryptionSW.java
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/ModifiedEncryptionSW.java
@@ -90,17 +90,21 @@ public class ModifiedEncryptionSW extends KeyStoreSamlEngineEncryption {
*/
@Override
public boolean isEncryptionEnabled(String countryCode) {
- // - encrypt if so configured
+ //encryption is enabled by default in MOA-ID configuration object
try {
AuthConfiguration moaconfig = AuthConfigurationProviderFactory.getInstance();
Boolean useEncryption = moaconfig.getStorkConfig().getCPEPS(countryCode).isXMLSignatureSupported();
- Logger.info(useEncryption ? "using encryption" : "do not use encrpytion");
+ String logResult = useEncryption ? " using encryption" : " do not use encrpytion";
+ Logger.debug("eIDAS respone for country " + countryCode + logResult);
return useEncryption;
+
} catch(NullPointerException | ConfigurationException e) {
Logger.warn("failed to gather information about encryption for countryCode " + countryCode + " - thus, enabling encryption");
if(Logger.isDebugEnabled())
e.printStackTrace();
return true;
+
}
+
}
}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAEidasProtocolProcesser.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAEidasProtocolProcesser.java
index c24c5efca..8abf29703 100644
--- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAEidasProtocolProcesser.java
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAEidasProtocolProcesser.java
@@ -22,7 +22,9 @@
*/
package at.gv.egovernment.moa.id.auth.modules.eidas.engine;
+import eu.eidas.auth.commons.attribute.AttributeRegistry;
import eu.eidas.auth.engine.core.eidas.EidasProtocolProcessor;
+import eu.eidas.auth.engine.core.eidas.spec.EidasSpec;
import eu.eidas.auth.engine.metadata.MetadataFetcherI;
import eu.eidas.auth.engine.metadata.MetadataSignerI;
@@ -38,11 +40,14 @@ public class MOAEidasProtocolProcesser extends EidasProtocolProcessor {
private final MetadataSignerI metadataSigner;
/**
- * @param metadataFetcher
- * @param metadataSigner
+ * Build a MOA specific eIDAS-engine protocol processor
+ *
+ * @param metadataFetcher eIDAS-engine Metadata fetcher implementation
+ * @param metadataSigner eIDAS-engine Signer implementation
+ * @param addAttrDefinitions additinal eIDAS attributes
*/
- public MOAEidasProtocolProcesser(MetadataFetcherI metadataFetcher, MetadataSignerI metadataSigner) {
- super(metadataFetcher, metadataSigner);
+ public MOAEidasProtocolProcesser(MetadataFetcherI metadataFetcher, MetadataSignerI metadataSigner, AttributeRegistry addAttrDefinitions) {
+ super(EidasSpec.REGISTRY, addAttrDefinitions, metadataFetcher, metadataSigner);
this.metadataFetcher = metadataFetcher;
this.metadataSigner = metadataSigner;
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAProtocolEngine.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAProtocolEngine.java
new file mode 100644
index 000000000..d8fcd1694
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAProtocolEngine.java
@@ -0,0 +1,68 @@
+package at.gv.egovernment.moa.id.auth.modules.eidas.engine;
+
+import java.security.cert.X509Certificate;
+
+import org.apache.commons.lang3.StringUtils;
+import org.opensaml.saml2.core.Response;
+
+import at.gv.egovernment.moa.logging.Logger;
+import eu.eidas.auth.commons.EidasErrorKey;
+import eu.eidas.auth.commons.protocol.IAuthenticationRequest;
+import eu.eidas.auth.engine.ProtocolEngine;
+import eu.eidas.auth.engine.configuration.ProtocolConfigurationAccessor;
+import eu.eidas.auth.engine.xml.opensaml.SAMLEngineUtils;
+import eu.eidas.engine.exceptions.EIDASSAMLEngineException;
+
+public class MOAProtocolEngine extends ProtocolEngine {
+
+ public MOAProtocolEngine(ProtocolConfigurationAccessor configurationAccessor) {
+ super(configurationAccessor);
+
+ }
+
+// @Override
+// protected X509Certificate getEncryptionCertificate(String requestIssuer,
+// String destinationCountryCode) throws EIDASSAMLEngineException {
+// if ((StringUtils.isNotBlank(destinationCountryCode)) && (null != getProtocolEncrypter())
+// && (getProtocolEncrypter().isEncryptionEnabled(destinationCountryCode))) {
+// X509Certificate encryptionCertificate = getProtocolProcessor().getEncryptionCertificate(requestIssuer);
+//
+// if (null == encryptionCertificate) {
+// return getProtocolEncrypter().getEncryptionCertificate(destinationCountryCode);
+//
+// }
+// return encryptionCertificate;
+// }
+// return null;
+// }
+//
+// @Override
+// protected Response signResponse(IAuthenticationRequest request, Response response)
+// throws EIDASSAMLEngineException {
+// Response responseToSign = response;
+//
+// if ((null != getProtocolEncrypter()) && (!(SAMLEngineUtils.isErrorSamlResponse(responseToSign)))) {
+// X509Certificate destinationCertificate = getEncryptionCertificate(request.getIssuer(),
+// request.getOriginCountryCode());
+//
+// if (null != destinationCertificate) {
+// responseToSign = getProtocolEncrypter().encryptSamlResponse(responseToSign, destinationCertificate);
+//
+// } else if (getProtocolEncrypter().isEncryptionEnabled(request.getOriginCountryCode())) {
+//// Logger.error(SAML_EXCHANGE,
+//// "BUSINESS EXCEPTION : encryption cannot be performed, no matching certificate for issuer="
+//// + request.getIssuer() + " and country=" + request.getOriginCountryCode());
+//
+// throw new EIDASSAMLEngineException(EidasErrorKey.SAML_ENGINE_INVALID_CERTIFICATE.errorCode(),
+// EidasErrorKey.SAML_ENGINE_INVALID_CERTIFICATE.errorMessage());
+// }
+//
+// } else if (!(SAMLEngineUtils.isErrorSamlResponse(responseToSign))) {
+// checkSendingUnencryptedResponsesAllowed();
+//
+// }
+//
+// Logger.debug("Signing SAML Response.");
+// return ((Response) getSigner().sign(responseToSign));
+// }
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/GenerateAuthnRequestTask.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/GenerateAuthnRequestTask.java
index a9c4d5d3a..7155040c6 100644
--- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/GenerateAuthnRequestTask.java
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/GenerateAuthnRequestTask.java
@@ -22,13 +22,10 @@
*/
package at.gv.egovernment.moa.id.auth.modules.eidas.tasks;
-import java.io.ByteArrayOutputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
-import java.util.zip.Deflater;
-import java.util.zip.DeflaterOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -42,7 +39,6 @@ import org.opensaml.common.xml.SAMLConstants;
import org.opensaml.saml2.metadata.EntityDescriptor;
import org.opensaml.saml2.metadata.SingleSignOnService;
import org.opensaml.saml2.metadata.provider.MetadataProviderException;
-import org.opensaml.xml.util.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -197,7 +193,17 @@ public class GenerateAuthnRequestTask extends AbstractAuthServletTask {
}
}
- //build requested attribute set
+ //request
+ if (reqAttrList.isEmpty()) {
+ Logger.info("No attributes requested by OA:" + pendingReq.getOnlineApplicationConfiguration().getPublicURLPrefix()
+ + " --> Request attr:" + Constants.eIDAS_ATTR_PERSONALIDENTIFIER + " by default");
+ AttributeDefinition<?> newAttribute = SAMLEngineUtils.getMapOfAllAvailableAttributes().get(Constants.eIDAS_ATTR_PERSONALIDENTIFIER);
+ Builder<?> attrBuilder = AttributeDefinition.builder(newAttribute).required(true);
+ reqAttrList.add(attrBuilder.build());
+
+ }
+
+ //build requested attribute set
ImmutableAttributeMap reqAttrMap = new ImmutableAttributeMap.Builder().putAll(reqAttrList).build();
//build eIDAS AuthnRequest
@@ -211,8 +217,13 @@ public class GenerateAuthnRequestTask extends AbstractAuthServletTask {
authnRequestBuilder.nameIdFormat(Constants.eIDAS_REQ_NAMEID_FORMAT);
- //set minimum required eIDAS LoA from OA config
- authnRequestBuilder.levelOfAssurance(LevelOfAssurance.fromString(oaConfig.getQaaLevel()));
+ //set minimum required eIDAS LoA from OA config
+ String LoA = oaConfig.getQaaLevel();
+ if (MiscUtil.isNotEmpty(LoA))
+ authnRequestBuilder.levelOfAssurance(LevelOfAssurance.fromString(oaConfig.getQaaLevel()));
+ else
+ authnRequestBuilder.levelOfAssurance(LevelOfAssurance.HIGH);
+
authnRequestBuilder.levelOfAssuranceComparison(LevelOfAssuranceComparison.MINIMUM);
//set correct SPType for this online application
@@ -234,7 +245,7 @@ public class GenerateAuthnRequestTask extends AbstractAuthServletTask {
IRequestMessage authnRequest = engine.generateRequestMessage(authnRequestBuilder.build(), issur);
-
+
//encode AuthnRequest
byte[] token = authnRequest.getMessageBytes();
String SAMLRequest = EidasStringUtil.encodeToBase64(token);
@@ -269,40 +280,6 @@ public class GenerateAuthnRequestTask extends AbstractAuthServletTask {
}
}
-
- /**
- * Encode the eIDAS request with Redirect binding
- *
- * @param pendingReq
- * @param authnReqEndpoint
- * @param token
- * @param authnRequest
- * @param response
- * @throws MOAIDException
- */
- private void buildRedirecttBindingRequest(IRequest pendingReq, SingleSignOnService authnReqEndpoint,
- byte[] token, IRequestMessage authnRequest, HttpServletResponse response)
- throws MOAIDException {
-
- //FIXME: implement correct deflat encoding accodring to SAML2 Redirect Binding specification
-
- try {
- ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
- Deflater deflater = new Deflater(Deflater.DEFLATED, true);
- DeflaterOutputStream deflaterStream = new DeflaterOutputStream(bytesOut, deflater);
- deflaterStream.write(token);
- deflaterStream.finish();
- String samlReqBase64 = Base64.encodeBytes(bytesOut.toByteArray(), Base64.DONT_BREAK_LINES);
-
-
-
- } catch (Exception e) {
- Logger.error("eIDAS Redirect-Binding request encoding error: " + e.getMessage());
- throw new MOAIDException("eIDAS.02", new Object[]{e.getMessage()}, e);
-
- }
-
- }
/**
* Encode the eIDAS request with POST binding
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java
index c4b2bfeae..45ba3d64e 100644
--- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java
@@ -19,12 +19,12 @@ import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils;
import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException;
import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
import at.gv.egovernment.moa.id.process.api.ExecutionContext;
+import at.gv.egovernment.moa.id.protocols.eidas.validator.eIDASResponseValidator;
import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants;
import at.gv.egovernment.moa.logging.Logger;
import at.gv.egovernment.moa.util.MiscUtil;
import eu.eidas.auth.commons.EidasStringUtil;
import eu.eidas.auth.commons.protocol.IAuthenticationResponse;
-import eu.eidas.auth.commons.protocol.eidas.LevelOfAssurance;
import eu.eidas.auth.engine.ProtocolEngineI;
import eu.eidas.engine.exceptions.EIDASSAMLEngineException;
@@ -78,16 +78,8 @@ public class ReceiveAuthnResponseTask extends AbstractAuthServletTask {
// **********************************************************
// ******* MOA-ID specific response validation **********
// **********************************************************
-
- //validate received LoA against minimum required LoA
- LevelOfAssurance reqLoA = LevelOfAssurance.fromString(pendingReq.getOnlineApplicationConfiguration().getQaaLevel());
- LevelOfAssurance respLoA = LevelOfAssurance.fromString(samlResp.getLevelOfAssurance());
- if (respLoA.numericValue() < reqLoA.numericValue()) {
- Logger.error("eIDAS Response LevelOfAssurance is lower than the required! "
- + "(Resp-LoA:" + respLoA.getValue() + " Req-LoA:" + reqLoA.getValue() + ")");
- throw new MOAIDException("eIDAS.14", new Object[]{respLoA.getValue()});
-
- }
+ String spCountry = authConfig.getBasicMOAIDConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_COUNTRYCODE, "AT");
+ eIDASResponseValidator.validateResponse(pendingReq, samlResp, spCountry);
// **********************************************************
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAProtocolEngineFactory.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAProtocolEngineFactory.java
index f29d2bb65..47cdb4ade 100644
--- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAProtocolEngineFactory.java
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAProtocolEngineFactory.java
@@ -95,5 +95,22 @@ public class MOAProtocolEngineFactory extends ProtocolEngineFactory {
}
+// public static ProtocolEngineI createProtocolEngine(String instanceName,
+// ProtocolEngineConfigurationFactory protocolEngineConfigurationFactory,
+// ProtocolProcessorI protocolProcessor, SamlEngineClock samlEngineClock)
+// throws SamlEngineConfigurationException {
+//
+// ProtocolEngineConfiguration preConfiguration = protocolEngineConfigurationFactory
+// .getConfiguration(instanceName);
+//
+// protocolProcessor.configure();
+//
+// ProtocolEngineConfiguration configuration = ProtocolEngineConfiguration.builder(preConfiguration)
+// .protocolProcessor(protocolProcessor).clock(samlEngineClock).build();
+//
+// ProtocolEngineI samlEngine = new MOAProtocolEngine(new FixedProtocolConfigurationAccessor(configuration));
+//
+// return samlEngine;
+// }
}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAWhiteListConfigurator.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAWhiteListConfigurator.java
index 7d647ff15..a2c6a3ad9 100644
--- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAWhiteListConfigurator.java
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAWhiteListConfigurator.java
@@ -22,7 +22,6 @@
*/
package at.gv.egovernment.moa.id.auth.modules.eidas.utils;
-import java.util.Locale;
import java.util.regex.Pattern;
import org.apache.commons.collections.CollectionUtils;
@@ -48,6 +47,11 @@ public class MOAWhiteListConfigurator {
}
ImmutableSet.Builder<String> allowed = ImmutableSet.builder();
String[] wlAlgorithms = WHITE_LIST_SPLITTER.split(algorithmWhiteListValue);
+
+ //BugFix: remove newlines from configuration
+ for (int i=0; i<wlAlgorithms.length; i++)
+ wlAlgorithms[i] = StringUtils.trimToNull(KeyValueUtils.removeAllNewlineFromString(wlAlgorithms[i]));
+
if (null != wlAlgorithms && wlAlgorithms.length > 0) {
return getAllowedAlgorithms(defaultWhiteList, allowedValues, ImmutableSet.<String>copyOf(wlAlgorithms));
}
@@ -72,7 +76,11 @@ public class MOAWhiteListConfigurator {
candidateValue = StringUtils.trimToNull(
KeyValueUtils.removeAllNewlineFromString(candidateValue));
if (StringUtils.isNotBlank(candidateValue)) {
- String candidateAlgorithm = StringUtils.lowerCase(candidateValue, Locale.ENGLISH);
+
+ //BUGFIX: eIDAS SAML-engine MPF1 signature schemes problem
+ String candidateAlgorithm = candidateValue;
+ //String candidateAlgorithm = StringUtils.lowerCase(candidateValue, Locale.ENGLISH);
+
if (allowedValues.contains(candidateAlgorithm)) {
allowed.add(candidateValue);
if (!modified && !candidateAlgorithm.equals(candidateValue)) {
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAeIDASMetadataGenerator.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAeIDASMetadataGenerator.java
index dd14972e3..7b159c73d 100644
--- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAeIDASMetadataGenerator.java
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAeIDASMetadataGenerator.java
@@ -77,7 +77,6 @@ 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;
@@ -209,16 +208,26 @@ public class MOAeIDASMetadataGenerator extends MetadataGenerator {
if (!StringUtils.isEmpty(params.getAssertionConsumerUrl())) {
addAssertionConsumerService();
}
- fillNameIDFormat(spSSODescriptor);
- if (params.getSpEngine() != null) {
- ProtocolEngineI spEngine = params.getSpEngine();
- ((MetadataSignerI) spEngine.getSigner()).signMetadata(spSSODescriptor);
- }
+
+ //FIX: Austrian eIDAS node SP only needs persistent identifiers
+ NameIDFormat persistentFormat =
+ (NameIDFormat) BuilderFactoryUtil.buildXmlObject(NameIDFormat.DEFAULT_ELEMENT_NAME);
+ persistentFormat.setFormat(SamlNameIdFormat.PERSISTENT.getNameIdFormat());
+ spSSODescriptor.getNameIDFormats().add(persistentFormat);
+
+ /**FIXME:
+ * Double signing of SPSSODescribtor is not required
+ */
+// if (params.getSpEngine() != null) {
+// ProtocolEngineI spEngine = params.getSpEngine();
+// ((MetadataSignerI) spEngine.getSigner()).signMetadata(spSSODescriptor);
+// }
+
entityDescriptor.getRoleDescriptors().add(spSSODescriptor);
}
-
- private void fillNameIDFormat(SSODescriptor ssoDescriptor) throws EIDASSAMLEngineException {
+
+ private void fillIDPNameIDFormat(SSODescriptor ssoDescriptor) throws EIDASSAMLEngineException {
NameIDFormat persistentFormat =
(NameIDFormat) BuilderFactoryUtil.buildXmlObject(NameIDFormat.DEFAULT_ELEMENT_NAME);
persistentFormat.setFormat(SamlNameIdFormat.PERSISTENT.getNameIdFormat());
@@ -265,7 +274,11 @@ public class MOAeIDASMetadataGenerator extends MetadataGenerator {
.add(getKeyDescriptor(keyInfoGeneratorFactory, params.getEncryptionCredential(), UsageType.ENCRYPTION));
}
idpSSODescriptor.addSupportedProtocol(params.getIdpSamlProtocol());
- fillNameIDFormat(idpSSODescriptor);
+
+ //Austrian eIDAS node IDP can provided persistent, transient, and unspecified identifiers
+ fillIDPNameIDFormat(idpSSODescriptor);
+
+
if (params.getIdpEngine() != null) {
if (params.getIdpEngine().getProtocolProcessor() != null
&& params.getIdpEngine().getProtocolProcessor().getFormat() == SAMLExtensionFormat.EIDAS10) {
@@ -277,8 +290,13 @@ public class MOAeIDASMetadataGenerator extends MetadataGenerator {
*/
generateSupportedAttributes(idpSSODescriptor, getAllSupportedAttributes());
}
- ProtocolEngineI idpEngine = params.getIdpEngine();
- ((MetadataSignerI) idpEngine.getSigner()).signMetadata(idpSSODescriptor);
+
+
+ /**FIXME:
+ * Double signing of IDPSSODescribtor is not required
+ */
+// ProtocolEngineI idpEngine = params.getIdpEngine();
+// ((MetadataSignerI) idpEngine.getSigner()).signMetadata(idpSSODescriptor);
}
idpSSODescriptor.getSingleSignOnServices().addAll(buildSingleSignOnServicesBindingLocations());
@@ -287,13 +305,18 @@ public class MOAeIDASMetadataGenerator extends MetadataGenerator {
}
- /*TODO: Only a work-around to add eIDAS attributes, which could be provided from MOA-ID, to IDP metadata
+ /* FIX: 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<AttributeDefinition<?>> getAllSupportedAttributes() {
ImmutableSortedSet.Builder<AttributeDefinition<?>> builder =
new ImmutableSortedSet.Builder<>(Ordering.<AttributeDefinition<?>>natural());
- builder.addAll(Constants.MOA_IDP_ATTR_REGISTRY.getAttributes());
+
+ for (String attr : eIDASAttributeBuilder.getAllProvideableeIDASAttributes()) {
+ AttributeDefinition<?> supAttr = params.getIdpEngine().getProtocolProcessor().getAttributeDefinitionNullable(attr);
+ builder.add(supAttr);
+ }
+
return builder.build();
}
@@ -465,7 +488,7 @@ public class MOAeIDASMetadataGenerator extends MetadataGenerator {
X509Certificate decryptionCertificate = engine.getDecryptionCertificate();
if (null != decryptionCertificate) {
- params.setEncryptionCredential(CertificateUtil.toCredential(decryptionCertificate));
+ params.setSpEncryptionCredential(CertificateUtil.toCredential(decryptionCertificate));
}
params.setSigningCredential(CertificateUtil.toCredential(engine.getSigningCertificate()));
params.setIdpEngine(engine);
@@ -530,7 +553,10 @@ public class MOAeIDASMetadataGenerator extends MetadataGenerator {
Set<String> signatureMethods = EIDASUtil.parseSemicolonSeparatedList(params.getDigestMethods());
Set<String> digestMethods = new HashSet<String>();
for (String signatureMethod : signatureMethods) {
- digestMethods.add(CertificateUtil.validateDigestAlgorithm(signatureMethod));
+
+ //BUGFIX: eIDAS implementation does not allow MGF1 signature schemes
+ digestMethods.add(signatureMethod);
+ //digestMethods.add(CertificateUtil.validateDigestAlgorithm(signatureMethod));
}
for (String digestMethod : digestMethods) {
final DigestMethod dm = (DigestMethod) BuilderFactoryUtil.buildXmlObject(DigestMethod.DEF_ELEMENT_NAME);
@@ -569,7 +595,7 @@ public class MOAeIDASMetadataGenerator extends MetadataGenerator {
generateDigest(eidasExtensions);
if (!StringUtils.isEmpty(params.getSigningMethods())) {
- Set<String> signMethods = EIDASUtil.parseSemicolonSeparatedList(params.getDigestMethods());
+ Set<String> signMethods = EIDASUtil.parseSemicolonSeparatedList(params.getSigningMethods());
for (String signMethod : signMethods) {
final SigningMethod sm =
(SigningMethod) BuilderFactoryUtil.buildXmlObject(SigningMethod.DEF_ELEMENT_NAME);
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java
index eb50c113f..edbecc4a0 100644
--- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java
@@ -23,6 +23,8 @@
package at.gv.egovernment.moa.id.auth.modules.eidas.utils;
import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
import java.util.HashMap;
import java.util.Map;
@@ -30,14 +32,19 @@ import org.opensaml.xml.ConfigurationException;
import org.opensaml.xml.XMLConfigurator;
import at.gv.egovernment.moa.id.auth.modules.eidas.Constants;
+import at.gv.egovernment.moa.id.auth.modules.eidas.config.MOAExtendedSWSigner;
import at.gv.egovernment.moa.id.auth.modules.eidas.config.MOAIDCertificateManagerConfigurationImpl;
-import at.gv.egovernment.moa.id.auth.modules.eidas.config.MOASWSigner;
import at.gv.egovernment.moa.id.auth.modules.eidas.engine.MOAEidasProtocolProcesser;
import at.gv.egovernment.moa.id.auth.modules.eidas.engine.MOAeIDASChainingMetadataProvider;
import at.gv.egovernment.moa.id.auth.modules.eidas.engine.MOAeIDASMetadataProviderDecorator;
import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASEngineException;
+import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory;
import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.FileUtils;
+import at.gv.egovernment.moa.util.MiscUtil;
import eu.eidas.auth.commons.attribute.AttributeDefinition;
+import eu.eidas.auth.commons.attribute.AttributeRegistries;
+import eu.eidas.auth.commons.attribute.AttributeRegistry;
import eu.eidas.auth.engine.ProtocolEngineI;
import eu.eidas.auth.engine.SamlEngineSystemClock;
import eu.eidas.auth.engine.metadata.MetadataFetcherI;
@@ -62,6 +69,7 @@ public class SAMLEngineUtils {
if (eIDASEngine == null) {
try {
+
//get eIDAS SAMLengine configuration from MOA-ID configuration
CertificateConfigurationManager configManager = new MOAIDCertificateManagerConfigurationImpl();
@@ -69,13 +77,26 @@ public class SAMLEngineUtils {
metadataFetcher = new MOAeIDASMetadataProviderDecorator(moaeIDASMetadataProvider);
//set metadata signer
- metadataSigner = new MOASWSigner(configManager);
+ metadataSigner = new MOAExtendedSWSigner(configManager);
+
+ //load additional eIDAS attribute definitions
+ String additionalAttributeConfigFile =
+ AuthConfigurationProviderFactory.getInstance().getBasicMOAIDConfiguration(
+ Constants.CONIG_PROPS_EIDAS_SAMLENGINE_ATTIONAL_ATTRIBUTE_DEFINITIONS);
+ AttributeRegistry addAttrDefinitions = AttributeRegistries.empty();
+ if (MiscUtil.isNotEmpty(additionalAttributeConfigFile)) {
+ URL addAttrConfigUrl = new URL(FileUtils.makeAbsoluteURL(
+ additionalAttributeConfigFile,
+ AuthConfigurationProviderFactory.getInstance().getRootConfigFileDir()));
+ addAttrDefinitions = AttributeRegistries.fromFile(addAttrConfigUrl.getPath());
+
+ }
//build eIDAS SAML eninge
ProtocolEngineI engine = MOAProtocolEngineFactory.createProtocolEngine(
Constants.eIDAS_SAML_ENGINE_NAME,
configManager,
- new MOAEidasProtocolProcesser(metadataFetcher, metadataSigner),
+ new MOAEidasProtocolProcesser(metadataFetcher, metadataSigner, addAttrDefinitions),
new SamlEngineSystemClock());
//build a map with all actually supported attributes
@@ -93,6 +114,14 @@ public class SAMLEngineUtils {
Logger.error("eIDAS SAMLengine initialization FAILED!", e);
throw new EIDASEngineException("eIDAS.00", new Object[]{e.getMessage()}, e);
+ } catch (at.gv.egovernment.moa.id.commons.api.exceptions.ConfigurationException e) {
+ Logger.error("eIDAS SAMLengine initialization FAILED!", e);
+ throw new EIDASEngineException("eIDAS.00", new Object[]{e.getMessage()}, e);
+
+ } catch (MalformedURLException e) {
+ Logger.error("eIDAS SAMLengine initialization FAILED!", e);
+ throw new EIDASEngineException("eIDAS.00", new Object[]{e.getMessage()}, e);
+
}
}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/eIDASAttributeBuilder.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/eIDASAttributeBuilder.java
new file mode 100644
index 000000000..22b94178e
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/eIDASAttributeBuilder.java
@@ -0,0 +1,174 @@
+/*
+ * 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.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ServiceLoader;
+
+import com.google.common.collect.ImmutableSet;
+
+import at.gv.egovernment.moa.id.commons.api.IOAAuthParameters;
+import at.gv.egovernment.moa.id.data.IAuthData;
+import at.gv.egovernment.moa.id.data.Pair;
+import at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeBuilder;
+import at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeGenerator;
+import at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.IeIDASAttribute;
+import at.gv.egovernment.moa.id.protocols.pvp2x.builder.PVPAttributeBuilder;
+import at.gv.egovernment.moa.id.protocols.pvp2x.builder.attributes.exceptions.AttributeException;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.MiscUtil;
+import eu.eidas.auth.commons.attribute.AttributeDefinition;
+import eu.eidas.auth.commons.attribute.AttributeDefinition.Builder;
+import eu.eidas.auth.commons.attribute.AttributeValue;
+import eu.eidas.auth.commons.attribute.AttributeValueMarshaller;
+import eu.eidas.auth.commons.attribute.AttributeValueMarshallingException;
+
+/**
+ * @author tlenz
+ *
+ */
+public class eIDASAttributeBuilder extends PVPAttributeBuilder {
+ private static IAttributeGenerator<String> generator = new SimpleEidasAttributeGenerator();
+
+ private static List<String> listOfSupportedeIDASAttributes;
+ private static ServiceLoader<IeIDASAttribute> eIDASAttributLoader =
+ ServiceLoader.load(IeIDASAttribute.class);
+
+ static {
+ List<String> supportAttrList = new ArrayList<String>();
+
+ Logger.info("Select eIDAS attributes that are corrently providable:");
+ if (eIDASAttributLoader != null ) {
+ Iterator<IeIDASAttribute> moduleLoaderInterator = eIDASAttributLoader.iterator();
+ while (moduleLoaderInterator.hasNext()) {
+ try {
+ IeIDASAttribute modul = moduleLoaderInterator.next();
+ Logger.info("Loading eIDAS attribut-builder Modul Information: " + modul.getName());
+ supportAttrList.add(modul.getName());
+
+ } catch(Throwable e) {
+ Logger.error("Check configuration! " + "Some attribute-builder modul" +
+ " is not a valid IAttributeBuilder", e);
+ }
+ }
+ }
+
+ listOfSupportedeIDASAttributes = Collections.unmodifiableList(supportAttrList);
+ Logger.info("Selection of providable eIDAS attributes done");
+
+ }
+
+ /**
+ * Get all eIDAS attribute names that can be generated by the Austrian eIDAS node.
+ * This list is dynamically generated from loaded eIDAS attribute builders that are found in Java Classpath
+ *
+ * @return {@link List} of {@link String} of eIDAS attribute names
+ */
+ public static List<String> getAllProvideableeIDASAttributes() {
+ return listOfSupportedeIDASAttributes;
+ }
+
+ /**
+ * This method build an eIDAS response attribute, by using a loaded eIDAS attribute builder.
+ *
+ * @param attr eIDAS attribute that should be generated
+ * @param onlineApplicationConfiguration SP configuration
+ * @param authData Authentication data that contains user information for attribute generation
+ * @return eIDAS attribute response {@link Pair} or null if the attribute generation FAILES
+ */
+ public static Pair<AttributeDefinition<?>,ImmutableSet<AttributeValue<?>>> buildAttribute(AttributeDefinition<?> attr, IOAAuthParameters onlineApplicationConfiguration,
+ IAuthData authData) {
+
+ String attrName = attr.getNameUri().toString();
+ Logger.trace("Build eIDAS attribute: "+ attrName);
+
+
+ IAttributeBuilder attrBuilder = getAttributeBuilder(attrName);
+ if (attrBuilder != null) {
+ try {
+ String attrValue = attrBuilder.build(onlineApplicationConfiguration, authData, generator);
+ if (MiscUtil.isNotEmpty(attrValue)) {
+ //set uniqueIdentifier attribute, because eIDAS SAMLEngine use this flag to select the
+ // Subject->NameID value from this attribute
+ Builder<?> eIDASAttrBuilder = AttributeDefinition.builder(attr);
+ eIDASAttrBuilder.uniqueIdentifier(evaluateUniqueID(attrName, authData.isUseMandate()));
+ AttributeDefinition<?> returnAttr = eIDASAttrBuilder.build();
+
+ //unmarshal attribute value into eIDAS attribute
+ AttributeValueMarshaller<?> attributeValueMarshaller = returnAttr.getAttributeValueMarshaller();
+ ImmutableSet.Builder<AttributeValue<?>> builder = ImmutableSet.builder();
+
+ AttributeValue<?> attributeValue = null;
+ try {
+ attributeValue = attributeValueMarshaller.unmarshal(attrValue, false);
+ builder.add(attributeValue);
+
+ } catch (AttributeValueMarshallingException e) {
+ throw new IllegalStateException(e);
+
+ }
+
+ return Pair.newInstance(returnAttr, builder.build());
+
+ }
+
+ } catch (AttributeException e) {
+ Logger.debug("Attribute can not generate requested attribute:" + attr.getNameUri().toString() + " Reason:" + e.getMessage());
+
+ }
+
+ } else
+ Logger.warn("NO attribute builder FOUND for eIDAS attr: " + attrName);
+
+ return null;
+ }
+
+ /**
+ * This method use the information from authenticated session and
+ * evaluate the uniqueID flag according to eIDAS specification
+ *
+ * @param attrName eIDAS attribute name that is evaluated
+ * @param useMandate flag that indicates if the current authenticated session includes a mandate
+ * @return true if eIDAS attribute holds the unique ID, otherwise false
+ */
+ private static boolean evaluateUniqueID(String attrName, boolean useMandate) {
+ //if no mandate is used the natural person identifier is the unique ID
+ if (!useMandate &&
+ attrName.equals(eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.PERSON_IDENTIFIER.getNameUri().toString()))
+ return true;
+
+ //if mandates are used the the legal person identifier or the natural person identifier of the mandator is the unique ID
+ else if (useMandate &&
+ attrName.equals(eu.eidas.auth.engine.core.eidas.spec.LegalPersonSpec.Definitions.LEGAL_PERSON_IDENTIFIER.getNameUri().toString()))
+ return true;
+
+ //TODO: implement flag selector for mandates and natural persons
+
+
+ return false;
+ }
+
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/eIDASAttributeProcessingUtils.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/eIDASAttributeProcessingUtils.java
new file mode 100644
index 000000000..30e1e4505
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/eIDASAttributeProcessingUtils.java
@@ -0,0 +1,75 @@
+/*
+ * 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.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import at.gv.egovernment.moa.id.auth.modules.eidas.Constants;
+import at.gv.egovernment.moa.id.data.Trible;
+import at.gv.egovernment.moa.logging.Logger;
+
+/**
+ * @author tlenz
+ *
+ */
+public class eIDASAttributeProcessingUtils {
+ public static final String PERSONALIDENIFIER_VALIDATION_PATTERN = "^[A-Z,a-z]{2}/[A-Z,a-z]{2}/.*";
+
+ /**
+ * Validate a eIDAS PersonalIdentifier attribute value
+ * This validation is done according to eIDAS SAML Attribute Profile - Section 2.2.3 Unique Identifier
+ *
+ * @param uniqueID eIDAS attribute value of a unique identifier
+ * @return true if the uniqueID matches to eIDAS to Unique Identifier specification, otherwise false
+ */
+ public static boolean validateEidasPersonalIdentifier(String uniqueID) {
+ Pattern pattern = Pattern.compile(PERSONALIDENIFIER_VALIDATION_PATTERN );
+ Matcher matcher = pattern.matcher(uniqueID);
+ return matcher.matches();
+
+ }
+
+
+ /**
+ * Parse an eIDAS PersonalIdentifier attribute value into it components.
+ * This processing is done according to eIDAS SAML Attribute Profile - Section 2.2.3 Unique Identifier
+ *
+ * @param uniqueID eIDAS attribute value of a unique identifier
+ * @return {@link Trible} that contains:
+ * <br> First : citizen country
+ * <br> Second: destination country
+ * <br> Third : unique identifier
+ * <br> or null if the attribute value has a wrong format
+ */
+ public static Trible<String, String, String> parseEidasPersonalIdentifier(String uniqueID) {
+ if (!validateEidasPersonalIdentifier(uniqueID)) {
+ Logger.error("eIDAS attribute value for " + Constants.eIDAS_ATTR_PERSONALIDENTIFIER
+ + " looks wrong formated. Value:" + ((String)uniqueID));
+ return null;
+
+ }
+ return Trible.newInstance(uniqueID.substring(0, 2), uniqueID.substring(3, 5), uniqueID.substring(6));
+
+ }
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASData.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASData.java
index 7647b4cab..694efab80 100644
--- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASData.java
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASData.java
@@ -15,6 +15,8 @@ import eu.eidas.auth.commons.protocol.IAuthenticationRequest;
@Scope(value = BeanDefinition.SCOPE_PROTOTYPE)
public class EIDASData extends RequestImpl {
+ public static final String REQ_PARAM_eIDAS_AUTHN_TRANSIENT_ID = "transiendIDRequested";
+
/** The Constant serialVersionUID. */
private static final long serialVersionUID = 8765755670214923910L;
@@ -28,7 +30,7 @@ public class EIDASData extends RequestImpl {
private String remoteIPAddress;
private String remoteRelayState;
-
+
@Override
public Collection<String> getRequestedAttributes(MetadataProvider metadataProvider) {
// TODO Auto-generated method stub
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java
index 13e64cdd0..5d13e26e2 100644
--- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java
@@ -25,6 +25,8 @@ package at.gv.egovernment.moa.id.protocols.eidas;
import java.io.IOException;
import java.io.StringWriter;
import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -36,7 +38,6 @@ import org.opensaml.saml2.core.StatusCode;
import org.opensaml.saml2.metadata.AssertionConsumerService;
import org.opensaml.saml2.metadata.EntityDescriptor;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@@ -51,6 +52,7 @@ import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASAuthnRequestV
import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASException;
import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils;
import at.gv.egovernment.moa.id.commons.MOAIDAuthConstants;
+import at.gv.egovernment.moa.id.commons.MOAIDConstants;
import at.gv.egovernment.moa.id.commons.api.IOAAuthParameters;
import at.gv.egovernment.moa.id.commons.api.IRequest;
import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException;
@@ -65,6 +67,7 @@ import eu.eidas.auth.commons.protocol.eidas.IEidasAuthenticationRequest;
import eu.eidas.auth.commons.protocol.eidas.impl.EidasAuthenticationRequest;
import eu.eidas.auth.commons.protocol.impl.AuthenticationResponse;
import eu.eidas.auth.commons.protocol.impl.AuthenticationResponse.Builder;
+import eu.eidas.auth.commons.protocol.impl.SamlNameIdFormat;
import eu.eidas.auth.engine.ProtocolEngineI;
import eu.eidas.auth.engine.metadata.MetadataUtil;
import eu.eidas.engine.exceptions.EIDASSAMLEngineException;
@@ -149,7 +152,8 @@ public class EIDASProtocol extends AbstractAuthProtocolModulController {
//preProcess eIDAS request
preProcess(req, resp, pendingReq);
- revisionsLogger.logEvent(pendingReq, Constants.eIDAS_REVERSIONSLOG_IDP_AUTHREQUEST);
+ revisionsLogger.logEvent(pendingReq, Constants.eIDAS_REVERSIONSLOG_IDP_AUTHREQUEST,
+ pendingReq.getEidasRequest().getId());
//AuthnRequest needs authentication
pendingReq.setNeedAuthentication(true);
@@ -213,6 +217,11 @@ public class EIDASProtocol extends AbstractAuthProtocolModulController {
}
+ //check eIDAS node configuration
+ IOAAuthParameters oaConfig = authConfig.getOnlineApplicationParameter(samlReq.getIssuer());
+ if (oaConfig == null)
+ throw new EIDASAuthnRequestProcessingException("eIDAS.08", new Object[]{samlReq.getIssuer()});
+
//validate AssertionConsumerServiceURL against metadata
EntityDescriptor eIDASNodeEntityDesc = new MOAeIDASMetadataProviderDecorator(eIDASMetadataProvider)
.getEntityDescriptor(eIDASSamlReq.getIssuer(), SAMLEngineUtils.getMetadataSigner());
@@ -258,8 +267,33 @@ public class EIDASProtocol extends AbstractAuthProtocolModulController {
}
+ //validate request country-code against eIDAS node config
+ String reqCC = samlReq.getOriginCountryCode();
+ String eIDASTarget = oaConfig.getIdentityLinkDomainIdentifier();
+
+ //validate eIDAS target
+ Pattern pattern = Pattern.compile("^" + at.gv.egovernment.moa.util.Constants.URN_PREFIX_EIDAS
+ + "\\+[A-Z,a-z]{2}\\+[A-Z,a-z]{2}$");
+ Matcher matcher = pattern.matcher(eIDASTarget);
+ if (MiscUtil.isEmpty(eIDASTarget) || !matcher.matches()) {
+ Logger.error("Configuration for eIDAS-node:" + samlReq.getIssuer()
+ + " contains wrong formated eIDAS target:" + eIDASTarget);
+ throw new MOAIDException("config.08", new Object[]{samlReq.getIssuer()});
+
+ } else {
+ String[] splittedTarget = eIDASTarget.split("\\+");
+ if (!splittedTarget[2].equalsIgnoreCase(reqCC)) {
+ Logger.error("Configuration for eIDAS-node:" + samlReq.getIssuer()
+ + " Destination Country from request (" + reqCC
+ + ") does not match to configuration:" + eIDASTarget);
+ throw new MOAIDException("eIDAS.01",
+ new Object[]{"Destination Country from request does not match to configuration"});
+
+ }
+ Logger.debug("CountryCode from request matches eIDAS-node configuration target");
+ }
-
+
//*************************************************
//***** store eIDAS request information *********
//*************************************************
@@ -269,15 +303,18 @@ public class EIDASProtocol extends AbstractAuthProtocolModulController {
// - memorize relaystate
String relayState = request.getParameter("RelayState");
pendingReq.setRemoteRelayState(relayState);
-
- // - memorize country code of target country
- pendingReq.setGenericDataToSession(
- RequestImpl.eIDAS_GENERIC_REQ_DATA_COUNTRY, samlReq.getOriginCountryCode());
//store level of assurance
pendingReq.setGenericDataToSession(RequestImpl.eIDAS_GENERIC_REQ_DATA_LEVELOFASSURENCE,
eIDASSamlReq.getEidasLevelOfAssurance().stringValue());
+ //set flag if transiend identifier is requested
+ if (MiscUtil.isNotEmpty(eIDASSamlReq.getNameIdFormat())
+ && eIDASSamlReq.getNameIdFormat().equals(SamlNameIdFormat.TRANSIENT.getNameIdFormat()))
+ pendingReq.setGenericDataToSession(EIDASData.REQ_PARAM_eIDAS_AUTHN_TRANSIENT_ID, true);
+ else
+ pendingReq.setGenericDataToSession(EIDASData.REQ_PARAM_eIDAS_AUTHN_TRANSIENT_ID, false);
+
// - memorize requested attributes
pendingReq.setEidasRequestedAttributes(eIDASSamlReq.getRequestedAttributes());
@@ -288,10 +325,6 @@ public class EIDASProtocol extends AbstractAuthProtocolModulController {
pendingReq.setOAURL(samlReq.getIssuer());
// - memorize OA config
- IOAAuthParameters oaConfig = authConfig.getOnlineApplicationParameter(pendingReq.getOAURL());
- if (oaConfig == null)
- throw new EIDASAuthnRequestProcessingException("eIDAS.08", new Object[]{pendingReq.getOAURL()});
-
pendingReq.setOnlineApplicationConfiguration(oaConfig);
// - memorize service-provider type from eIDAS request
@@ -302,7 +335,7 @@ public class EIDASProtocol extends AbstractAuthProtocolModulController {
if (MiscUtil.isEmpty(spType))
spType = MetadataUtil.getSPTypeFromMetadata(eIDASNodeEntityDesc);
- if (MiscUtil.isEmpty(spType))
+ if (MiscUtil.isNotEmpty(spType))
Logger.debug("eIDAS request has SPType:" + spType);
else
Logger.info("eIDAS request and eIDAS metadata contains NO 'SPType' element.");
@@ -367,7 +400,7 @@ public class EIDASProtocol extends AbstractAuthProtocolModulController {
String token = EidasStringUtil.encodeToBase64(eIDASRespMsg.getMessageBytes());
VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine();
- Template template = velocityEngine.getTemplate("/resources/templates/stork2_postbinding_template.html");
+ Template template = velocityEngine.getTemplate("/resources/templates/eidas_postbinding_template.vm");
VelocityContext context = new VelocityContext();
context.put("RelayState", eidasReq.getRemoteRelayState());
@@ -387,7 +420,7 @@ public class EIDASProtocol extends AbstractAuthProtocolModulController {
Logger.trace("Sending html content : " + new String(writer.getBuffer()));
byte[] content = writer.getBuffer().toString().getBytes("UTF-8");
- response.setContentType(MediaType.TEXT_HTML.getType());
+ response.setContentType(MOAIDConstants.DEFAULT_CONTENT_TYPE_HTML_UTF8);
response.setContentLength(content.length);
response.getOutputStream().write(content);
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EidasMetaDataRequest.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EidasMetaDataRequest.java
index 174fa2c17..df96bef12 100644
--- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EidasMetaDataRequest.java
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EidasMetaDataRequest.java
@@ -72,13 +72,19 @@ public class EidasMetaDataRequest implements IAction {
String metadata_url = pubURLPrefix + Constants.eIDAS_HTTP_ENDPOINT_METADATA;
String sp_return_url = pubURLPrefix + Constants.eIDAS_HTTP_ENDPOINT_SP_POST;
+ //generate eIDAS metadata
String metaData = generateMetadata(req, metadata_url, sp_return_url);
-
+
+ //write content to response
+ byte[] content = metaData.getBytes("UTF-8");
+ httpResp.setStatus(HttpServletResponse.SC_OK);
+ httpResp.setContentType(MediaType.APPLICATION_XML.toString());
+ httpResp.setContentLength(content.length);
+ httpResp.getOutputStream().write(content);
+
+ //write log if required
Logger.trace(metaData);
-
- httpResp.setContentType(MediaType.APPLICATION_XML.getType());
- httpResp.getWriter().print(metaData);
- httpResp.flushBuffer();
+
} catch (Exception e) {
Logger.error("eIDAS Metadata generation FAILED.", e);
throw new MOAIDException("eIDAS.05", new Object[]{e.getMessage()}, e);
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/IeIDASAttribute.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/IeIDASAttribute.java
new file mode 100644
index 000000000..15060fb52
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/IeIDASAttribute.java
@@ -0,0 +1,33 @@
+/*
+ * 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.protocols.eidas.attributes.builder;
+
+import at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeBuilder;
+
+/**
+ * @author tlenz
+ *
+ */
+public interface IeIDASAttribute extends IAttributeBuilder{
+
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrDateOfBirth.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrDateOfBirth.java
new file mode 100644
index 000000000..64e5ae770
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrDateOfBirth.java
@@ -0,0 +1,37 @@
+/*
+ * 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.protocols.eidas.attributes.builder;
+
+import at.gv.egovernment.moa.id.protocols.builder.attributes.BirthdateAttributeBuilder;
+
+/**
+ * @author tlenz
+ *
+ */
+public class eIDASAttrDateOfBirth extends BirthdateAttributeBuilder implements IeIDASAttribute {
+
+ @Override
+ public String getName() {
+ return eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.DATE_OF_BIRTH.getNameUri().toString();
+ }
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrFamilyName.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrFamilyName.java
new file mode 100644
index 000000000..4195eeeef
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrFamilyName.java
@@ -0,0 +1,61 @@
+/*
+ * 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.protocols.eidas.attributes.builder;
+
+import at.gv.egovernment.moa.id.commons.api.IOAAuthParameters;
+import at.gv.egovernment.moa.id.data.IAuthData;
+import at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeGenerator;
+import at.gv.egovernment.moa.id.protocols.pvp2x.builder.attributes.exceptions.AttributeException;
+
+/**
+ * @author tlenz
+ *
+ */
+public class eIDASAttrFamilyName implements IeIDASAttribute{
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeBuilder#getName()
+ */
+ @Override
+ public String getName() {
+ return eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.CURRENT_FAMILY_NAME.getNameUri().toString();
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeBuilder#build(at.gv.egovernment.moa.id.commons.api.IOAAuthParameters, at.gv.egovernment.moa.id.data.IAuthData, at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeGenerator)
+ */
+ @Override
+ public <ATT> ATT build(IOAAuthParameters oaParam, IAuthData authData, IAttributeGenerator<ATT> g)
+ throws AttributeException {
+ return g.buildStringAttribute(null, getName(), authData.getFamilyName());
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeBuilder#buildEmpty(at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeGenerator)
+ */
+ @Override
+ public <ATT> ATT buildEmpty(IAttributeGenerator<ATT> g) {
+ return null;
+ }
+
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrGivenName.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrGivenName.java
new file mode 100644
index 000000000..2a654ac44
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrGivenName.java
@@ -0,0 +1,61 @@
+/*
+ * 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.protocols.eidas.attributes.builder;
+
+import at.gv.egovernment.moa.id.commons.api.IOAAuthParameters;
+import at.gv.egovernment.moa.id.data.IAuthData;
+import at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeGenerator;
+import at.gv.egovernment.moa.id.protocols.pvp2x.builder.attributes.exceptions.AttributeException;
+
+/**
+ * @author tlenz
+ *
+ */
+public class eIDASAttrGivenName implements IeIDASAttribute{
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeBuilder#getName()
+ */
+ @Override
+ public String getName() {
+ return eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.CURRENT_GIVEN_NAME.getNameUri().toString();
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeBuilder#build(at.gv.egovernment.moa.id.commons.api.IOAAuthParameters, at.gv.egovernment.moa.id.data.IAuthData, at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeGenerator)
+ */
+ @Override
+ public <ATT> ATT build(IOAAuthParameters oaParam, IAuthData authData, IAttributeGenerator<ATT> g)
+ throws AttributeException {
+ return g.buildStringAttribute(null, getName(), authData.getGivenName());
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeBuilder#buildEmpty(at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeGenerator)
+ */
+ @Override
+ public <ATT> ATT buildEmpty(IAttributeGenerator<ATT> g) {
+ return null;
+ }
+
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrLegalName.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrLegalName.java
new file mode 100644
index 000000000..51a2bd69b
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrLegalName.java
@@ -0,0 +1,37 @@
+/*
+ * 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.protocols.eidas.attributes.builder;
+
+import at.gv.egovernment.moa.id.protocols.builder.attributes.MandateLegalPersonFullNameAttributeBuilder;
+
+/**
+ * @author tlenz
+ *
+ */
+public class eIDASAttrLegalName extends MandateLegalPersonFullNameAttributeBuilder implements IeIDASAttribute {
+
+ @Override
+ public String getName() {
+ return eu.eidas.auth.engine.core.eidas.spec.LegalPersonSpec.Definitions.LEGAL_NAME.getNameUri().toString();
+ }
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrLegalPersonIdentifier.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrLegalPersonIdentifier.java
new file mode 100644
index 000000000..c008048cb
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrLegalPersonIdentifier.java
@@ -0,0 +1,37 @@
+/*
+ * 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.protocols.eidas.attributes.builder;
+
+import at.gv.egovernment.moa.id.protocols.builder.attributes.MandateLegalPersonSourcePinAttributeBuilder;
+
+/**
+ * @author tlenz
+ *
+ */
+public class eIDASAttrLegalPersonIdentifier extends MandateLegalPersonSourcePinAttributeBuilder implements IeIDASAttribute {
+
+ @Override
+ public String getName() {
+ return eu.eidas.auth.engine.core.eidas.spec.LegalPersonSpec.Definitions.LEGAL_PERSON_IDENTIFIER.getNameUri().toString();
+ }
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrNaturalPersonalIdentifier.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrNaturalPersonalIdentifier.java
new file mode 100644
index 000000000..cb659c2b1
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrNaturalPersonalIdentifier.java
@@ -0,0 +1,116 @@
+/*
+ * 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.protocols.eidas.attributes.builder;
+
+import java.security.MessageDigest;
+
+import at.gv.egovernment.moa.id.auth.modules.eidas.utils.eIDASAttributeProcessingUtils;
+import at.gv.egovernment.moa.id.commons.api.IOAAuthParameters;
+import at.gv.egovernment.moa.id.data.IAuthData;
+import at.gv.egovernment.moa.id.data.Trible;
+import at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeGenerator;
+import at.gv.egovernment.moa.id.protocols.eidas.EIDASData;
+import at.gv.egovernment.moa.id.protocols.pvp2x.builder.attributes.exceptions.AttributeException;
+import at.gv.egovernment.moa.id.util.Random;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.Base64Utils;
+import at.gv.egovernment.moa.util.MiscUtil;
+
+/**
+ * @author tlenz
+ *
+ */
+public class eIDASAttrNaturalPersonalIdentifier implements IeIDASAttribute{
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeBuilder#getName()
+ */
+ @Override
+ public String getName() {
+ return eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.PERSON_IDENTIFIER.getNameUri().toString();
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeBuilder#build(at.gv.egovernment.moa.id.commons.api.IOAAuthParameters, at.gv.egovernment.moa.id.data.IAuthData, at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeGenerator)
+ */
+ @Override
+ public <ATT> ATT build(IOAAuthParameters oaParam, IAuthData authData, IAttributeGenerator<ATT> g)
+ throws AttributeException {
+ String personalID = authData.getBPK();
+
+ //generate eIDAS conform 'PersonalIdentifier' attribute
+ if (!eIDASAttributeProcessingUtils.validateEidasPersonalIdentifier(personalID)) {
+ Logger.debug("preCalculated PersonalIdentifier does not include eIDAS conform prefixes ... add prefix now");
+ if (MiscUtil.isEmpty(authData.getBPKType())
+ || !authData.getBPKType().startsWith(at.gv.egovernment.moa.util.Constants.URN_PREFIX_EIDAS)) {
+ Logger.error("BPKType is empty or does not start with eIDAS bPKType prefix! bPKType:" + authData.getBPKType());
+ throw new AttributeException("Suspect bPKType for eIDAS identifier generation");
+
+ }
+
+ String prefix = authData.getBPKType().substring(at.gv.egovernment.moa.util.Constants.URN_PREFIX_EIDAS.length() + 1);
+ personalID = prefix.replaceAll("\\+", "/") + "/" + personalID;
+
+ }
+
+ //generate a transient unique identifier if it is requested
+ Boolean isTransiendIDRequested =
+ authData.getGenericData(EIDASData.REQ_PARAM_eIDAS_AUTHN_TRANSIENT_ID, Boolean.class);
+ if (isTransiendIDRequested != null && isTransiendIDRequested)
+ personalID = generateTransientNameID(personalID);
+
+ return g.buildStringAttribute(null, getName(), personalID);
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeBuilder#buildEmpty(at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeGenerator)
+ */
+ @Override
+ public <ATT> ATT buildEmpty(IAttributeGenerator<ATT> g) {
+ return null;
+ }
+
+ private String generateTransientNameID(String nameID) {
+ //extract source-country and destination country from persistent identifier
+ Trible<String, String, String> split = eIDASAttributeProcessingUtils.parseEidasPersonalIdentifier(nameID);
+ if (split == null) {
+ Logger.error("eIDAS 'PersonalIdentifier' has a wrong format. There had to be a ERROR in implementation!!!!");
+ throw new IllegalStateException("eIDAS 'PersonalIdentifier' has a wrong format. There had to be a ERROR in implementation!!!!");
+
+ }
+
+ //build correct formated transient identifier
+ String random = Random.nextLongRandom();
+ try {
+ MessageDigest md = MessageDigest.getInstance("SHA-1");
+ byte[] hash = md.digest((split.getThird() + random).getBytes("ISO-8859-1"));
+ return split.getFirst() + "/" + split.getSecond() + "/" + Base64Utils.encode(hash);
+
+ } catch (Exception e) {
+ Logger.error("Can not generate transient personal identifier!", e);
+ return null;
+
+ }
+
+ }
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/eIDASAuthenticationRequest.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/eIDASAuthenticationRequest.java
index 22ac37604..d0cda38c7 100644
--- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/eIDASAuthenticationRequest.java
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/eIDASAuthenticationRequest.java
@@ -23,8 +23,6 @@
package at.gv.egovernment.moa.id.protocols.eidas;
import java.io.StringWriter;
-import java.security.MessageDigest;
-import java.text.SimpleDateFormat;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -34,7 +32,6 @@ import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.opensaml.saml2.core.StatusCode;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import com.google.common.collect.ImmutableSet;
@@ -44,30 +41,23 @@ import at.gv.egovernment.moa.id.auth.frontend.velocity.VelocityProvider;
import at.gv.egovernment.moa.id.auth.modules.eidas.Constants;
import at.gv.egovernment.moa.id.auth.modules.eidas.engine.MOAeIDASChainingMetadataProvider;
import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SimpleEidasAttributeGenerator;
+import at.gv.egovernment.moa.id.auth.modules.eidas.utils.eIDASAttributeBuilder;
+import at.gv.egovernment.moa.id.commons.MOAIDConstants;
import at.gv.egovernment.moa.id.commons.api.IRequest;
import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException;
import at.gv.egovernment.moa.id.data.IAuthData;
+import at.gv.egovernment.moa.id.data.Pair;
import at.gv.egovernment.moa.id.data.SLOInformationImpl;
import at.gv.egovernment.moa.id.data.SLOInformationInterface;
import at.gv.egovernment.moa.id.moduls.IAction;
import at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeGenerator;
-import at.gv.egovernment.moa.id.protocols.builder.attributes.MandateLegalPersonFullNameAttributeBuilder;
-import at.gv.egovernment.moa.id.protocols.builder.attributes.MandateLegalPersonSourcePinAttributeBuilder;
-import at.gv.egovernment.moa.id.protocols.pvp2x.builder.attributes.exceptions.AttributeException;
-import at.gv.egovernment.moa.id.util.Random;
import at.gv.egovernment.moa.logging.Logger;
-import at.gv.egovernment.moa.util.Base64Utils;
-import at.gv.egovernment.moa.util.MiscUtil;
import eu.eidas.auth.commons.EidasStringUtil;
import eu.eidas.auth.commons.attribute.AttributeDefinition;
-import eu.eidas.auth.commons.attribute.AttributeDefinition.Builder;
import eu.eidas.auth.commons.attribute.AttributeValue;
-import eu.eidas.auth.commons.attribute.AttributeValueMarshaller;
-import eu.eidas.auth.commons.attribute.AttributeValueMarshallingException;
import eu.eidas.auth.commons.attribute.ImmutableAttributeMap;
import eu.eidas.auth.commons.protocol.IResponseMessage;
import eu.eidas.auth.commons.protocol.impl.AuthenticationResponse;
-import eu.eidas.auth.commons.protocol.impl.SamlNameIdFormat;
import eu.eidas.auth.engine.ProtocolEngineI;
import eu.eidas.auth.engine.xml.opensaml.SAMLEngineUtils;
@@ -95,82 +85,31 @@ public class eIDASAuthenticationRequest implements IAction {
else
throw new MOAIDException("got wrong IRequest type. is: {}, should be: {}", new String[] {req.getClass().toString(), EIDASData.class.toString()});
-
+
String subjectNameID = null;
-
+
//gather attributes
ImmutableAttributeMap reqAttributeList = (ImmutableAttributeMap) eidasRequest.getEidasRequestedAttributes();
ImmutableAttributeMap.Builder attrMapBuilder = ImmutableAttributeMap.builder();
-
- //TODO: if we support more then this minimum required attributes -> redesign to a smoother attribute builder selector
+
+ //generate eIDAS attributes
for(AttributeDefinition<?> attr : reqAttributeList.getDefinitions()) {
- String newValue = "";
- boolean isUniqueID = false;
- try {
- switch(attr.getFriendlyName()) {
- case Constants.eIDAS_ATTR_DATEOFBIRTH:
- newValue = new SimpleDateFormat("YYYY-MM-dd").format(authData.getDateOfBirth());
- break;
- case Constants.eIDAS_ATTR_CURRENTFAMILYNAME:
- newValue = authData.getFamilyName();
- break;
- case Constants.eIDAS_ATTR_CURRENTGIVENNAME:
- newValue = authData.getGivenName();
- break;
- case Constants.eIDAS_ATTR_PERSONALIDENTIFIER:
- newValue = authData.getBPK();
- isUniqueID = true;
+ Pair<AttributeDefinition<?>, ImmutableSet<AttributeValue<?>>> eIDASAttr = eIDASAttributeBuilder.buildAttribute(
+ attr, req.getOnlineApplicationConfiguration(), authData);
- //generate a transient unique identifier if it is requested
- String reqNameIDFormat = eidasRequest.getEidasRequest().getNameIdFormat();
- if (MiscUtil.isNotEmpty(reqNameIDFormat)
- && reqNameIDFormat.equals(SamlNameIdFormat.TRANSIENT.getNameIdFormat()))
- newValue = generateTransientNameID(newValue);
-
- subjectNameID = newValue;
- break;
- case Constants.eIDAS_ATTR_LEGALPERSONIDENTIFIER:
- newValue = new MandateLegalPersonSourcePinAttributeBuilder().build(
- req.getOnlineApplicationConfiguration(), authData, generator);
- break;
- case Constants.eIDAS_ATTR_LEGALNAME:
- newValue = new MandateLegalPersonFullNameAttributeBuilder().build(
- req.getOnlineApplicationConfiguration(), authData, generator);
- break;
-
- }
-
- } catch (AttributeException e) {
- Logger.debug("Attribute can not generate requested attribute:" + attr.getFriendlyName() + " Reason:" + e.getMessage());
-
- }
-
- if(MiscUtil.isEmpty(newValue)) {
- Logger.info("eIDAS Attr:" + attr.getNameUri() + " is not available.");
+ if(eIDASAttr == null) {
+ if (attr.isRequired()) {
+ Logger.info("eIDAS Attr:" + attr.getNameUri() + " is marked as 'Required' but not available.");
+ throw new MOAIDException("eIDAS.15", new Object[]{attr.getFriendlyName()});
+
+ } else
+ Logger.info("eIDAS Attr:" + attr.getNameUri() + " is not available.");
} else {
- //set uniqueIdentifier attribute, because eIDAS SAMLEngine use this flag to select the
- // Subject->NameID value from this attribute
- Builder<?> attrBuilder = AttributeDefinition.builder(attr);
- attrBuilder.uniqueIdentifier(isUniqueID);
- AttributeDefinition<?> returnAttr = attrBuilder.build();
-
- //unmarshal attribute value into eIDAS attribute
- AttributeValueMarshaller<?> attributeValueMarshaller = returnAttr.getAttributeValueMarshaller();
- ImmutableSet.Builder<AttributeValue<?>> builder = ImmutableSet.builder();
-
- AttributeValue<?> attributeValue = null;
- try {
- attributeValue = attributeValueMarshaller.unmarshal(newValue, false);
- builder.add(attributeValue);
-
- } catch (AttributeValueMarshallingException e) {
- throw new IllegalStateException(e);
-
- }
-
- //add attribute to Map
- attrMapBuilder.put((AttributeDefinition)returnAttr, (ImmutableSet) builder.build());
+ //add attribute to Map
+ attrMapBuilder.put(
+ (AttributeDefinition)eIDASAttr.getFirst(),
+ (ImmutableSet)eIDASAttr.getSecond());
}
}
@@ -207,19 +146,7 @@ public class eIDASAuthenticationRequest implements IAction {
eIDASRespMsg = engine.generateResponseMessage(eidasRequest.getEidasRequest(),
response, true, eidasRequest.getRemoteAddress());
-
-// if(null == eidasRequest.getEidasRequest().getAssertionConsumerServiceURL()) {
-// String assertionConsumerUrl = MetadataUtil.getAssertionUrlFromMetadata(
-// new MOAeIDASMetadataProviderDecorator(eIDASMetadataProvider),
-// engine,
-// eidasRequest.getEidasRequest());
-// eidasRequest.getEidasRequest().setAssertionConsumerServiceURL(assertionConsumerUrl);
-//
-// }
-
-// response = engine.generateEIDASAuthnResponse(eidasRequest.getEidasRequest(), response, eidasRequest.getRemoteAddress(), true);
-
-
+
token = EidasStringUtil.encodeToBase64(eIDASRespMsg.getMessageBytes());
} catch(Exception e) {
@@ -228,12 +155,13 @@ public class eIDASAuthenticationRequest implements IAction {
}
- revisionsLogger.logEvent(req, Constants.eIDAS_REVERSIONSLOG_IDP_AUTHREQUEST);
+ revisionsLogger.logEvent(req, Constants.eIDAS_REVERSIONSLOG_IDP_AUTHRESPONSE,
+ eIDASRespMsg.getResponse().getId());
// send the response
try {
VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine();
- Template template = velocityEngine.getTemplate("/resources/templates/stork2_postbinding_template.html");
+ Template template = velocityEngine.getTemplate("/resources/templates/eidas_postbinding_template.vm");
VelocityContext context = new VelocityContext();
context.put("RelayState", eidasRequest.getRemoteRelayState());
@@ -253,7 +181,7 @@ public class eIDASAuthenticationRequest implements IAction {
Logger.trace("Sending html content : " + new String(writer.getBuffer()));
byte[] content = writer.getBuffer().toString().getBytes("UTF-8");
- httpResp.setContentType(MediaType.TEXT_HTML.getType());
+ httpResp.setContentType(MOAIDConstants.DEFAULT_CONTENT_TYPE_HTML_UTF8);
httpResp.setContentLength(content.length);
httpResp.getOutputStream().write(content);
@@ -294,20 +222,6 @@ public class eIDASAuthenticationRequest implements IAction {
}
- private String generateTransientNameID(String nameID) {
- String random = Random.nextLongRandom();
-
- try {
- MessageDigest md = MessageDigest.getInstance("SHA-1");
- byte[] hash = md.digest((nameID + random).getBytes("ISO-8859-1"));
- return Base64Utils.encode(hash);
-
- } catch (Exception e) {
- Logger.error("Can not generate transient personal identifier!", e);
- return null;
-
- }
-
- }
+
}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/validator/eIDASResponseValidator.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/validator/eIDASResponseValidator.java
new file mode 100644
index 000000000..f0527bc5e
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/validator/eIDASResponseValidator.java
@@ -0,0 +1,130 @@
+/*
+ * 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.protocols.eidas.validator;
+
+import at.gv.egovernment.moa.id.auth.modules.eidas.Constants;
+import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils;
+import at.gv.egovernment.moa.id.auth.modules.eidas.utils.eIDASAttributeProcessingUtils;
+import at.gv.egovernment.moa.id.commons.api.IRequest;
+import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException;
+import at.gv.egovernment.moa.id.data.Trible;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.MiscUtil;
+import eu.eidas.auth.commons.protocol.IAuthenticationResponse;
+import eu.eidas.auth.commons.protocol.eidas.LevelOfAssurance;
+
+/**
+ * @author tlenz
+ *
+ */
+public class eIDASResponseValidator {
+
+
+ public static void validateResponse(IRequest pendingReq, IAuthenticationResponse samlResp, String spCountry) throws MOAIDException {
+
+ /*-----------------------------------------------------|
+ * validate received LoA against minimum required LoA |
+ *_____________________________________________________|
+ */
+ LevelOfAssurance reqLoA = LevelOfAssurance.fromString(pendingReq.getOnlineApplicationConfiguration().getQaaLevel());
+ LevelOfAssurance respLoA = LevelOfAssurance.fromString(samlResp.getLevelOfAssurance());
+ if (respLoA.numericValue() < reqLoA.numericValue()) {
+ Logger.error("eIDAS Response LevelOfAssurance is lower than the required! "
+ + "(Resp-LoA:" + respLoA.getValue() + " Req-LoA:" + reqLoA.getValue() + ")");
+ throw new MOAIDException("eIDAS.14", new Object[]{respLoA.getValue()});
+
+ }
+
+ /*-----------------------------------------------------|
+ * validate 'PersonalIdentifier' attribute |
+ *_____________________________________________________|
+ */
+ String respCC = samlResp.getCountry();
+ Object personalIdObj = samlResp.getAttributes().getFirstValue(
+ SAMLEngineUtils.getMapOfAllAvailableAttributes().get(
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER));
+
+ //check attribute type
+ if (personalIdObj == null || !(personalIdObj instanceof String))
+ Logger.warn("eIDAS Response include NO 'PersonalIdentifier' attriubte "
+ + ".... That can be a BIG problem in further processing steps");
+
+ else {
+ //validate attribute value format
+ Trible<String, String, String> split =
+ eIDASAttributeProcessingUtils.parseEidasPersonalIdentifier((String)personalIdObj);
+ if (split == null) {
+ throw new MOAIDException("eIDAS.16",
+ new Object[]{
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER,
+ "Wrong identifier format"});
+
+ } else {
+ //validation according to eIDAS SAML Attribute Profile, Section 2.2.3
+ if (MiscUtil.isEmpty(split.getSecond())) {
+ Logger.error("eIDAS attribute value for " + Constants.eIDAS_ATTR_PERSONALIDENTIFIER
+ + " includes NO destination country. Value:" + ((String)personalIdObj));
+ throw new MOAIDException("eIDAS.16",
+ new Object[]{
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER,
+ "No or empty destination country"});
+
+ }
+ if (!split.getSecond().equalsIgnoreCase(spCountry)) {
+ Logger.error("eIDAS attribute value for " + Constants.eIDAS_ATTR_PERSONALIDENTIFIER
+ + " includes wrong destination country. Value:" + ((String)personalIdObj)
+ + " SP-Country:" + spCountry);
+ throw new MOAIDException("eIDAS.16",
+ new Object[]{
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER,
+ "Destination country does not match to SP country"});
+
+ }
+
+ if (MiscUtil.isEmpty(split.getFirst())) {
+ Logger.error("eIDAS attribute value for " + Constants.eIDAS_ATTR_PERSONALIDENTIFIER
+ + " includes NO citizen country. Value:" + ((String)personalIdObj));
+ throw new MOAIDException("eIDAS.16",
+ new Object[]{
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER,
+ "No or empty citizen country"});
+
+ }
+ if (!split.getFirst().equalsIgnoreCase(respCC)) {
+ Logger.error("eIDAS attribute value for " + Constants.eIDAS_ATTR_PERSONALIDENTIFIER
+ + " includes a citizen country that does not match to eIDAS Response node. "
+ + " Value:" + ((String)personalIdObj)
+ + " Response-Node Country:" + respCC);
+ throw new MOAIDException("eIDAS.16",
+ new Object[]{
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER,
+ "Citizen country does not match to eIDAS-node country that generates the response"});
+
+ }
+ }
+ }
+
+
+
+ }
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeBuilder b/id/server/modules/moa-id-module-eIDAS/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeBuilder
new file mode 100644
index 000000000..62e7c20ab
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeBuilder
@@ -0,0 +1,6 @@
+at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.eIDASAttrDateOfBirth
+at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.eIDASAttrFamilyName
+at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.eIDASAttrGivenName
+at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.eIDASAttrNaturalPersonalIdentifier
+at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.eIDASAttrLegalPersonIdentifier
+at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.eIDASAttrLegalName
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.IeIDASAttribute b/id/server/modules/moa-id-module-eIDAS/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.IeIDASAttribute
new file mode 100644
index 000000000..62e7c20ab
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.IeIDASAttribute
@@ -0,0 +1,6 @@
+at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.eIDASAttrDateOfBirth
+at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.eIDASAttrFamilyName
+at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.eIDASAttrGivenName
+at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.eIDASAttrNaturalPersonalIdentifier
+at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.eIDASAttrLegalPersonIdentifier
+at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.eIDASAttrLegalName
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/resources/resources/templates/eidas_postbinding_template.vm b/id/server/modules/moa-id-module-eIDAS/src/main/resources/resources/templates/eidas_postbinding_template.vm
index 3bd225b00..0535d48b6 100644
--- a/id/server/modules/moa-id-module-eIDAS/src/main/resources/resources/templates/eidas_postbinding_template.vm
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/resources/resources/templates/eidas_postbinding_template.vm
@@ -7,7 +7,7 @@
## SAMLRequest - String - the Base64 encoded SAML Request
## SAMLResponse - String - the Base64 encoded SAML Response
## Contains target attribute to delegate PEPS authentication out of iFrame
-
+<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>