aboutsummaryrefslogtreecommitdiff
path: root/id/server/modules/moa-id-module-eIDAS/src/main/java/at
diff options
context:
space:
mode:
Diffstat (limited to 'id/server/modules/moa-id-module-eIDAS/src/main/java/at')
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java75
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAIDCertificateManagerConfigurationImpl.java118
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAeIDASSAMLEngineConfigurationImpl.java268
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAeIDASSAMLInstanceConfigurationImpl.java60
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/eIDASAuthenticationModulImpl.java72
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/eIDASSignalServlet.java95
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASChainingMetadataProvider.java370
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASMetadataProviderDecorator.java120
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASMetadataSignatureFilter.java132
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/EIDASEngineConfigurationException.java60
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/EIDASEngineException.java45
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/eIDASAttributeException.java38
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/CreateIdentityLinkTask.java185
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/GenerateAuthnRequestTask.java210
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java109
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAOrderedAttributeIterator.java66
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAPersonalAttributeList.java343
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java71
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/AuthenticationRequest.java176
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASData.java96
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java152
-rw-r--r--id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EidasMetaDataRequest.java117
22 files changed, 2978 insertions, 0 deletions
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
new file mode 100644
index 000000000..5166f090d
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.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;
+
+/**
+ * @author tlenz
+ *
+ */
+public class Constants {
+
+ public static final String eIDAS_SAML_ENGINE_NAME = "default";
+ public static final String SSLSOCKETFACTORYNAME = "eIDASMetadataSSLSocketFactory";
+
+ //default keys for eIDAS SAML-engine configuration
+ public static final String eIDAS_SAML_ENGINE_NAME_ID_BASICCONFIG = "SamlEngineConf";
+ public static final String eIDAS_SAML_ENGINE_NAME_ID_SIGNATURECONFIG = "SignatureConf";
+ public static final String eIDAS_SAML_ENGINE_NAME_ID_ENCRYPTIONCONFIG = "EncryptionConf";
+ 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 = "eu.eidas.auth.engine.core.impl.SignSW";
+ public static final String SAML_ENCRYPTION_IMPLENTATION = "eu.eidas.auth.engine.core.impl.EncryptionSW";
+
+ //configuration property keys
+ public static final String CONIG_PROPS_EIDAS_PREFIX="moa.id.protocols.eIDAS";
+ public static final String CONIG_PROPS_EIDAS_SAMLENGINE="samlengine";
+ public static final String CONIG_PROPS_EIDAS_SAMLENGINE_PREFIX=CONIG_PROPS_EIDAS_PREFIX + "." + CONIG_PROPS_EIDAS_SAMLENGINE;
+ public static final String CONIG_PROPS_EIDAS_SAMLENGINE_BASIC_CONFIGFILE = CONIG_PROPS_EIDAS_SAMLENGINE_PREFIX + ".config.file";
+ public static final String CONIG_PROPS_EIDAS_SAMLENGINE_SIGN="sign";
+ public static final String CONIG_PROPS_EIDAS_SAMLENGINE_ENCRYPT="enc";
+ 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";
+ public static final String CONIG_PROPS_EIDAS_METADATA_VALIDATION_TRUSTSTORE = CONIG_PROPS_EIDAS_PREFIX + ".metadata.validation.truststore";
+
+ //timeouts and clock skews
+ public static final long CONFIG_PROPS_SKEWTIME = 2 * 60 * 1000; //2 minutes skew time for response validation
+ public static final int CONFIG_PROPS_METADATA_SOCKED_TIMEOUT = 20 * 1000; //20 seconds metadata socked timeout
+ public static final long CONFIG_PROPS_METADATA_GARBAGE_TIMEOUT = 7 * 24 * 60 * 60 * 1000; //remove unused eIDAS metadata after 7 days
+
+ //eIDAS attribute names
+ public static final String eIDAS_ATTR_PERSONALIDENTIFIER = "PersonIdentifier";
+ public static final String eIDAS_ATTR_DATEOFBIRTH = "DateOfBirth";
+ public static final String eIDAS_ATTR_CURRENTGIVENNAME = "CurrentGivenName";
+ public static final String eIDAS_ATTR_CURRENTFAMILYNAME = "CurrentFamilyName";
+
+ //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_METADATA = "/eidas/metadata";
+
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAIDCertificateManagerConfigurationImpl.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAIDCertificateManagerConfigurationImpl.java
new file mode 100644
index 000000000..9b634ff4d
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAIDCertificateManagerConfigurationImpl.java
@@ -0,0 +1,118 @@
+/*
+ * 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.util.HashMap;
+import java.util.Map;
+
+import at.gv.egovernment.moa.logging.Logger;
+
+import eu.eidas.config.ConfigurationException;
+import eu.eidas.samlengineconfig.AbstractCertificateConfigurationManager;
+import eu.eidas.samlengineconfig.EngineInstance;
+import eu.eidas.samlengineconfig.SamlEngineConfiguration;
+import eu.eidas.samlengineconfig.impl.SamlEngineConfigurationImpl;
+
+/**
+ * @author tlenz
+ *
+ */
+public class MOAIDCertificateManagerConfigurationImpl extends
+ AbstractCertificateConfigurationManager {
+
+ private SamlEngineConfiguration samlEngineConfiguration =null;
+
+ @Override
+ public boolean isActive() {
+ return true;
+ }
+
+ /**
+ *
+ */
+ public MOAIDCertificateManagerConfigurationImpl() {
+ try {
+ initalizeConfiguration();
+
+ } catch (at.gv.egovernment.moa.id.config.ConfigurationException e) {
+ Logger.error("eIDAS SAML-engine initialization FAILED", e);
+
+ }
+ }
+
+
+ /* (non-Javadoc)
+ * @see eu.eidas.samlengineconfig.CertificateConfigurationManager#addConfiguration(java.lang.String, java.lang.String, java.util.Map, boolean)
+ */
+ @Override
+ public void addConfiguration(String paramString1, String paramString2,
+ Map<String, String> paramMap, boolean paramBoolean) {
+ throw new ConfigurationException("","not yet implemented");
+
+ }
+
+ /* (non-Javadoc)
+ * @see eu.eidas.samlengineconfig.CertificateConfigurationManager#getInstance(java.lang.String)
+ */
+ @Override
+ public EngineInstance getInstance(String paramString) {
+ return getConfiguration().get(paramString);
+
+ }
+
+ /* (non-Javadoc)
+ * @see eu.eidas.samlengineconfig.CertificateConfigurationManager#getConfiguration()
+ */
+ @Override
+ public Map<String, EngineInstance> getConfiguration() {
+ if(samlEngineConfiguration == null){
+ try {
+ initalizeConfiguration();
+
+ } catch (at.gv.egovernment.moa.id.config.ConfigurationException e) {
+ Logger.error("eIDAS SAML-engine initialization FAILED", e);
+
+ }
+
+ }
+
+ return samlEngineConfiguration==null?new HashMap<String, EngineInstance>():((MOAeIDASSAMLEngineConfigurationImpl) samlEngineConfiguration).getInstanceMap();
+
+ }
+
+
+ /**
+ * Initialize eIDAS SAML-engine from MOA-ID configuration
+ * @throws at.gv.egovernment.moa.id.config.ConfigurationException
+ *
+ */
+ private void initalizeConfiguration() throws at.gv.egovernment.moa.id.config.ConfigurationException {
+ //initialize configuration
+ MOAeIDASSAMLEngineConfigurationImpl tmp = new MOAeIDASSAMLEngineConfigurationImpl();
+ tmp.initialize();
+
+ //set initialized configuration
+ samlEngineConfiguration = tmp;
+ }
+
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAeIDASSAMLEngineConfigurationImpl.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAeIDASSAMLEngineConfigurationImpl.java
new file mode 100644
index 000000000..584910ea5
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAeIDASSAMLEngineConfigurationImpl.java
@@ -0,0 +1,268 @@
+/*
+ * 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.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import at.gv.egovernment.moa.id.auth.modules.eidas.Constants;
+import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASEngineConfigurationException;
+import at.gv.egovernment.moa.id.config.ConfigurationException;
+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.samlengineconfig.BinaryParameter;
+import eu.eidas.samlengineconfig.ConfigurationParameter;
+import eu.eidas.samlengineconfig.EngineInstance;
+import eu.eidas.samlengineconfig.InstanceConfiguration;
+import eu.eidas.samlengineconfig.PropsParameter;
+import eu.eidas.samlengineconfig.SamlEngineConfiguration;
+
+/**
+ * @author tlenz
+ *
+ */
+public class MOAeIDASSAMLEngineConfigurationImpl extends
+ SamlEngineConfiguration {
+
+ private static final String KEYSTORE_PATH="keystorePath";
+ private static final String METADATA_KEYSTORE_PATH="metadata.keystorePath";
+ private static final String ENCRYPTION_ACTIVATION="encryptionActivation";
+ private static final String[] BINARY_PARAMETERS={KEYSTORE_PATH, ENCRYPTION_ACTIVATION,METADATA_KEYSTORE_PATH};
+
+ public List<EngineInstance> getInstances(){
+ return super.getInstances();
+ }
+
+ @Override
+ public void setInstances(List<EngineInstance> engineInstances) {
+ super.setInstances(engineInstances);
+
+ }
+
+ public Map<String, EngineInstance> getInstanceMap() {
+ Map<String, EngineInstance> result = new HashMap<String, EngineInstance>();
+ for(EngineInstance instance:getInstances()) {
+
+ result.put(instance.getName(), instance);
+ }
+
+ return result;
+ }
+
+ //initialize
+ public void initialize() throws ConfigurationException {
+ //create an eIDAS SAML-engine instance
+ EngineInstance engineInst = new EngineInstance();
+ engineInst.setName(Constants.eIDAS_SAML_ENGINE_NAME);
+ List<InstanceConfiguration> engineConfigs = new ArrayList<InstanceConfiguration>();
+
+
+ //add configurations
+
+ //add basic eIDAS SAML-engine configuration
+ MOAeIDASSAMLInstanceConfigurationImpl samlBaseConfig = new MOAeIDASSAMLInstanceConfigurationImpl();
+ samlBaseConfig.setName(Constants.eIDAS_SAML_ENGINE_NAME_ID_BASICCONFIG);
+ samlBaseConfig.addParameter(loadConfigurationFromExternalFile(Constants.CONIG_PROPS_EIDAS_SAMLENGINE_BASIC_CONFIGFILE));
+ engineConfigs.add(samlBaseConfig);
+
+ //add signing eIDAS SAML-engine configuration
+ MOAeIDASSAMLInstanceConfigurationImpl samlSignConfig = new MOAeIDASSAMLInstanceConfigurationImpl();
+ samlSignConfig.setName(Constants.eIDAS_SAML_ENGINE_NAME_ID_SIGNATURECONFIG);
+ samlSignConfig.addParameter(Constants.eIDAS_SAML_ENGINE_NAME_ID_CLASS,
+ Constants.SAML_SIGNING_IMPLENTATION);
+
+ //TODO: load signing keys directly from MOA-ID configuration in finale version
+ samlSignConfig.addParameter(loadConfigurationFromExternalFile(Constants.CONIG_PROPS_EIDAS_SAMLENGINE_SIGN_CONFIGFILE));
+ engineConfigs.add(samlSignConfig);
+
+ //add encryption eIDAS SAML-engine configuration
+ MOAeIDASSAMLInstanceConfigurationImpl samlEncConfig = new MOAeIDASSAMLInstanceConfigurationImpl();
+ samlEncConfig.setName(Constants.eIDAS_SAML_ENGINE_NAME_ID_ENCRYPTIONCONFIG);
+ samlEncConfig.addParameter(Constants.eIDAS_SAML_ENGINE_NAME_ID_CLASS,
+ Constants.SAML_ENCRYPTION_IMPLENTATION);
+
+ //TODO: load encryption keys directly from MOA-ID configuration in finale version
+ samlEncConfig.addParameter(loadConfigurationFromExternalFile(Constants.CONIG_PROPS_EIDAS_SAMLENGINE_ENC_CONFIGFILE));
+ engineConfigs.add(samlEncConfig);
+
+ engineInst.setConfigurations(engineConfigs);
+ super.addInstance(engineInst);
+
+ }
+
+ /**
+ * Load an external eIDAS SAML-engine configuration file, which is referenced from MOA-ID configuration
+ *
+ * @param key Configuration key, which is used in property based MOA-ID configuration file
+ * @return eIDAS SAML-engine configuration object
+ * @throws ConfigurationException
+ */
+
+ private ConfigurationParameter loadConfigurationFromExternalFile(String key) throws ConfigurationException {
+ String configFile =
+ AuthConfigurationProviderFactory.getInstance().getBasicMOAIDConfiguration(key);
+ if (MiscUtil.isEmpty(configFile)) {
+ Logger.warn("No eIDAS SAML-engine configuration key: "
+ + key + " found in MOA-ID properties configuration file.");
+ //throw new EIDASEngineConfigurationException("No eIDAS SAML-engine configuration property.", null);
+ return null;
+ }
+
+ Properties inputProps = loadPropsFromXml(configFile);
+ return buildPropsParameter(inputProps, configFile);
+
+ }
+
+
+ private PropsParameter buildPropsParameter(Properties inputProps, String fileName) throws EIDASEngineConfigurationException {
+ PropsParameter outputProps = new PropsParameter();
+ outputProps.setFileName(fileName);
+
+ //original eIDAS SAML-engine use this identifier
+ outputProps.setName("fileConfiguration");
+
+ outputProps.setValue(inputProps);
+
+ //post-process special parameters
+ for(String key:BINARY_PARAMETERS) {
+ Object keystorePath = inputProps.get(key);
+ if (keystorePath != null) {
+ if (keystorePath instanceof String &&
+ isBinaryParameter((String)keystorePath) ) {
+ BinaryParameter bp = new BinaryParameter();
+ bp.setValue(loadBinaryFile(keystorePath.toString()));
+ bp.setName(key);
+ bp.setUrl(keystorePath.toString());
+ inputProps.put(key, bp);
+
+ } else {
+ Logger.warn("eIDAS SAML-engine keyStore parameter has an unsuspected type. +" +
+ "(Type: " + keystorePath.toString() + ")");
+
+ }
+ }
+ }
+
+ return outputProps;
+ }
+
+ private boolean isBinaryParameter(String parameter) {
+ if (MiscUtil.isNotEmpty(parameter)) {
+ String absoluteConfigFile;
+ try {
+ absoluteConfigFile = FileUtils.makeAbsoluteURL(
+ parameter,
+ AuthConfigurationProviderFactory.getInstance().getRootConfigFileDir());
+ File file = new File(new URL(absoluteConfigFile).toURI());
+ return file.exists();
+
+ } catch (ConfigurationException | MalformedURLException | URISyntaxException e) {
+ Logger.warn("Binary eIDAS SAML-engine configuration parameter: "
+ + parameter + " is not loadable.");
+
+ }
+
+ }
+
+ return false;
+
+ }
+
+ private byte[] loadBinaryFile(String fileName) throws EIDASEngineConfigurationException{
+ InputStream is = null;
+ byte data[]=null;
+ try {
+ String absoluteConfigFile = FileUtils.makeAbsoluteURL(
+ fileName,
+ AuthConfigurationProviderFactory.getInstance().getRootConfigFileDir());
+
+ File file = new File(new URL(absoluteConfigFile).toURI());
+ is = new FileInputStream(file);
+ data=new byte[is.available()];
+ is.read(data);
+
+ } catch (ConfigurationException | URISyntaxException | IOException e) {
+ throw new EIDASEngineConfigurationException("eIDAS SAML-engine configuration FAILED", null, e);
+
+ } finally {
+ if (is != null)
+ try {
+ is.close();
+
+ } catch (IOException e) {
+ Logger.warn("eIDAS SAML-engine configuration is not closeable.", e);
+
+ }
+
+ }
+
+ return data;
+
+ }
+
+ private Properties loadPropsFromXml(String configFile) throws EIDASEngineConfigurationException {
+ Properties props = new Properties();
+ InputStream is = null;
+ try {
+ String absoluteConfigFile = FileUtils.makeAbsoluteURL(
+ configFile,
+ AuthConfigurationProviderFactory.getInstance().getRootConfigFileDir());
+
+ File file = new File(new URL(absoluteConfigFile).toURI());
+ is = new FileInputStream(file);
+ props.loadFromXML(is);
+
+ } catch (ConfigurationException | URISyntaxException | IOException e) {
+ throw new EIDASEngineConfigurationException("eIDAS SAML-engine configuration FAILED", null, e);
+
+ } finally {
+ if (is != null)
+ try {
+ is.close();
+
+ } catch (IOException e) {
+ Logger.warn("eIDAS SAML-engine configuration is not closeable.", e);
+
+ }
+
+ }
+
+ return props;
+
+ }
+
+
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAeIDASSAMLInstanceConfigurationImpl.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAeIDASSAMLInstanceConfigurationImpl.java
new file mode 100644
index 000000000..dccd39905
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAeIDASSAMLInstanceConfigurationImpl.java
@@ -0,0 +1,60 @@
+/*
+ * 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.util.ArrayList;
+import java.util.List;
+
+import eu.eidas.samlengineconfig.ConfigurationParameter;
+import eu.eidas.samlengineconfig.InstanceConfiguration;
+import eu.eidas.samlengineconfig.StringParameter;
+
+/**
+ * @author tlenz
+ *
+ */
+public class MOAeIDASSAMLInstanceConfigurationImpl extends
+ InstanceConfiguration {
+
+ public void addParameter(ConfigurationParameter param) {
+ if (param != null) {
+ List<ConfigurationParameter> paramList = super.getParameters();
+ if (paramList == null) {
+ paramList = new ArrayList<ConfigurationParameter>();
+ super.setParameters(paramList);
+
+ }
+
+ paramList.add(param);
+ }
+ }
+
+ public void addParameter(String key, String value) {
+ StringParameter param = new StringParameter();
+ param.setName(key);
+ param.setValue(value);
+ addParameter(param);
+
+ }
+
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/eIDASAuthenticationModulImpl.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/eIDASAuthenticationModulImpl.java
new file mode 100644
index 000000000..7b044522c
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/eIDASAuthenticationModulImpl.java
@@ -0,0 +1,72 @@
+/*
+ * 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;
+
+import org.apache.commons.lang3.StringUtils;
+
+import at.gv.egovernment.moa.id.auth.modules.AuthModule;
+import at.gv.egovernment.moa.id.process.api.ExecutionContext;
+
+/**
+ * @author tlenz
+ *
+ */
+public class eIDASAuthenticationModulImpl implements AuthModule {
+
+ private int priority = 1;
+
+ @Override
+ public int getPriority() {
+ return priority;
+ }
+
+ /**
+ * Sets the priority of this module. Default value is {@code 0}.
+ * @param priority The priority.
+ */
+ public void setPriority(int priority) {
+ this.priority = priority;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#selectProcess(at.gv.egovernment.moa.id.process.api.ExecutionContext)
+ */
+ @Override
+ public String selectProcess(ExecutionContext context) {
+ if (StringUtils.isNotBlank((String) context.get("ccc")) ||
+ StringUtils.isNotBlank((String) context.get("CCC")))
+ return "eIDASAuthentication";
+ else
+ return null;
+
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#getProcessDefinitions()
+ */
+ @Override
+ public String[] getProcessDefinitions() {
+ return new String[] { "classpath:at/gv/egovernment/moa/id/auth/modules/eidas/eIDAS.Authentication.process.xml" };
+ }
+
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/eIDASSignalServlet.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/eIDASSignalServlet.java
new file mode 100644
index 000000000..49f0451cb
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/eIDASSignalServlet.java
@@ -0,0 +1,95 @@
+/*
+ * 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;
+
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.lang.StringEscapeUtils;
+
+import at.gv.egovernment.moa.id.auth.servlet.ProcessEngineSignalServlet;
+import at.gv.egovernment.moa.logging.Logger;
+
+/**
+ * @author tlenz
+ *
+ */
+@WebServlet(urlPatterns = { "/eidas/sp/post", "/eidas/sp/redirect"}, loadOnStartup = 1)
+public class eIDASSignalServlet extends ProcessEngineSignalServlet {
+
+ private static final long serialVersionUID = 8215688005533754459L;
+
+ public eIDASSignalServlet() {
+ super();
+ Logger.debug("Registering servlet " + getClass().getName() +
+ " with mappings '/eidas/sp/post' and '/eidas/sp/redirect'.");
+
+ }
+
+
+ @Override
+ /**
+ * Protocol specific implementation to get the sessionID
+ * from http request object
+ *
+ * @param request The http Servlet-Request object
+ * @return The SessionId
+ *
+ */
+ public String getMoaSessionId(HttpServletRequest request) {
+ String sessionId = super.getMoaSessionId(request);
+
+ try {
+
+ // use SAML2 relayState
+ if (sessionId == null) {
+ sessionId = StringEscapeUtils.escapeHtml(request.getParameter("RelayState"));
+ }
+
+ // take from InResponseTo attribute of SAMLResponse
+ if (sessionId == null) {
+ String base64SamlToken = request.getParameter("SAMLResponse");
+ if (base64SamlToken != null && false) {
+// byte[] samlToken = Base64Utils.decode(base64SamlToken, false);
+// Document samlResponse = parseDocument(new ByteArrayInputStream(samlToken));
+//
+// XPath xPath = XPathFactory.newInstance().newXPath();
+// SimpleNamespaceContext nsContext = new SimpleNamespaceContext();
+// nsContext.bindNamespaceUri("saml2p", "urn:oasis:names:tc:SAML:2.0:protocol");
+// xPath.setNamespaceContext(nsContext);
+// XPathExpression expression = xPath.compile("string(/saml2p:Response/@InResponseTo)");
+// sessionId = (String) expression.evaluate(samlResponse, XPathConstants.STRING);
+// sessionId = StringEscapeUtils.escapeHtml(StringUtils.trimToNull(sessionId));
+ } else {
+ Logger.warn("No parameter 'SAMLResponse'. Unable to retrieve MOA session id.");
+ }
+ }
+
+ } catch (Exception e) {
+ Logger.warn("Unable to retrieve moa session id.", e);
+ }
+
+ return sessionId;
+ }
+
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASChainingMetadataProvider.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASChainingMetadataProvider.java
new file mode 100644
index 000000000..965abcde1
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASChainingMetadataProvider.java
@@ -0,0 +1,370 @@
+package at.gv.egovernment.moa.id.auth.modules.eidas.engine;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Timer;
+
+import javax.net.ssl.SSLHandshakeException;
+import javax.xml.namespace.QName;
+
+import org.apache.commons.httpclient.MOAHttpClient;
+import org.apache.commons.httpclient.params.HttpClientParams;
+import org.opensaml.saml2.metadata.EntitiesDescriptor;
+import org.opensaml.saml2.metadata.EntityDescriptor;
+import org.opensaml.saml2.metadata.RoleDescriptor;
+import org.opensaml.saml2.metadata.provider.ChainingMetadataProvider;
+import org.opensaml.saml2.metadata.provider.HTTPMetadataProvider;
+import org.opensaml.saml2.metadata.provider.MetadataFilter;
+import org.opensaml.saml2.metadata.provider.MetadataProvider;
+import org.opensaml.saml2.metadata.provider.MetadataProviderException;
+import org.opensaml.saml2.metadata.provider.ObservableMetadataProvider;
+import org.opensaml.xml.XMLObject;
+
+import at.gv.egovernment.moa.id.auth.modules.eidas.Constants;
+import at.gv.egovernment.moa.id.commons.ex.MOAHttpProtocolSocketFactoryException;
+import at.gv.egovernment.moa.id.commons.utils.MOAHttpProtocolSocketFactory;
+import at.gv.egovernment.moa.id.config.auth.AuthConfiguration;
+import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory;
+import at.gv.egovernment.moa.id.config.auth.IGarbageCollectorProcessing;
+import at.gv.egovernment.moa.id.config.auth.MOAGarbageCollector;
+import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.filter.SchemaValidationException;
+import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.filter.SignatureValidationException;
+import at.gv.egovernment.moa.id.saml2.MetadataFilterChain;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.MiscUtil;
+import eu.eidas.auth.engine.AbstractSAMLEngine;
+
+public class MOAeIDASChainingMetadataProvider implements ObservableMetadataProvider, IGarbageCollectorProcessing {
+
+ private static MOAeIDASChainingMetadataProvider instance = null;
+ private static Object mutex = new Object();
+
+ private MetadataProvider internalProvider;
+ private Map<String, Date> lastAccess = null;
+
+
+ public static MOAeIDASChainingMetadataProvider getInstance() {
+ if (instance == null) {
+ synchronized (mutex) {
+ if (instance == null) {
+ instance = new MOAeIDASChainingMetadataProvider();
+ MOAGarbageCollector.addModulForGarbageCollection(instance);
+ }
+ }
+ }
+ return instance;
+ }
+
+
+ private MOAeIDASChainingMetadataProvider() {
+ internalProvider = new ChainingMetadataProvider();
+ lastAccess = new HashMap<String, Date>();
+
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.config.auth.IGarbageCollectorProcessing#runGarbageCollector()
+ */
+ @Override
+ public void runGarbageCollector() {
+ if (!lastAccess.isEmpty()) {
+ Date now = new Date();
+ Date expioredate = new Date(now.getTime() -
+ Constants.CONFIG_PROPS_METADATA_GARBAGE_TIMEOUT);
+ Logger.debug("Starting eIDAS Metadata garbag collection (Expioredate:"
+ + expioredate + ")");
+
+ List<String> expiredEntities = new ArrayList<String>();
+
+ Iterator<Entry<String, Date>> lastAccessInterator = lastAccess.entrySet().iterator();
+ while(lastAccessInterator.hasNext()) {
+ Entry<String, Date> element = lastAccessInterator.next();
+ if (element.getValue().before(expioredate)) {
+ Logger.debug("Remove unused eIDAS Metadate: " + element.getKey());
+ expiredEntities.add(element.getKey());
+
+ }
+ }
+
+ if (!expiredEntities.isEmpty()) {
+ ChainingMetadataProvider chainProvider = (ChainingMetadataProvider) internalProvider;
+
+ //get all actually loaded metadata providers
+ Map<String, HTTPMetadataProvider> loadedproviders = getAllActuallyLoadedProviders();
+
+ for (String expired : expiredEntities) {
+ if (loadedproviders.containsKey(expired)) {
+ HTTPMetadataProvider provider = loadedproviders.get(expired);
+
+ //destroy metadata provider
+ provider.destroy();
+
+ //remove from map
+ loadedproviders.remove(expired);
+
+ /*OpenSAML ChainingMetadataProvider can not remove a MetadataProvider (UnsupportedOperationException)
+ *The ChainingMetadataProvider use internal a unmodifiableList to hold all registrated MetadataProviders.*/
+ //chainProvider.removeMetadataProvider(provider);
+ Logger.info("Remove not used eIDAS MetadataProvider " + expired
+ + " after timeout.");
+
+ } else
+ Logger.warn("eIDAS metadata for EntityID: " + expired
+ + " is marked as unsed, but no loaded metadata provider is found.");
+
+ }
+
+ try {
+ synchronized (chainProvider) {
+ chainProvider.setProviders(new ArrayList<MetadataProvider>(loadedproviders.values()));
+
+ emitChangeEvent();
+ }
+
+ } catch (MetadataProviderException e) {
+ Logger.warn("ReInitalize eIDASA MetaDataProvider is not possible! MOA-ID Instance has to be restarted manualy", e);
+
+ }
+ }
+ }
+ }
+
+
+
+ private HTTPMetadataProvider createNewHTTPMetaDataProvider(String metadataURL) {
+ HTTPMetadataProvider httpProvider = null;
+ Timer timer= null;
+ MOAHttpClient httpClient = null;
+ try {
+ AuthConfiguration authConfig = AuthConfigurationProviderFactory.getInstance();
+
+ httpClient = new MOAHttpClient();
+
+ HttpClientParams httpClientParams = new HttpClientParams();
+ httpClientParams.setSoTimeout(Constants.CONFIG_PROPS_METADATA_SOCKED_TIMEOUT);
+ httpClient.setParams(httpClientParams);
+
+ if (metadataURL.startsWith("https:")) {
+ try {
+ MOAHttpProtocolSocketFactory protoSocketFactory = new MOAHttpProtocolSocketFactory(
+ Constants.SSLSOCKETFACTORYNAME,
+ authConfig.getCertstoreDirectory(),
+ authConfig.getTrustedCACertificates(),
+ null,
+ AuthConfiguration.DEFAULT_X509_CHAININGMODE,
+ authConfig.isTrustmanagerrevoationchecking());
+
+ httpClient.setCustomSSLTrustStore(metadataURL, protoSocketFactory);
+
+ } catch (MOAHttpProtocolSocketFactoryException e) {
+ Logger.warn("MOA SSL-TrustStore can not initialized. Use default Java TrustStore.");
+
+ }
+ }
+
+ timer = new Timer();
+ httpProvider = new HTTPMetadataProvider(timer, httpClient,
+ metadataURL);
+ httpProvider.setParserPool(AbstractSAMLEngine.getNewBasicSecuredParserPool());
+ httpProvider.setRequireValidMetadata(true);
+ httpProvider.setMinRefreshDelay(1000*60*15); //15 minutes
+ httpProvider.setMaxRefreshDelay(1000*60*60*24); //24 hours
+ //httpProvider.setRefreshDelayFactor(0.1F);
+
+ //add Metadata filters
+ MetadataFilterChain filter = new MetadataFilterChain();
+ filter.addFilter(new MOAeIDASMetadataSignatureFilter(
+ authConfig.getBasicMOAIDConfiguration(Constants.CONIG_PROPS_EIDAS_METADATA_VALIDATION_TRUSTSTORE)));
+ httpProvider.setMetadataFilter(filter);
+
+ httpProvider.initialize();
+
+ return httpProvider;
+
+ } catch (Throwable e) {
+ if (e.getCause() != null && e.getCause().getCause() instanceof SSLHandshakeException) {
+ Logger.warn("SSL-Server certificate for metadata "
+ + metadataURL + " not trusted.", e);
+
+ } if (e.getCause() != null && e.getCause().getCause() instanceof SignatureValidationException) {
+ Logger.warn("Signature verification for metadata"
+ + metadataURL + " FAILED.", e);
+
+ } if (e.getCause() != null && e.getCause().getCause() instanceof SchemaValidationException) {
+ Logger.warn("Schema validation for metadata "
+ + metadataURL + " FAILED.", e);
+ }
+
+ Logger.error(
+ "Failed to add Metadata file for "
+ + metadataURL + "[ "
+ + e.getMessage() + " ]", e);
+
+ if (httpProvider != null) {
+ Logger.debug("Destroy failed Metadata provider");
+ httpProvider.destroy();
+ }
+
+ if (timer != null) {
+ Logger.debug("Destroy Timer.");
+ timer.cancel();
+ }
+
+
+ }
+
+ return null;
+ }
+
+ private Map<String, HTTPMetadataProvider> getAllActuallyLoadedProviders() {
+ Map<String, HTTPMetadataProvider> loadedproviders = new HashMap<String, HTTPMetadataProvider>();
+ ChainingMetadataProvider chainProvider = (ChainingMetadataProvider) internalProvider;
+
+ //make a Map of all actually loaded HTTPMetadataProvider
+ List<MetadataProvider> providers = chainProvider.getProviders();
+ for (MetadataProvider provider : providers) {
+ if (provider instanceof HTTPMetadataProvider) {
+ HTTPMetadataProvider httpprovider = (HTTPMetadataProvider) provider;
+ loadedproviders.put(httpprovider.getMetadataURI(), httpprovider);
+
+ }
+ }
+
+ return loadedproviders;
+ }
+
+ public boolean refreshMetadataProvider(String metadataURL) {
+ try {
+ if (MiscUtil.isNotEmpty(metadataURL)) {
+ Map<String, HTTPMetadataProvider> actuallyLoadedProviders = getAllActuallyLoadedProviders();
+
+ // check if MetadataProvider is actually loaded
+ if (actuallyLoadedProviders.containsKey(metadataURL)) {
+ actuallyLoadedProviders.get(metadataURL).refresh();
+ Logger.info("eIDAS metadata for "
+ + metadataURL + " is refreshed.");
+ return true;
+
+ } else {
+ //load new Metadata Provider
+ ChainingMetadataProvider chainProvider = (ChainingMetadataProvider) internalProvider;
+ HTTPMetadataProvider newMetadataProvider = createNewHTTPMetaDataProvider(metadataURL);
+ chainProvider.addMetadataProvider(newMetadataProvider);
+
+ emitChangeEvent();
+ Logger.info("eIDAS metadata for "
+ + metadataURL + " is added.");
+ return true;
+
+ }
+
+ } else
+ Logger.debug("Can not refresh eIDAS metadata: NO eIDAS metadata URL.");
+
+ } catch (MetadataProviderException e) {
+ Logger.warn("Refresh eIDAS metadata for "
+ + metadataURL + " FAILED.", e);
+
+ }
+
+ return false;
+
+ }
+
+
+ public boolean requireValidMetadata() {
+ return internalProvider.requireValidMetadata();
+ }
+
+ public void setRequireValidMetadata(boolean requireValidMetadata) {
+ internalProvider.setRequireValidMetadata(requireValidMetadata);
+ }
+
+ public MetadataFilter getMetadataFilter() {
+ return internalProvider.getMetadataFilter();
+ }
+
+ public void setMetadataFilter(MetadataFilter newFilter)
+ throws MetadataProviderException {
+ internalProvider.setMetadataFilter(newFilter);
+ }
+
+ public XMLObject getMetadata() throws MetadataProviderException {
+ return internalProvider.getMetadata();
+ }
+
+ public EntitiesDescriptor getEntitiesDescriptor(String entitiesID)
+ throws MetadataProviderException {
+ Logger.warn("eIDAS metadata not support 'EntitiesDescriptor' elements!");
+ return null;
+
+ }
+
+ public EntityDescriptor getEntityDescriptor(String entityID)
+ throws MetadataProviderException {
+ EntityDescriptor entityDesc = null;
+ try {
+ entityDesc = internalProvider.getEntityDescriptor(entityID);
+ if (entityDesc == null) {
+ Logger.debug("Can not find eIDAS metadata for entityID: " + entityID
+ + " Start refreshing process ...");
+ if (refreshMetadataProvider(entityID))
+ entityDesc = internalProvider.getEntityDescriptor(entityID);
+
+ } else {
+ if (!entityDesc.isValid())
+ if (refreshMetadataProvider(entityID))
+ entityDesc = internalProvider.getEntityDescriptor(entityID);
+
+ }
+
+
+ } catch (MetadataProviderException e) {
+ Logger.debug("Can not find eIDAS metadata for entityID: " + entityID
+ + " Start refreshing process ...");
+ if (refreshMetadataProvider(entityID))
+ entityDesc = internalProvider.getEntityDescriptor(entityID);
+
+ }
+
+ if (entityDesc != null)
+ lastAccess.put(entityID, new Date());
+
+ return entityDesc;
+ }
+
+ public List<RoleDescriptor> getRole(String entityID, QName roleName)
+ throws MetadataProviderException {
+ return internalProvider.getRole(entityID, roleName);
+ }
+
+ public RoleDescriptor getRole(String entityID, QName roleName,
+ String supportedProtocol) throws MetadataProviderException {
+ return internalProvider.getRole(entityID, roleName, supportedProtocol);
+ }
+
+ /* (non-Javadoc)
+ * @see org.opensaml.saml2.metadata.provider.ObservableMetadataProvider#getObservers()
+ */
+ @Override
+ public List<Observer> getObservers() {
+ return ((ChainingMetadataProvider) internalProvider).getObservers();
+ }
+
+ protected void emitChangeEvent() {
+ if ((getObservers() == null) || (getObservers().size() == 0)) {
+ return;
+ }
+
+ List<Observer> tempObserverList = new ArrayList<Observer>(getObservers());
+ for (ObservableMetadataProvider.Observer observer : tempObserverList)
+ if (observer != null)
+ observer.onEvent(this);
+ }
+
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASMetadataProviderDecorator.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASMetadataProviderDecorator.java
new file mode 100644
index 000000000..e3ae5c046
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASMetadataProviderDecorator.java
@@ -0,0 +1,120 @@
+/*
+ * 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.engine;
+
+import java.security.KeyStore;
+
+import org.opensaml.saml2.metadata.EntityDescriptor;
+import org.opensaml.saml2.metadata.IDPSSODescriptor;
+import org.opensaml.saml2.metadata.RoleDescriptor;
+import org.opensaml.saml2.metadata.SPSSODescriptor;
+import org.opensaml.saml2.metadata.provider.MetadataProvider;
+import org.opensaml.saml2.metadata.provider.MetadataProviderException;
+
+import eu.eidas.auth.engine.EIDASSAMLEngine;
+import eu.eidas.auth.engine.metadata.MetadataProcessorI;
+import eu.eidas.engine.exceptions.SAMLEngineException;
+
+/**
+ * @author tlenz
+ *
+ */
+public class MOAeIDASMetadataProviderDecorator implements MetadataProcessorI {
+
+ private MetadataProvider metadataprovider = null;
+
+ /**
+ *
+ */
+ public MOAeIDASMetadataProviderDecorator(MetadataProvider metadataprovider) {
+ this.metadataprovider = metadataprovider;
+
+ }
+
+ /* (non-Javadoc)
+ * @see eu.eidas.auth.engine.metadata.MetadataProcessorI#getEntityDescriptor(java.lang.String)
+ */
+ @Override
+ public EntityDescriptor getEntityDescriptor(String url)
+ throws SAMLEngineException {
+ try {
+ return this.metadataprovider.getEntityDescriptor(url);
+
+ } catch (MetadataProviderException e) {
+ throw new SAMLEngineException("eIDAS Metadata processing FAILED.", e);
+
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see eu.eidas.auth.engine.metadata.MetadataProcessorI#getSPSSODescriptor(java.lang.String)
+ */
+ @Override
+ public SPSSODescriptor getSPSSODescriptor(String url)
+ throws SAMLEngineException {
+ return getFirstRoleDescriptor(getEntityDescriptor(url), SPSSODescriptor.class);
+
+ }
+
+ /* (non-Javadoc)
+ * @see eu.eidas.auth.engine.metadata.MetadataProcessorI#getIDPSSODescriptor(java.lang.String)
+ */
+ @Override
+ public IDPSSODescriptor getIDPSSODescriptor(String url)
+ throws SAMLEngineException {
+ return getFirstRoleDescriptor(getEntityDescriptor(url), IDPSSODescriptor.class);
+
+ }
+
+ /* (non-Javadoc)
+ * @see eu.eidas.auth.engine.metadata.MetadataProcessorI#checkValidMetadataSignature(java.lang.String, eu.eidas.auth.engine.EIDASSAMLEngine)
+ */
+ @Override
+ public void checkValidMetadataSignature(String url, EIDASSAMLEngine engine)
+ throws SAMLEngineException {
+ //Do nothing, because metadata signature is already validated during
+ //metadata provider initialization
+
+ }
+
+ /* (non-Javadoc)
+ * @see eu.eidas.auth.engine.metadata.MetadataProcessorI#checkValidMetadataSignature(java.lang.String, java.security.KeyStore)
+ */
+ @Override
+ public void checkValidMetadataSignature(String url, KeyStore trustStore)
+ throws SAMLEngineException {
+ //Do nothing, because metadata signature is already validated during
+ //metadata provider initialization
+
+ }
+
+ protected <T extends RoleDescriptor> T getFirstRoleDescriptor(EntityDescriptor entityDescriptor, final Class<T> clazz){
+ for(RoleDescriptor rd:entityDescriptor.getRoleDescriptors()){
+ if(clazz.isInstance(rd)){
+ return (T)rd;
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASMetadataSignatureFilter.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASMetadataSignatureFilter.java
new file mode 100644
index 000000000..c9f3e5bcd
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASMetadataSignatureFilter.java
@@ -0,0 +1,132 @@
+/*
+ * 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.engine;
+
+import java.io.IOException;
+import java.io.StringWriter;
+
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.opensaml.saml2.metadata.EntityDescriptor;
+import org.opensaml.saml2.metadata.provider.FilterException;
+import org.opensaml.saml2.metadata.provider.MetadataFilter;
+import org.opensaml.xml.XMLObject;
+
+import at.gv.egovernment.moa.id.auth.builder.SignatureVerificationUtils;
+import at.gv.egovernment.moa.id.auth.data.VerifyXMLSignatureResponse;
+import at.gv.egovernment.moa.id.auth.exception.BuildException;
+import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
+import at.gv.egovernment.moa.logging.Logger;
+
+/**
+ * @author tlenz
+ *
+ */
+public class MOAeIDASMetadataSignatureFilter implements MetadataFilter {
+
+ private String trustProfileID = null;
+
+ /**
+ *
+ */
+ public MOAeIDASMetadataSignatureFilter(String trustProfileID) {
+ this.trustProfileID = trustProfileID;
+
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.opensaml.saml2.metadata.provider.MetadataFilter#doFilter(org.opensaml.xml.XMLObject)
+ */
+ @Override
+ public void doFilter(XMLObject metadata) throws FilterException {
+ if (metadata instanceof EntityDescriptor) {
+ if (((EntityDescriptor) metadata).isSigned()) {
+ EntityDescriptor entityDes = (EntityDescriptor) metadata;
+ //check signature;
+ try {
+ Transformer transformer = TransformerFactory.newInstance()
+ .newTransformer();
+ StringWriter sw = new StringWriter();
+ StreamResult sr = new StreamResult(sw);
+ DOMSource source = new DOMSource(metadata.getDOM());
+ transformer.transform(source, sr);
+ sw.close();
+ String metadataXML = sw.toString();
+
+ SignatureVerificationUtils sigVerify =
+ new SignatureVerificationUtils();
+ VerifyXMLSignatureResponse result = sigVerify.verify(
+ metadataXML.getBytes(), trustProfileID);
+
+ //check signature-verification result
+ if (result.getSignatureCheckCode() != 0) {
+ Logger.warn("eIDAS Metadata signature-verification FAILED!"
+ + " Metadata: " + entityDes.getEntityID()
+ + " StatusCode:" + result.getSignatureCheckCode());
+ throw new FilterException("eIDAS Metadata signature-verification FAILED!"
+ + " Metadata: " + entityDes.getEntityID()
+ + " StatusCode:" + result.getSignatureCheckCode());
+
+ }
+
+ if (result.getCertificateCheckCode() != 0) {
+ Logger.warn("eIDAS Metadata certificate-verification FAILED!"
+ + " Metadata: " + entityDes.getEntityID()
+ + " StatusCode:" + result.getCertificateCheckCode());
+ throw new FilterException("eIDAS Metadata certificate-verification FAILED!"
+ + " Metadata: " + entityDes.getEntityID()
+ + " StatusCode:" + result.getCertificateCheckCode());
+
+ }
+
+
+ } catch (MOAIDException | TransformerFactoryConfigurationError | TransformerException | IOException e) {
+ Logger.error("eIDAS Metadata verification has an interal error.", e);
+ throw new FilterException("eIDAS Metadata verification has an interal error."
+ + " Message:" + e.getMessage());
+
+ }
+
+
+ } else {
+ Logger.warn("eIDAS Metadata root-element MUST be signed.");
+ throw new FilterException("eIDAS Metadata root-element MUST be signed.'");
+
+ }
+
+ } else {
+ Logger.warn("eIDAS Metadata root-element is not of type 'EntityDescriptor'");
+ throw new FilterException("eIDAS Metadata root-element is not of type 'EntityDescriptor'");
+
+ }
+
+ }
+
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/EIDASEngineConfigurationException.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/EIDASEngineConfigurationException.java
new file mode 100644
index 000000000..98bc559d2
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/EIDASEngineConfigurationException.java
@@ -0,0 +1,60 @@
+/*
+ * 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.exceptions;
+
+import at.gv.egovernment.moa.id.config.ConfigurationException;
+
+/**
+ * @author tlenz
+ *
+ */
+public class EIDASEngineConfigurationException extends ConfigurationException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * @param messageId
+ * @param parameters
+ * @param wrapped
+ */
+ public EIDASEngineConfigurationException(String messageId,
+ Object[] parameters, Throwable wrapped) {
+ super(messageId, parameters, wrapped);
+ }
+
+ /**
+ * @param string
+ * @param object
+ */
+ public EIDASEngineConfigurationException(String string, Object[] object) {
+ super(string, object);
+ }
+
+
+
+
+
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/EIDASEngineException.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/EIDASEngineException.java
new file mode 100644
index 000000000..95690bbeb
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/EIDASEngineException.java
@@ -0,0 +1,45 @@
+/*
+ * 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.exceptions;
+
+
+/**
+ * @author tlenz
+ *
+ */
+public class EIDASEngineException extends Exception {
+
+ /**
+ * @param string
+ * @param e
+ */
+ public EIDASEngineException(String string, Throwable e) {
+ super(string, e);
+ }
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1559812927427153879L;
+
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/eIDASAttributeException.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/eIDASAttributeException.java
new file mode 100644
index 000000000..7840ae2e6
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/exceptions/eIDASAttributeException.java
@@ -0,0 +1,38 @@
+/*
+ * 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.exceptions;
+
+/**
+ * @author tlenz
+ *
+ */
+public class eIDASAttributeException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ public eIDASAttributeException(String message) {
+ super(message);
+
+ }
+
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/CreateIdentityLinkTask.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/CreateIdentityLinkTask.java
new file mode 100644
index 000000000..f4d6c4ad4
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/CreateIdentityLinkTask.java
@@ -0,0 +1,185 @@
+/*
+ * 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.tasks;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
+
+import eu.eidas.auth.commons.IPersonalAttributeList;
+
+import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants;
+import at.gv.egovernment.moa.id.advancedlogging.MOAReversionLogger;
+import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants;
+import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
+import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionStorageConstants;
+import at.gv.egovernment.moa.id.auth.data.IdentityLink;
+import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
+import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask;
+import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException;
+import at.gv.egovernment.moa.id.auth.modules.eidas.Constants;
+import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.eIDASAttributeException;
+import at.gv.egovernment.moa.id.auth.parser.IdentityLinkAssertionParser;
+import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
+import at.gv.egovernment.moa.id.config.auth.AuthConfiguration;
+import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory;
+import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters;
+import at.gv.egovernment.moa.id.moduls.IRequest;
+import at.gv.egovernment.moa.id.moduls.RequestStorage;
+import at.gv.egovernment.moa.id.process.api.ExecutionContext;
+import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
+import at.gv.egovernment.moa.id.util.IdentityLinkReSigner;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.DOMUtils;
+import at.gv.egovernment.moa.util.XPathUtils;
+
+/**
+ * @author tlenz
+ *
+ */
+public class CreateIdentityLinkTask extends AbstractAuthServletTask {
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.process.springweb.MoaIdTask#execute(at.gv.egovernment.moa.id.process.api.ExecutionContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+ */
+ @Override
+ public void execute(ExecutionContext executionContext,
+ HttpServletRequest request, HttpServletResponse response)
+ throws TaskExecutionException {
+ try{
+ String moasessionid = (String) executionContext.get(MOAIDAuthConstants.PARAM_SESSIONID);
+ String pendingRequestID = (String) executionContext.get("pendingRequestID");
+
+ //load pending request
+ IRequest pendingReq = RequestStorage.getPendingRequest(pendingRequestID);
+ if (pendingReq == null) {
+ Logger.info("No PendingRequest with Id: " + pendingRequestID + " Maybe, a transaction timeout occure.");
+ throw new MOAIDException("auth.28", new Object[]{pendingRequestID});
+
+ }
+
+ //load MOASession object and OA-configuration
+ AuthenticationSession moasession = AuthenticationSessionStoreage.getSession(moasessionid);
+ IOAAuthParameters oaConfig = pendingReq.getOnlineApplicationConfiguration();
+
+ //get eIDAS attributes from MOA-Session
+ IPersonalAttributeList eIDASAttributes = moasession.getGenericDataFromSession(
+ AuthenticationSessionStorageConstants.eIDAS_ATTRIBUTELIST,
+ IPersonalAttributeList.class);
+
+ AuthConfiguration config = AuthConfigurationProviderFactory.getInstance();
+ IdentityLink identityLink = null;
+
+ //connect SZR-Gateway
+ //TODO: implement SZR-Gateway communication!!!!
+ if(true) {
+
+ // create fake IdL
+ // - fetch IdL template from resources
+ InputStream s = CreateIdentityLinkTask.class.getResourceAsStream("/resources/xmldata/fakeIdL_IdL_template.xml");
+ Element idlTemplate = DOMUtils.parseXmlValidating(s);
+
+ identityLink = new IdentityLinkAssertionParser(idlTemplate).parseIdentityLink();
+
+ // replace data
+ Element idlassertion = identityLink.getSamlAssertion();
+
+ // - set bpk/wpbk;
+ Node prIdentification = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_IDENT_VALUE_XPATH);
+ if(!eIDASAttributes.containsKey(Constants.eIDAS_ATTR_PERSONALIDENTIFIER))
+ throw new eIDASAttributeException("PersonalIdentifier is missing");
+ String eIdentifier = eIDASAttributes.get(Constants.eIDAS_ATTR_PERSONALIDENTIFIER).getValue().get(0);
+ prIdentification.getFirstChild().setNodeValue(eIdentifier);
+
+ // - set last name
+ Node prFamilyName = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_FAMILY_NAME_XPATH);
+ if(!eIDASAttributes.containsKey(Constants.eIDAS_ATTR_CURRENTFAMILYNAME))
+ throw new eIDASAttributeException("currentFamilyName is missing");
+ String familyName = eIDASAttributes.get(Constants.eIDAS_ATTR_CURRENTFAMILYNAME).getValue().get(0);
+ prFamilyName.getFirstChild().setNodeValue(familyName);
+
+ // - set first name
+ Node prGivenName = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_GIVEN_NAME_XPATH);
+ if(!eIDASAttributes.containsKey(Constants.eIDAS_ATTR_CURRENTGIVENNAME))
+ throw new eIDASAttributeException("currentGivenName is missing");
+ String givenName = eIDASAttributes.get(Constants.eIDAS_ATTR_CURRENTGIVENNAME).getValue().get(0);
+ prGivenName.getFirstChild().setNodeValue(givenName);
+
+ // - set date of birth
+ Node prDateOfBirth = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_DATE_OF_BIRTH_XPATH);
+ if(!eIDASAttributes.containsKey(Constants.eIDAS_ATTR_DATEOFBIRTH))
+ throw new eIDASAttributeException("dateOfBirth is missing");
+ String dateOfBirth = eIDASAttributes.get(Constants.eIDAS_ATTR_DATEOFBIRTH).getValue().get(0);
+ dateOfBirth = new SimpleDateFormat("yyyy-MM-dd").format(new SimpleDateFormat("yyyyMMdd").parse(dateOfBirth));
+ prDateOfBirth.getFirstChild().setNodeValue(dateOfBirth);
+
+ identityLink = new IdentityLinkAssertionParser(idlassertion).parseIdentityLink();
+
+ //resign IDL
+ IdentityLinkReSigner identitylinkresigner = IdentityLinkReSigner.getInstance();
+ Element resignedilAssertion = identitylinkresigner.resignIdentityLink(identityLink.getSamlAssertion(), config.getStorkFakeIdLResigningKey());
+ identityLink = new IdentityLinkAssertionParser(resignedilAssertion).parseIdentityLink();
+
+ } else {
+ //contact SZR Gateway
+ Logger.debug("Starting connecting SZR Gateway");
+
+ //TODO:!!!!!!
+
+ }
+
+ Logger.debug("SZR communication was successfull");
+
+ if (identityLink == null) {
+ Logger.error("SZR Gateway did not return an identity link.");
+ throw new MOAIDException("stork.10", null);
+ }
+
+ MOAReversionLogger.getInstance().logEvent(pendingReq, MOAIDEventConstants.AUTHPROCESS_PEPS_IDL_RECEIVED);
+ moasession.setForeigner(true);
+ moasession.setIdentityLink(identityLink);
+ moasession.setBkuURL("Not applicable (eIDASAuthentication)");
+
+ //store MOA-session to database
+ AuthenticationSessionStoreage.storeSession(moasession);
+
+ } catch (ParseException | MOAIDException | MOADatabaseException | ParserConfigurationException | SAXException | IOException e) {
+ throw new TaskExecutionException("IdentityLink generation for foreign person FAILED.", e);
+
+ } catch (eIDASAttributeException e) {
+ throw new TaskExecutionException("Minimum required eIDAS attributeset not found.", e);
+
+ }
+
+ }
+
+}
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
new file mode 100644
index 000000000..06643ec53
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/GenerateAuthnRequestTask.java
@@ -0,0 +1,210 @@
+/*
+ * 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.tasks;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.Collection;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang3.BooleanUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+
+import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants;
+import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
+import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
+import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
+import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask;
+import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException;
+import at.gv.egovernment.moa.id.auth.modules.eidas.Constants;
+import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASEngineException;
+import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils;
+import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
+import at.gv.egovernment.moa.id.config.auth.AuthConfiguration;
+import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory;
+import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters;
+import at.gv.egovernment.moa.id.config.stork.CPEPS;
+import at.gv.egovernment.moa.id.config.stork.StorkAttribute;
+import at.gv.egovernment.moa.id.moduls.IRequest;
+import at.gv.egovernment.moa.id.moduls.RequestStorage;
+import at.gv.egovernment.moa.id.process.api.ExecutionContext;
+import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
+import at.gv.egovernment.moa.id.util.VelocityProvider;
+import at.gv.egovernment.moa.logging.Logger;
+import eu.eidas.auth.commons.EIDASAuthnRequest;
+import eu.eidas.auth.commons.EIDASUtil;
+import eu.eidas.auth.commons.EidasLoaCompareType;
+import eu.eidas.auth.commons.EidasLoaLevels;
+import eu.eidas.auth.commons.IPersonalAttributeList;
+import eu.eidas.auth.commons.PersonalAttribute;
+import eu.eidas.auth.commons.PersonalAttributeList;
+import eu.eidas.auth.engine.EIDASSAMLEngine;
+import eu.eidas.auth.engine.core.eidas.SPType;
+import eu.eidas.engine.exceptions.EIDASSAMLEngineException;
+
+/**
+ * @author tlenz
+ *
+ */
+public class GenerateAuthnRequestTask extends AbstractAuthServletTask {
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.process.springweb.MoaIdTask#execute(at.gv.egovernment.moa.id.process.api.ExecutionContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+ */
+ @Override
+ public void execute(ExecutionContext executionContext,
+ HttpServletRequest request, HttpServletResponse response)
+ throws TaskExecutionException {
+
+ try{
+ String moasessionid = (String) executionContext.get(MOAIDAuthConstants.PARAM_SESSIONID);
+ String pendingRequestID = (String) executionContext.get("pendingRequestID");
+
+ //load pending request
+ IRequest pendingReq = RequestStorage.getPendingRequest(pendingRequestID);
+ if (pendingReq == null) {
+ Logger.info("No PendingRequest with Id: '{}' Maybe, a transaction timeout occure.", new Object[] {pendingRequestID});
+ throw new MOAIDException("auth.28", new Object[]{pendingRequestID});
+
+ }
+
+ //load MOASession object, configuration and OA-configuration
+ AuthenticationSession moasession = AuthenticationSessionStoreage.getSession(moasessionid);
+ IOAAuthParameters oaConfig = pendingReq.getOnlineApplicationConfiguration();
+ AuthConfiguration moaconfig = AuthConfigurationProviderFactory.getInstance();
+
+ // get target country
+ String citizenCountryCode = (String) executionContext.get(MOAIDAuthConstants.PARAM_CCC);
+
+ if (StringUtils.isEmpty(citizenCountryCode)) {
+ // illegal state; task should not have been executed without a selected country
+ throw new AuthenticationException("stork.22", new Object[] { moasessionid });
+ }
+
+ CPEPS cpeps = moaconfig.getStorkConfig().getCPEPS(citizenCountryCode);
+ if(null == cpeps) {
+ Logger.error("PEPS unknown for country", new Object[] {citizenCountryCode});
+ throw new AuthenticationException("Unknown PEPS for citizen country '{}'", new Object[] {citizenCountryCode});
+ }
+ Logger.debug("Found eIDaS Node/C-PEPS configuration for citizen of country: " + citizenCountryCode);
+ String destination = cpeps.getPepsURL().toString().split(";")[1].trim(); // FIXME convenience for metadata url and assertion destination
+ String metadataUrl = cpeps.getPepsURL().toString().split(";")[0].trim();
+
+ // assemble requested attributes
+ Collection<StorkAttribute> attributesFromConfig = oaConfig.getRequestedSTORKAttributes();
+
+ // - prepare attribute list
+ IPersonalAttributeList pAttList = new PersonalAttributeList();
+
+ // - fill container
+ for (StorkAttribute current : attributesFromConfig) {
+ PersonalAttribute newAttribute = new PersonalAttribute();
+ newAttribute.setName(current.getName());
+
+ boolean globallyMandatory = false;
+ for (StorkAttribute currentGlobalAttribute : moaconfig.getStorkConfig().getStorkAttributes())
+ if (current.getName().equals(currentGlobalAttribute.getName())) {
+ globallyMandatory = BooleanUtils.isTrue(currentGlobalAttribute.getMandatory());
+ break;
+ }
+
+ newAttribute.setIsRequired(current.getMandatory() || globallyMandatory);
+ pAttList.add(newAttribute);
+ }
+
+ EIDASSAMLEngine engine = SAMLEngineUtils.createSAMLEngine();
+
+ //build eIDAS AuthnRequest
+ EIDASAuthnRequest authnRequest = new EIDASAuthnRequest();
+ authnRequest.setProviderName(pendingReq.getAuthURL());
+ authnRequest.setPersonalAttributeList(pAttList);
+
+ authnRequest.setIssuer(moaconfig.getPublicURLPrefix() + Constants.eIDAS_HTTP_ENDPOINT_METADATA);
+
+ authnRequest.setDestination(destination);
+ authnRequest.setEidasNameidFormat(EIDASAuthnRequest.NAMEID_FORMAT_UNSPECIFIED);
+ authnRequest.setEidasLoA(EidasLoaLevels.LOW.stringValue());
+ authnRequest.setEidasLoACompareType(EidasLoaCompareType.MINIMUM.stringValue());
+ authnRequest.setSPType(SPType.DEFAULT_VALUE);
+
+ engine.initRequestedAttributes(pAttList);
+ authnRequest = engine.generateEIDASAuthnRequest(authnRequest);
+
+ //encode AuthnRequest
+ byte[] token = authnRequest.getTokenSaml();
+ String SAMLRequest = EIDASUtil.encodeSAMLToken(token);
+
+
+ //send
+ try {
+ VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine();
+ Template template = velocityEngine.getTemplate("/resources/templates/eidas_postbinding_template.vm");
+ VelocityContext context = new VelocityContext();
+
+ String actionType = "SAMLRequest";
+ context.put(actionType, SAMLRequest);
+ Logger.debug("Encoded " + actionType + " original: " + SAMLRequest);
+
+ context.put("RelayState", moasessionid);
+
+ Logger.debug("Using assertion consumer url as action: " + destination);
+ context.put("action", destination);
+
+ Logger.debug("Starting template merge");
+ StringWriter writer = new StringWriter();
+
+ Logger.debug("Doing template merge");
+ template.merge(context, writer);
+ Logger.debug("Template merge done");
+
+ Logger.debug("Sending html content: " + writer.getBuffer().toString());
+
+ response.setContentType("text/html;charset=UTF-8");
+ response.getOutputStream().write(writer.getBuffer().toString().getBytes("UTF-8"));
+
+ } catch (IOException e) {
+ Logger.error("Velocity IO error: " + e.getMessage());
+ throw new MOAIDException("stork.15", null); // TODO
+ } catch (Exception e) {
+ Logger.error("Velocity general error: " + e.getMessage());
+ throw new MOAIDException("stork.15", null); // TODO
+ }
+
+ }catch (EIDASSAMLEngineException e){
+ Logger.error("eIDAS AuthnRequest generation FAILED.", e);
+ throw new TaskExecutionException("eIDAS AuthnRequest generation FAILED.",
+ new EIDASEngineException("Could not generate token for Saml Request", e));
+
+ } catch (EIDASEngineException | MOAIDException | MOADatabaseException e) {
+ throw new TaskExecutionException("eIDAS AuthnRequest generation FAILED.", e);
+
+ }
+
+ }
+
+}
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
new file mode 100644
index 000000000..693807d63
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java
@@ -0,0 +1,109 @@
+package at.gv.egovernment.moa.id.auth.modules.eidas.tasks;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import eu.eidas.auth.commons.EIDASAuthnResponse;
+import eu.eidas.auth.commons.EIDASUtil;
+import eu.eidas.auth.engine.EIDASSAMLEngine;
+import eu.eidas.engine.exceptions.EIDASSAMLEngineException;
+
+import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants;
+import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
+import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionStorageConstants;
+import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
+import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask;
+import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException;
+import at.gv.egovernment.moa.id.auth.modules.eidas.Constants;
+import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASEngineException;
+import at.gv.egovernment.moa.id.auth.modules.eidas.utils.MOAPersonalAttributeList;
+import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils;
+import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
+import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory;
+import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters;
+import at.gv.egovernment.moa.id.moduls.IRequest;
+import at.gv.egovernment.moa.id.moduls.RequestStorage;
+import at.gv.egovernment.moa.id.process.api.ExecutionContext;
+import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.MiscUtil;
+
+public class ReceiveAuthnResponseTask extends AbstractAuthServletTask {
+
+ @Override
+ public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) throws TaskExecutionException {
+
+ try{
+ String moasessionid = (String) executionContext.get(MOAIDAuthConstants.PARAM_SESSIONID);
+ String pendingRequestID = (String) executionContext.get("pendingRequestID");
+
+ //load pending request
+ IRequest pendingReq = RequestStorage.getPendingRequest(pendingRequestID);
+ if (pendingReq == null) {
+ Logger.info("No PendingRequest with Id: " + pendingRequestID + " Maybe, a transaction timeout occure.");
+ throw new MOAIDException("auth.28", new Object[]{pendingRequestID});
+
+ }
+
+ //load MOASession object and OA-configuration
+ AuthenticationSession moasession = AuthenticationSessionStoreage.getSession(moasessionid);
+ IOAAuthParameters oaConfig = pendingReq.getOnlineApplicationConfiguration();
+
+ //get SAML Response and decode it
+ String base64SamlToken = request.getParameter("SAMLResponse");
+ if (MiscUtil.isEmpty(base64SamlToken)) {
+ Logger.warn("No eIDAS SAMLReponse found in http request.");
+ throw new MOAIDException("HTTP request includes no eIDAS SAML-Response element.", null);
+
+ }
+ byte[] decSamlToken = EIDASUtil.decodeSAMLToken(base64SamlToken);
+
+ //get eIDAS SAML-engine
+ EIDASSAMLEngine engine = SAMLEngineUtils.createSAMLEngine();
+
+ //validate SAML token
+ EIDASAuthnResponse samlResp = engine.validateEIDASAuthnResponse(decSamlToken,
+ request.getRemoteHost(), Constants.CONFIG_PROPS_SKEWTIME);
+
+ boolean encryptedResponse=engine.isEncryptedSamlResponse(decSamlToken);
+ if (encryptedResponse) {
+ Logger.info("Received encrypted eIDAS SAML-Response.");
+ //TODO: check if additional decryption operation is required
+
+ }
+
+ //MOA-ID specific response validation
+ //TODO: implement MOA-ID specific response validation
+
+ //update MOA-Session data with received information
+ Logger.debug("Store eIDAS response information into MOA-session.");
+ moasession.setQAALevel(samlResp.getAssuranceLevel());
+ moasession.setCcc(samlResp.getCountry());
+
+ moasession.setGenericDataToSession(
+ AuthenticationSessionStorageConstants.eIDAS_ATTRIBUTELIST,
+ new MOAPersonalAttributeList(samlResp.getPersonalAttributeList()));
+
+ moasession.setGenericDataToSession(
+ AuthenticationSessionStorageConstants.eIDAS_RESPONSE,
+ decSamlToken);
+
+ //set general information to MOA-Session
+ moasession.setAuthURL(AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix() + "/");
+
+ //store MOA-session to database
+ AuthenticationSessionStoreage.storeSession(moasession);
+
+ }catch (EIDASSAMLEngineException e) {
+ Logger.error("eIDAS AuthnRequest generation FAILED.", e);
+ throw new TaskExecutionException("eIDAS Response processing FAILED.",
+ new EIDASEngineException("Could not validate eIDAS response", e));
+
+ } catch (EIDASEngineException | MOAIDException | MOADatabaseException e) {
+ throw new TaskExecutionException("eIDAS Response processing FAILED.", e);
+
+ }
+
+ }
+
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAOrderedAttributeIterator.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAOrderedAttributeIterator.java
new file mode 100644
index 000000000..573163af0
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAOrderedAttributeIterator.java
@@ -0,0 +1,66 @@
+/*
+ * 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.Iterator;
+import java.util.NoSuchElementException;
+
+import at.gv.egovernment.moa.logging.Logger;
+
+import eu.eidas.auth.commons.PersonalAttribute;
+import eu.eidas.auth.commons.PersonalAttributeList;
+
+
+/**
+ * @author tlenz
+ *
+ */
+public class MOAOrderedAttributeIterator implements Iterator<PersonalAttribute> {
+
+ private MOAPersonalAttributeList pal;
+ private Iterator<String> keyIterator;
+
+ public MOAOrderedAttributeIterator(MOAPersonalAttributeList palArg) {
+ this.pal = palArg;
+ keyIterator = palArg.getInsertOrder().iterator();
+ }
+
+ @Override
+ public boolean hasNext() {
+ return keyIterator.hasNext();
+ }
+
+ @Override
+ public PersonalAttribute next() {
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
+ return pal.get(keyIterator.next());
+ }
+
+ @Override
+ public void remove() {
+ Logger.error("Not implemented");
+ }
+
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAPersonalAttributeList.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAPersonalAttributeList.java
new file mode 100644
index 000000000..5cc100b70
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAPersonalAttributeList.java
@@ -0,0 +1,343 @@
+/*
+ * 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.io.IOException;
+import java.io.ObjectInputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.commons.lang.StringUtils;
+
+import at.gv.egovernment.moa.logging.Logger;
+
+import eu.eidas.auth.commons.AttributeConstants;
+import eu.eidas.auth.commons.AttributeUtil;
+import eu.eidas.auth.commons.EIDASErrors;
+import eu.eidas.auth.commons.EIDASParameters;
+import eu.eidas.auth.commons.EIDASUtil;
+import eu.eidas.auth.commons.EIDASValues;
+import eu.eidas.auth.commons.IPersonalAttributeList;
+import eu.eidas.auth.commons.PersonalAttribute;
+import eu.eidas.auth.commons.exceptions.InternalErrorEIDASException;
+
+/**
+ * @author tlenz
+ *
+ */
+public final class MOAPersonalAttributeList extends
+ ConcurrentHashMap<String, PersonalAttribute> implements IPersonalAttributeList {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -4488124133022713089L;
+
+ public MOAPersonalAttributeList(IPersonalAttributeList eIDASAttributeList) {
+ super();
+ Iterator<PersonalAttribute> element = eIDASAttributeList.iterator();
+ while(element.hasNext())
+ add(element.next());
+
+ }
+
+ /**
+ * Hash with the latest fetched attribute name alias.
+ */
+ private Map<String, Integer> latestAttrAlias =
+ new HashMap<String, Integer>();
+
+ /**
+ * Hash with mapping number of alias or the attribute name.
+ */
+ private Map<String, Integer> attrAliasNumber =
+ new HashMap<String, Integer>();
+ private List<String> insertOrder = new ArrayList<String>();
+
+ /**
+ * Obtain the insertOrder Collection
+ *
+ * @return defensive copy of the collection
+ */
+ List<String> getInsertOrder() {
+ return Collections.unmodifiableList(this.insertOrder);
+ }
+
+ /**
+ * Default constructor.
+ */
+ public MOAPersonalAttributeList() {
+ super();
+
+ }
+
+ /**
+ * Constructor with initial capacity for the PersonalAttributeList size.
+ *
+ * @param capacity The initial capacity for the PersonalAttributeList.
+ */
+ public MOAPersonalAttributeList(final int capacity) {
+ super(capacity);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Iterator<PersonalAttribute> iterator() {
+ return new MOAOrderedAttributeIterator(this);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public PersonalAttribute get(final Object key) {
+ String attrName = (String) key;
+
+ if (this.latestAttrAlias == null)
+ this.latestAttrAlias = new HashMap<String, Integer>();
+
+ if (this.attrAliasNumber == null)
+ this.attrAliasNumber = new HashMap<String, Integer>();
+
+ if (this.latestAttrAlias.containsKey(key)) {
+ attrName = attrName + this.latestAttrAlias.get(key);
+ } else {
+ if (this.attrAliasNumber.containsKey(key)) {
+ this.latestAttrAlias.put(attrName, this.attrAliasNumber.get(key));
+ }
+ }
+ return super.get(attrName);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void add(final PersonalAttribute value) {
+ if (value != null) {
+ this.put(value.getName(), value);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public PersonalAttribute put(final String key, final PersonalAttribute val) {
+ if (StringUtils.isNotEmpty(key) && val != null) {
+ // Validate if attribute name already exists!
+ String attrAlias = key;
+ if (this.containsKey(attrAlias)) {
+ if (this.attrAliasNumber == null)
+ this.attrAliasNumber = new HashMap<String, Integer>();
+ if (!val.isEmptyValue() && StringUtils.isNumeric(val.getValue().get(0))) {
+ final String attrValue = val.getValue().get(0);
+ attrAlias = key + attrValue;
+ this.attrAliasNumber.put(key, Integer.valueOf(attrValue));
+ } else {
+ final PersonalAttribute attr = super.get(key);
+ if (!attr.isEmptyValue()
+ && StringUtils.isNumeric(attr.getValue().get(0))) {
+ attrAlias = key + attr.getValue().get(0);
+ super.put(key, (PersonalAttribute) attr);
+ this.attrAliasNumber.put(key, null);
+ }
+ }
+ } else {
+ if (insertOrder == null)
+ insertOrder = new ArrayList<String>();
+
+ insertOrder.add(key);
+ }
+ return super.put(attrAlias, val);
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public PersonalAttribute remove(Object key) {
+ insertOrder.remove(key);
+ return super.remove(key);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void populate(final String attrList) {
+ final StringTokenizer strToken =
+ new StringTokenizer(attrList, EIDASValues.ATTRIBUTE_SEP.toString());
+
+ while (strToken.hasMoreTokens()) {
+ final PersonalAttribute persAttr = new PersonalAttribute();
+ String[] tuples =
+ strToken.nextToken().split(EIDASValues.ATTRIBUTE_TUPLE_SEP.toString(),
+ AttributeConstants.NUMBER_TUPLES.intValue());
+
+ // Convert to the new format if needed!
+ tuples = convertFormat(tuples);
+
+ if (AttributeUtil.hasValidTuples(tuples)) {
+ final int attrValueIndex =
+ AttributeConstants.ATTR_VALUE_INDEX.intValue();
+ final String tmpAttrValue =
+ tuples[attrValueIndex].substring(1,
+ tuples[attrValueIndex].length() - 1);
+ final String[] vals =
+ tmpAttrValue.split(EIDASValues.ATTRIBUTE_VALUE_SEP.toString());
+
+ persAttr.setName(tuples[AttributeConstants.ATTR_NAME_INDEX.intValue()]);
+ persAttr.setIsRequired(Boolean
+ .valueOf(tuples[AttributeConstants.ATTR_TYPE_INDEX.intValue()]));
+ // check if it is a complex value
+ if (tuples[AttributeConstants.ATTR_NAME_INDEX.intValue()]
+ .equals(EIDASParameters.COMPLEX_ADDRESS_VALUE.toString())) {
+ persAttr.setComplexValue(createComplexValue(vals));
+ } else {
+ persAttr.setValue(createValues(vals));
+ }
+
+ if (tuples.length == AttributeConstants.NUMBER_TUPLES.intValue()) {
+ persAttr.setStatus(tuples[AttributeConstants.ATTR_STATUS_INDEX
+ .intValue()]);
+ }
+ this.put(tuples[AttributeConstants.ATTR_NAME_INDEX.intValue()],
+ persAttr);
+
+ } else {
+ Logger.info("BUSINESS EXCEPTION : Invalid personal attribute list tuples");
+ }
+
+ }
+ }
+
+ /**
+ * Returns a copy of this <tt>IPersonalAttributeList</tt> instance.
+ *
+ * @return The copy of this IPersonalAttributeList.
+ */
+ public Object clone() {
+ try {
+ MOAPersonalAttributeList theClone= (MOAPersonalAttributeList)super.clone();
+ theClone.insertOrder=new ArrayList<String>(insertOrder);
+ return theClone;
+
+ } catch (CloneNotSupportedException e) {
+ throw new InternalErrorEIDASException(
+ EIDASUtil.getConfig(EIDASErrors.INTERNAL_ERROR.errorCode()),
+ EIDASUtil.getConfig(EIDASErrors.INTERNAL_ERROR.errorMessage()), e);
+ }
+ }
+
+ /**
+ * Creates a string in the following format.
+ *
+ * attrName:attrType:[attrValue1,attrValue2=attrComplexValue]:attrStatus;
+ *
+ * @return {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ final StringBuilder strBuilder = new StringBuilder();
+ final Iterator<String> iteratorInsertOrder = insertOrder.iterator();
+ while (iteratorInsertOrder.hasNext()) {
+ String key = iteratorInsertOrder.next();
+ final PersonalAttribute attr = get(key);
+ strBuilder.append(attr.toString());
+ if (isNumberAlias(key)) {
+ strBuilder.append(get(key).toString());
+ }
+ }
+ return strBuilder.toString();
+ }
+
+ /**
+ * Validates and creates the attribute's complex values.
+ *
+ * @param values The complex values.
+ * @return The {@link Map} with the complex values.
+ * @see Map
+ */
+ private Map<String, String> createComplexValue(final String[] values) {
+ final Map<String, String> complexValue = new HashMap<String, String>();
+ for (final String val : values) {
+ final String[] tVal = val.split("=");
+ if (StringUtils.isNotEmpty(val) && tVal.length == 2) {
+ complexValue.put(tVal[0], AttributeUtil.unescape(tVal[1]));
+ }
+ }
+ return complexValue;
+ }
+
+ /**
+ * Validates and creates the attribute values.
+ *
+ * @param vals The attribute values.
+ * @return The {@link List} with the attribute values.
+ * @see List
+ */
+ private List<String> createValues(final String[] vals) {
+ final List<String> values = new ArrayList<String>();
+ for (final String val : vals) {
+ if (StringUtils.isNotEmpty(val)) {
+ values.add(AttributeUtil.unescape(val));
+ }
+ }
+ return values;
+ }
+
+ //////////////////
+ /**
+ * Converts the attribute tuple (attrName:attrType...) to the new format.
+ *
+ * @param tuples The attribute tuples to convert.
+ * @return The attribute tuples in the new format.
+ */
+ private String[] convertFormat(final String[] tuples) {
+ final String[] newFormatTuples =
+ new String[AttributeConstants.NUMBER_TUPLES.intValue()];
+ if (tuples != null) {
+ System.arraycopy(tuples, 0, newFormatTuples, 0, tuples.length);
+
+ for (int i = tuples.length; i < newFormatTuples.length; i++) {
+ if (i == AttributeConstants.ATTR_VALUE_INDEX.intValue()) {
+ newFormatTuples[i] = "[]";
+ } else {
+ newFormatTuples[i] = "";
+ }
+ }
+ }
+ return newFormatTuples;
+ }
+
+ public boolean isNumberAlias(String key) {
+ return this.attrAliasNumber.containsKey(key);
+ }
+
+
+
+}
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
new file mode 100644
index 000000000..8e46f0ef1
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java
@@ -0,0 +1,71 @@
+/*
+ * 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 at.gv.egovernment.moa.id.auth.modules.eidas.Constants;
+import at.gv.egovernment.moa.id.auth.modules.eidas.config.MOAIDCertificateManagerConfigurationImpl;
+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.logging.Logger;
+import eu.eidas.auth.engine.EIDASSAMLEngine;
+import eu.eidas.engine.exceptions.EIDASSAMLEngineException;
+import eu.eidas.samlengineconfig.CertificateConfigurationManager;
+
+/**
+ * @author tlenz
+ *
+ */
+public class SAMLEngineUtils {
+
+ private static EIDASSAMLEngine eIDASEngine = null;
+
+ public static synchronized EIDASSAMLEngine createSAMLEngine() throws EIDASEngineException{
+
+ if (eIDASEngine == null) {
+ try {
+ //get eIDAS SAMLengine configuration from MOA-ID configuration
+ CertificateConfigurationManager configManager = new MOAIDCertificateManagerConfigurationImpl();
+
+ //initial eIDAS SAMLengine
+ EIDASSAMLEngine engine = EIDASSAMLEngine.createSAMLEngine(Constants.eIDAS_SAML_ENGINE_NAME,
+ configManager);
+
+ //set Metadata managment to eIDAS SAMLengine
+ engine.setMetadataProcessor(
+ new MOAeIDASMetadataProviderDecorator(
+ MOAeIDASChainingMetadataProvider.getInstance()));
+
+ eIDASEngine = engine;
+
+ } catch (EIDASSAMLEngineException e) {
+ Logger.error("eIDAS SAMLengine initialization FAILED!", e);
+ throw new EIDASEngineException("eIDAS SAMLengine initialization FAILED!", e);
+
+ }
+ }
+
+ return eIDASEngine;
+ }
+
+}
diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/AuthenticationRequest.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/AuthenticationRequest.java
new file mode 100644
index 000000000..c8f6bba9c
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/AuthenticationRequest.java
@@ -0,0 +1,176 @@
+/*******************************************************************************
+ * 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;
+
+import java.io.StringWriter;
+import java.text.SimpleDateFormat;
+import java.util.Map.Entry;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+
+import at.gv.egovernment.moa.id.auth.builder.BPKBuilder;
+import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
+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.engine.MOAeIDASMetadataProviderDecorator;
+import at.gv.egovernment.moa.id.auth.modules.eidas.utils.MOAPersonalAttributeList;
+import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils;
+import at.gv.egovernment.moa.id.config.auth.AuthConfiguration;
+import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory;
+import at.gv.egovernment.moa.id.data.IAuthData;
+import at.gv.egovernment.moa.id.data.SLOInformationInterface;
+import at.gv.egovernment.moa.id.moduls.IAction;
+import at.gv.egovernment.moa.id.moduls.IRequest;
+import at.gv.egovernment.moa.id.util.VelocityProvider;
+import at.gv.egovernment.moa.logging.Logger;
+import eu.eidas.auth.commons.EIDASAuthnResponse;
+import eu.eidas.auth.commons.EIDASStatusCode;
+import eu.eidas.auth.commons.EIDASUtil;
+import eu.eidas.auth.commons.PersonalAttribute;
+import eu.eidas.auth.engine.EIDASSAMLEngine;
+import eu.eidas.auth.engine.metadata.MetadataUtil;
+
+
+/**
+ * Second request step - after authentication of the user is done and moasession obtained,
+ * process request and forward the user further to PEPS and/or other entities
+ *
+ * @author bsuzic
+ */
+
+public class AuthenticationRequest implements IAction {
+
+ @Override
+ public SLOInformationInterface processRequest(IRequest req, HttpServletRequest httpReq, HttpServletResponse httpResp, IAuthData authData) throws MOAIDException {
+ EIDASData eidasRequest;
+ if(req instanceof EIDASData)
+ eidasRequest = (EIDASData) req;
+ else
+ throw new MOAIDException("got wrong IRequest type. is: {}, should be: {}", new String[] {req.getClass().toString(), EIDASData.class.toString()});
+
+
+ // gather attributes
+ MOAPersonalAttributeList resultingAttributeList = (MOAPersonalAttributeList) eidasRequest.getEidasRequestedAttributes().clone();
+
+ for(Entry<String, PersonalAttribute> current : resultingAttributeList.entrySet()) {
+ String newValue = "";
+
+ // TODO make use of proper builder
+ switch(current.getKey()) {
+ 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 = new BPKBuilder().buildStorkeIdentifier(authData.getIdentificationType(), authData.getIdentificationValue(),
+ eidasRequest.getTarget()); break;
+ }
+
+ if("".equals(newValue))
+ current.getValue().setStatus(EIDASStatusCode.STATUS_NOT_AVAILABLE.toString());
+ else {
+ current.getValue().getValue().clear();
+ current.getValue().getValue().add(newValue);
+ current.getValue().setStatus(EIDASStatusCode.STATUS_AVAILABLE.toString());
+ }
+ }
+
+ // construct eIDaS response
+ EIDASAuthnResponse response = new EIDASAuthnResponse();
+ response.setPersonalAttributeList(resultingAttributeList);
+
+ // - create metadata url
+ AuthConfiguration config = AuthConfigurationProviderFactory.getInstance();
+ String pubURLPrefix = req.getAuthURL();
+ String metadata_url = pubURLPrefix + Constants.eIDAS_HTTP_ENDPOINT_METADATA;
+ response.setIssuer(metadata_url);
+
+ response.setAssuranceLevel(authData.getEIDASQAALevel());
+
+ String token = null;
+ try {
+ EIDASSAMLEngine engine = SAMLEngineUtils.createSAMLEngine();
+
+ // check if we have the destination available, supply it if not
+ if(null == eidasRequest.getEidasRequest().getAssertionConsumerServiceURL()) {
+ String assertionConsumerUrl = MetadataUtil.getAssertionUrlFromMetadata(
+ new MOAeIDASMetadataProviderDecorator(MOAeIDASChainingMetadataProvider.getInstance()),
+ engine,
+ eidasRequest.getEidasRequest());
+ eidasRequest.getEidasRequest().setAssertionConsumerServiceURL(assertionConsumerUrl);
+ }
+
+ response = engine.generateEIDASAuthnResponse(eidasRequest.getEidasRequest(), response, eidasRequest.getRemoteAddress(), true);
+
+
+ token = EIDASUtil.encodeSAMLToken(response.getTokenSaml());
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+
+ // send the response
+ try {
+ VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine();
+ Template template = velocityEngine.getTemplate("/resources/templates/stork2_postbinding_template.html");
+ VelocityContext context = new VelocityContext();
+
+ context.put("SAMLResponse", token);
+ Logger.debug("SAMLResponse original: " + token);
+
+ Logger.debug("Putting assertion consumer url as action: " + eidasRequest.getEidasRequest().getAssertionConsumerServiceURL());
+ context.put("action", eidasRequest.getEidasRequest().getAssertionConsumerServiceURL());
+ Logger.trace("Starting template merge");
+ StringWriter writer = new StringWriter();
+
+ Logger.trace("Doing template merge");
+ template.merge(context, writer);
+ Logger.trace("Template merge done");
+
+ Logger.trace("Sending html content: " + writer.getBuffer().toString());
+ Logger.trace("Sending html content2 : " + new String(writer.getBuffer()));
+
+ httpResp.getOutputStream().write(writer.getBuffer().toString().getBytes("UTF-8"));
+
+ } catch (Exception e) {
+ Logger.error("Velocity error: " + e.getMessage());
+ }
+
+ return null;
+ }
+
+ @Override
+ public boolean needAuthentication(IRequest req, HttpServletRequest httpReq, HttpServletResponse httpResp) {
+ return true;
+ }
+
+ @Override
+ public String getDefaultActionName() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+
+}
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
new file mode 100644
index 000000000..374c3df30
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASData.java
@@ -0,0 +1,96 @@
+package at.gv.egovernment.moa.id.protocols.eidas;
+
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.opensaml.saml2.core.Attribute;
+
+import at.gv.egovernment.moa.id.auth.modules.eidas.utils.MOAPersonalAttributeList;
+import at.gv.egovernment.moa.id.config.ConfigurationException;
+import at.gv.egovernment.moa.id.moduls.RequestImpl;
+import eu.eidas.auth.commons.EIDASAuthnRequest;
+
+public class EIDASData extends RequestImpl {
+
+ /**
+ * @param req
+ * @throws ConfigurationException
+ */
+ public EIDASData(HttpServletRequest req) throws ConfigurationException {
+ super(req);
+
+ }
+
+ /** The Constant serialVersionUID. */
+ private static final long serialVersionUID = 8765755670214923910L;
+
+ /** The attributes requested by the eIDaS. */
+ private MOAPersonalAttributeList attributes;
+
+ /** The incoming eIDaS SAML2 AuthnRequest. */
+ private EIDASAuthnRequest authnRequest;
+
+ /** The ip address of the requester. */
+ private String remoteIPAddress;
+
+ @Override
+ public List<Attribute> getRequestedAttributes() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /**
+ * Gets the eidas requested attributes.
+ *
+ * @return the requested attributes
+ */
+ public MOAPersonalAttributeList getEidasRequestedAttributes() {
+ return (MOAPersonalAttributeList) attributes.clone();
+ }
+
+ /**
+ * Sets the eidas requested attributes.
+ *
+ * @param personalAttributeList the requested attributes
+ */
+ public void setEidasRequestedAttributes(MOAPersonalAttributeList personalAttributeList) {
+ attributes = personalAttributeList;
+ }
+
+ /**
+ * Gets the eidas request.
+ *
+ * @return the eidas request
+ */
+ public EIDASAuthnRequest getEidasRequest() {
+ return authnRequest;
+ }
+
+ /**
+ * Sets the eidas request.
+ *
+ * @param request the new eidas request
+ */
+ public void setEidasRequest(EIDASAuthnRequest request) {
+ authnRequest = request;
+ }
+
+ /**
+ * Gets the remote address.
+ *
+ * @return the remote address
+ */
+ public String getRemoteAddress() {
+ return remoteIPAddress;
+ }
+
+ /**
+ * Sets the remote address.
+ *
+ * @param remoteIP the new remote address
+ */
+ public void setRemoteAddress(String remoteIP) {
+ remoteIPAddress = remoteIP;
+ }
+}
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
new file mode 100644
index 000000000..b652503f8
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java
@@ -0,0 +1,152 @@
+/*******************************************************************************
+ * 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;
+
+import java.util.HashMap;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants;
+import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
+import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
+import at.gv.egovernment.moa.id.auth.modules.eidas.utils.MOAPersonalAttributeList;
+import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils;
+import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory;
+import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
+import at.gv.egovernment.moa.id.moduls.IAction;
+import at.gv.egovernment.moa.id.moduls.IModulInfo;
+import at.gv.egovernment.moa.id.moduls.IRequest;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.MiscUtil;
+import eu.eidas.auth.commons.EIDASAuthnRequest;
+import eu.eidas.auth.commons.EIDASUtil;
+import eu.eidas.auth.engine.EIDASSAMLEngine;
+
+/**
+ * Stork 2 Protocol Support
+ *
+ * @author bsuzic
+ */
+public class EIDASProtocol extends MOAIDAuthConstants implements IModulInfo {
+
+ public static final String NAME = EIDASProtocol.class.getName();
+ public static final String PATH = "eidas";
+
+ public static final String AUTHENTICATIONREQUEST = "AuthenticationRequest";
+ public static final String METADATAREQUEST = "MetadataRequest";
+
+ private static HashMap<String, IAction> actions = new HashMap<String, IAction>();
+
+ static {
+ actions.put(AUTHENTICATIONREQUEST, new AuthenticationRequest());
+ actions.put(METADATAREQUEST, new EidasMetaDataRequest());
+
+ }
+
+ public String getName() {
+ return NAME;
+ }
+
+ public String getPath() {
+ return PATH;
+ }
+
+ public IAction getAction(String action) {
+ return actions.get(action);
+ }
+
+ public EIDASProtocol() {
+ super();
+ }
+
+ /*
+ First request step - send it to BKU selection for user authentication. After the user credentials
+ and other info are obtained, in the second step the request will be processed and the user redirected
+ */
+ public IRequest preProcess(HttpServletRequest request, HttpServletResponse response, String action,
+ String sessionId, String transactionId) throws MOAIDException {
+
+ Logger.info("received an eIDaS request");
+
+ //get SAML Response and decode it
+ String base64SamlToken = request.getParameter("SAMLRequest");
+ if (MiscUtil.isEmpty(base64SamlToken)) {
+ Logger.warn("No eIDAS SAMLRequest found in http request.");
+ throw new MOAIDException("HTTP request includes no eIDAS SAML-Request element.", null);
+ }
+ byte[] decSamlToken = EIDASUtil.decodeSAMLToken(base64SamlToken);
+
+ try {
+ //get eIDAS SAML-engine
+ EIDASSAMLEngine engine = SAMLEngineUtils.createSAMLEngine();
+
+ //validate SAML token
+ EIDASAuthnRequest samlReq = engine.validateEIDASAuthnRequest(decSamlToken);
+
+ // memorize important stuff
+ EIDASData result = new EIDASData(request);
+
+ // - memorize remote ip
+ result.setRemoteAddress(request.getRemoteAddr());
+
+ // - memorize country code of target country
+ result.setTarget(samlReq.getCountry());
+
+ // - memorize requested attributes
+ result.setEidasRequestedAttributes(new MOAPersonalAttributeList(samlReq.getPersonalAttributeList()));
+
+ // - memorize whole request
+ samlReq.setPersonalAttributeList(result.getEidasRequestedAttributes()); // circumvent non-serializable eidas personal attribute list
+ result.setEidasRequest(samlReq);
+
+ // - memorize OA url
+ result.setOAURL(samlReq.getIssuer());
+
+ // - memorize OA config
+ OAAuthParameter oaConfig = AuthConfigurationProviderFactory.getInstance().getOnlineApplicationParameter(result.getOAURL());
+ if (oaConfig == null)
+ throw new AuthenticationException("stork.12", new Object[]{result.getOAURL()});
+ result.setOnlineApplicationConfiguration(oaConfig);
+
+ return result;
+ } catch(Exception e) {
+ Logger.error("error in preprocessing step", e);
+ throw new MOAIDException("error in preprocessing step", null);
+ }
+ }
+
+ public IAction canHandleRequest(HttpServletRequest request, HttpServletResponse response) {
+ return null;
+ }
+
+ public boolean generateErrorMessage(Throwable e, HttpServletRequest request, HttpServletResponse response, IRequest protocolRequest) throws Throwable {
+ return false;
+ }
+
+ public boolean validate(HttpServletRequest request, HttpServletResponse response, IRequest pending) {
+ return false;
+ }
+}
+
+
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
new file mode 100644
index 000000000..0be291a06
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EidasMetaDataRequest.java
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * Copyright 2015 e-SENS project
+ *
+ * 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://ec.europa.eu/idabc/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.
+ *******************************************************************************/
+package at.gv.egovernment.moa.id.protocols.eidas;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+
+import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
+import at.gv.egovernment.moa.id.auth.modules.eidas.Constants;
+import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASEngineException;
+import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils;
+import at.gv.egovernment.moa.id.data.IAuthData;
+import at.gv.egovernment.moa.id.data.SLOInformationInterface;
+import at.gv.egovernment.moa.id.moduls.IAction;
+import at.gv.egovernment.moa.id.moduls.IRequest;
+import eu.eidas.auth.engine.EIDASSAMLEngine;
+import eu.eidas.auth.engine.metadata.MetadataConfigParams;
+import eu.eidas.auth.engine.metadata.MetadataGenerator;
+import eu.eidas.engine.exceptions.SAMLEngineException;
+
+
+/**
+ * First version to provide some valid metadata to an asking eIDaS node
+ */
+//@WebServlet("/eidas/metadata")
+public class EidasMetaDataRequest implements IAction {
+ private static final long serialVersionUID = -2129228304760706063L;
+ private Logger logger = org.slf4j.LoggerFactory.getLogger(EidasMetaDataRequest.class);
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.moduls.IAction#processRequest(at.gv.egovernment.moa.id.moduls.IRequest, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, at.gv.egovernment.moa.id.data.IAuthData)
+ */
+ @Override
+ public SLOInformationInterface processRequest(IRequest req,
+ HttpServletRequest httpReq, HttpServletResponse httpResp,
+ IAuthData authData) throws MOAIDException {
+
+ try {
+ logger.debug("EidasMetaDataServlet GET");
+
+ String pubURLPrefix = req.getAuthURL();
+
+ String metadata_url = pubURLPrefix + Constants.eIDAS_HTTP_ENDPOINT_METADATA;
+
+ String sp_return_url = pubURLPrefix + Constants.eIDAS_HTTP_ENDPOINT_SP_POST;
+ String metaData = generateMetadata(metadata_url, sp_return_url);
+
+ logger.trace(metaData);
+
+ httpResp.setContentType("text/xml");
+ httpResp.getWriter().print(metaData);
+ httpResp.flushBuffer();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.moduls.IAction#needAuthentication(at.gv.egovernment.moa.id.moduls.IRequest, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+ */
+ @Override
+ public boolean needAuthentication(IRequest req, HttpServletRequest httpReq,
+ HttpServletResponse httpResp) {
+ return false;
+
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.moduls.IAction#getDefaultActionName()
+ */
+ @Override
+ public String getDefaultActionName() {
+ return "eIDAS-Metadata Action";
+
+ }
+
+ public String generateMetadata(String metadata_url, String sp_return_url) throws SAMLEngineException, EIDASEngineException{
+ String metadata="invalid metadata";
+
+ EIDASSAMLEngine engine = SAMLEngineUtils.createSAMLEngine();
+
+ MetadataGenerator generator = new MetadataGenerator();
+ MetadataConfigParams mcp=new MetadataConfigParams();
+ generator.setConfigParams(mcp);
+ generator.initialize(engine);
+ mcp.setEntityID(metadata_url);
+
+ generator.addSPRole();
+ String returnUrl = sp_return_url;
+ mcp.setAssertionConsumerUrl(returnUrl);
+
+ generator.addIDPRole();
+ mcp.setAssuranceLevel("http://eidas.europa.eu/LoA/substantial"); // TODO make configurable
+
+ metadata = generator.generateMetadata();
+ return metadata;
+ }
+}