aboutsummaryrefslogtreecommitdiff
path: root/id/server/modules/moa-id-module-eIDAS-v2/src/main/java
diff options
context:
space:
mode:
authorThomas Lenz <tlenz@iaik.tugraz.at>2018-04-25 09:40:52 +0200
committerThomas Lenz <tlenz@iaik.tugraz.at>2018-04-25 09:40:52 +0200
commit44bce0049b598604cc1a30f419e936c6b5fc59cf (patch)
tree504cdd7c0360b216002eb7c32df2c1aec74bff52 /id/server/modules/moa-id-module-eIDAS-v2/src/main/java
parentb4c009b6d64cc17974e5917c10f92dbe987d826e (diff)
downloadmoa-id-spss-44bce0049b598604cc1a30f419e936c6b5fc59cf.tar.gz
moa-id-spss-44bce0049b598604cc1a30f419e936c6b5fc59cf.tar.bz2
moa-id-spss-44bce0049b598604cc1a30f419e936c6b5fc59cf.zip
first test codes for eIDAS Ref. Impl. v2 integration
Diffstat (limited to 'id/server/modules/moa-id-module-eIDAS-v2/src/main/java')
-rw-r--r--id/server/modules/moa-id-module-eIDAS-v2/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas_v2/Constants.java44
-rw-r--r--id/server/modules/moa-id-module-eIDAS-v2/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas_v2/eIDASAuthenticationModulImpl.java72
-rw-r--r--id/server/modules/moa-id-module-eIDAS-v2/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas_v2/eIDASAuthenticationSpringResourceProvider.java28
-rw-r--r--id/server/modules/moa-id-module-eIDAS-v2/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas_v2/eIDASSignalServlet.java88
-rw-r--r--id/server/modules/moa-id-module-eIDAS-v2/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas_v2/tasks/CreateIdentityLinkTask.java180
-rw-r--r--id/server/modules/moa-id-module-eIDAS-v2/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas_v2/tasks/GenerateAuthnRequestTask.java333
-rw-r--r--id/server/modules/moa-id-module-eIDAS-v2/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas_v2/tasks/ReceiveAuthnResponseTask.java141
7 files changed, 886 insertions, 0 deletions
diff --git a/id/server/modules/moa-id-module-eIDAS-v2/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas_v2/Constants.java b/id/server/modules/moa-id-module-eIDAS-v2/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas_v2/Constants.java
new file mode 100644
index 000000000..ca62319f3
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS-v2/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas_v2/Constants.java
@@ -0,0 +1,44 @@
+package at.gv.egovernment.moa.id.auth.modules.eidas_v2;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class Constants {
+ //TODO: update endpoints
+
+ //configuration properties
+ public static final String CONIG_PROPS_EIDAS_PREFIX="moa.id.protocols.eIDAS";
+ public static final String CONIG_PROPS_EIDAS_NODE= CONIG_PROPS_EIDAS_PREFIX + ".node_v2";
+ public static final String CONIG_PROPS_EIDAS_NODE_COUNTRYCODE = CONIG_PROPS_EIDAS_NODE + ".countrycode";
+
+
+ //http endpoint descriptions
+ public static final String eIDAS_HTTP_ENDPOINT_SP_POST = "/eidas/light/sp/post";
+ public static final String eIDAS_HTTP_ENDPOINT_SP_REDIRECT = "/eidas/light/sp/redirect";
+ public static final String eIDAS_HTTP_ENDPOINT_IDP_COLLEAGUEREQUEST = "/eidas/light/ColleagueRequest";
+ public static final String eIDAS_HTTP_ENDPOINT_METADATA = "/eidas/light/metadata";
+
+ //eIDAS request parameters
+ public static final String eIDAS_REQ_NAMEID_FORMAT = "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent";
+
+ //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 = "FirstName";
+ public static final String eIDAS_ATTR_CURRENTFAMILYNAME = "FamilyName";
+ public static final String eIDAS_ATTR_LEGALPERSONIDENTIFIER = "LegalPersonIdentifier";
+ public static final String eIDAS_ATTR_LEGALNAME = "LegalName";
+
+ public static final List<URI> NATURALPERSONMINIMUMDATASETLIST = Collections.unmodifiableList(new ArrayList<URI>() {
+ private static final long serialVersionUID = 1L;
+ {
+ //TODO: find correct location of attribute definitions
+// add(eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.CURRENT_FAMILY_NAME.getNameUri());
+// add(eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.CURRENT_GIVEN_NAME.getNameUri());
+// add(eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.DATE_OF_BIRTH.getNameUri());
+// add(eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.PERSON_IDENTIFIER.getNameUri());
+ }
+ });
+}
diff --git a/id/server/modules/moa-id-module-eIDAS-v2/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas_v2/eIDASAuthenticationModulImpl.java b/id/server/modules/moa-id-module-eIDAS-v2/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas_v2/eIDASAuthenticationModulImpl.java
new file mode 100644
index 000000000..6e3170534
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS-v2/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas_v2/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_v2;
+
+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_v2";
+ 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_v2/eIDAS.Authentication.process.xml" };
+ }
+
+}
diff --git a/id/server/modules/moa-id-module-eIDAS-v2/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas_v2/eIDASAuthenticationSpringResourceProvider.java b/id/server/modules/moa-id-module-eIDAS-v2/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas_v2/eIDASAuthenticationSpringResourceProvider.java
new file mode 100644
index 000000000..fb3b7fc24
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS-v2/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas_v2/eIDASAuthenticationSpringResourceProvider.java
@@ -0,0 +1,28 @@
+package at.gv.egovernment.moa.id.auth.modules.eidas_v2;
+
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+
+import at.gv.egiz.components.spring.api.SpringResourceProvider;
+
+public class eIDASAuthenticationSpringResourceProvider implements SpringResourceProvider {
+
+ @Override
+ public String getName() {
+ return "MOA-ID eIDAS-Authentication SpringResourceProvider";
+ }
+
+ @Override
+ public String[] getPackagesToScan() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Resource[] getResourcesToLoad() {
+ ClassPathResource eIDASAuthConfig = new ClassPathResource("/moaid_eidas_v2_auth.beans", eIDASAuthenticationSpringResourceProvider.class);
+
+ return new Resource[] {eIDASAuthConfig};
+ }
+
+}
diff --git a/id/server/modules/moa-id-module-eIDAS-v2/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas_v2/eIDASSignalServlet.java b/id/server/modules/moa-id-module-eIDAS-v2/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas_v2/eIDASSignalServlet.java
new file mode 100644
index 000000000..3198d04a3
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS-v2/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas_v2/eIDASSignalServlet.java
@@ -0,0 +1,88 @@
+/*
+ * 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_v2;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import at.gv.egovernment.moa.id.auth.servlet.AbstractProcessEngineSignalController;
+import at.gv.egovernment.moa.logging.Logger;
+
+/**
+ * @author tlenz
+ *
+ */
+@Controller
+public class eIDASSignalServlet extends AbstractProcessEngineSignalController {
+
+ public eIDASSignalServlet() {
+ super();
+ Logger.debug("Registering servlet " + getClass().getName() +
+ " with mappings '"+ Constants.eIDAS_HTTP_ENDPOINT_SP_POST +
+ "' and '"+ Constants.eIDAS_HTTP_ENDPOINT_SP_REDIRECT + "'.");
+
+ }
+
+ @RequestMapping(value = { Constants.eIDAS_HTTP_ENDPOINT_SP_POST,
+ Constants.eIDAS_HTTP_ENDPOINT_SP_REDIRECT
+ },
+ method = {RequestMethod.POST, RequestMethod.GET})
+ public void performCitizenCardAuthentication(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ signalProcessManagement(req, resp);
+ }
+
+ @Override
+ /**
+ * Protocol specific implementation to get the pending-requestID
+ * from http request object
+ *
+ * @param request The http Servlet-Request object
+ * @return The Pending-request id
+ *
+ */
+ public String getPendingRequestId(HttpServletRequest request) {
+ String sessionId = super.getPendingRequestId(request);
+
+ try {
+
+ // use SAML2 relayState
+ if (sessionId == null) {
+ sessionId = StringEscapeUtils.escapeHtml(request.getParameter("RelayState"));
+ } 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-v2/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas_v2/tasks/CreateIdentityLinkTask.java b/id/server/modules/moa-id-module-eIDAS-v2/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas_v2/tasks/CreateIdentityLinkTask.java
new file mode 100644
index 000000000..dec4f6a89
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS-v2/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas_v2/tasks/CreateIdentityLinkTask.java
@@ -0,0 +1,180 @@
+/*
+ * 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_v2.tasks;
+
+import java.io.InputStream;
+import java.text.SimpleDateFormat;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.joda.time.DateTime;
+import org.springframework.stereotype.Component;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants;
+import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionStorageConstants;
+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.modules.eidas.utils.SAMLEngineUtils;
+import at.gv.egovernment.moa.id.auth.parser.IdentityLinkAssertionParser;
+import at.gv.egovernment.moa.id.commons.api.data.IIdentityLink;
+import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException;
+import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
+import at.gv.egovernment.moa.id.process.api.ExecutionContext;
+import at.gv.egovernment.moa.id.util.IdentityLinkReSigner;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.DOMUtils;
+import at.gv.egovernment.moa.util.XPathUtils;
+import eu.eidas.auth.commons.attribute.ImmutableAttributeMap;
+
+/**
+ * @author tlenz
+ *
+ */
+@Component("CreateIdentityLinkTask")
+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{
+ defaultTaskInitialization(request, executionContext);
+
+ //get eIDAS attributes from MOA-Session
+ ImmutableAttributeMap eIDASAttributes = moasession.getGenericDataFromSession(
+ AuthenticationSessionStorageConstants.eIDAS_ATTRIBUTELIST,
+ ImmutableAttributeMap.class);
+
+ IIdentityLink 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 fake baseID;
+ Node prIdentification = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_IDENT_VALUE_XPATH);
+
+
+ Object eIdentifier = eIDASAttributes.getFirstValue(
+ SAMLEngineUtils.getMapOfAllAvailableAttributes().get(
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER));
+ if (eIdentifier == null || !(eIdentifier instanceof String))
+ throw new eIDASAttributeException(Constants.eIDAS_ATTR_PERSONALIDENTIFIER);
+ prIdentification.getFirstChild().setNodeValue((String) eIdentifier);
+
+ //build personal identifier which looks like a baseID
+// String fakeBaseID = new BPKBuilder().buildBPK(eIdentifier, "baseID");
+// Logger.info("Map eIDAS eIdentifier:" + eIdentifier + " to fake baseID:" + fakeBaseID);
+// prIdentification.getFirstChild().setNodeValue(fakeBaseID);
+
+ // - set last name
+ Node prFamilyName = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_FAMILY_NAME_XPATH);
+ Object familyName = eIDASAttributes.getFirstValue(
+ SAMLEngineUtils.getMapOfAllAvailableAttributes().get(
+ Constants.eIDAS_ATTR_CURRENTFAMILYNAME));
+ if (familyName == null || !(familyName instanceof String))
+ throw new eIDASAttributeException(Constants.eIDAS_ATTR_CURRENTFAMILYNAME);
+ prFamilyName.getFirstChild().setNodeValue((String) familyName);
+
+ // - set first name
+ Node prGivenName = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_GIVEN_NAME_XPATH);
+ Object givenName = eIDASAttributes.getFirstValue(
+ SAMLEngineUtils.getMapOfAllAvailableAttributes().get(
+ Constants.eIDAS_ATTR_CURRENTGIVENNAME));
+ if (givenName == null || !(givenName instanceof String))
+ throw new eIDASAttributeException(Constants.eIDAS_ATTR_CURRENTGIVENNAME);
+ prGivenName.getFirstChild().setNodeValue((String) givenName);
+
+ // - set date of birth
+ Node prDateOfBirth = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_DATE_OF_BIRTH_XPATH);
+ Object dateOfBirth = eIDASAttributes.getFirstValue(
+ SAMLEngineUtils.getMapOfAllAvailableAttributes().get(
+ Constants.eIDAS_ATTR_DATEOFBIRTH));
+ if (dateOfBirth == null || !(dateOfBirth instanceof DateTime))
+ throw new eIDASAttributeException(Constants.eIDAS_ATTR_DATEOFBIRTH);
+
+ String formatedDateOfBirth = new SimpleDateFormat("yyyy-MM-dd").format(((DateTime)dateOfBirth).toDate());
+ prDateOfBirth.getFirstChild().setNodeValue(formatedDateOfBirth);
+
+ identityLink = new IdentityLinkAssertionParser(idlassertion).parseIdentityLink();
+
+ //resign IDL
+ IdentityLinkReSigner identitylinkresigner = IdentityLinkReSigner.getInstance();
+ Element resignedilAssertion = identitylinkresigner.resignIdentityLink(identityLink.getSamlAssertion(), authConfig.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);
+ }
+
+ revisionsLogger.logEvent(pendingReq, MOAIDEventConstants.AUTHPROCESS_PEPS_IDL_RECEIVED);
+ moasession.setForeigner(true);
+ moasession.setIdentityLink(identityLink);
+ moasession.setBkuURL("Not applicable (eIDASAuthentication)");
+
+ //store MOA-session to database
+ requestStoreage.storePendingRequest(pendingReq);
+
+ } catch (eIDASAttributeException e) {
+ throw new TaskExecutionException(pendingReq, "Minimum required eIDAS attributeset not found.", e);
+
+ } catch (MOAIDException | MOADatabaseException e) {
+ throw new TaskExecutionException(pendingReq, "IdentityLink generation for foreign person FAILED.", e);
+
+ } catch (Exception e) {
+ Logger.error("IdentityLink generation for foreign person FAILED.", e);
+ throw new TaskExecutionException(pendingReq, "IdentityLink generation for foreign person FAILED.", e);
+
+ }
+ }
+
+}
diff --git a/id/server/modules/moa-id-module-eIDAS-v2/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas_v2/tasks/GenerateAuthnRequestTask.java b/id/server/modules/moa-id-module-eIDAS-v2/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas_v2/tasks/GenerateAuthnRequestTask.java
new file mode 100644
index 000000000..3085d0e70
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS-v2/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas_v2/tasks/GenerateAuthnRequestTask.java
@@ -0,0 +1,333 @@
+/*
+ * 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_v2.tasks;
+
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.UUID;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang3.BooleanUtils;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+import org.opensaml.common.xml.SAMLConstants;
+import org.opensaml.saml2.metadata.EntityDescriptor;
+import org.opensaml.saml2.metadata.SingleSignOnService;
+import org.opensaml.saml2.metadata.provider.MetadataProviderException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import com.google.common.net.MediaType;
+
+import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants;
+import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
+import at.gv.egovernment.moa.id.auth.frontend.velocity.VelocityProvider;
+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_v2.Constants;
+import at.gv.egovernment.moa.id.commons.MOAIDAuthConstants;
+import at.gv.egovernment.moa.id.commons.api.IOAAuthParameters;
+import at.gv.egovernment.moa.id.commons.api.IRequest;
+import at.gv.egovernment.moa.id.commons.api.data.CPEPS;
+import at.gv.egovernment.moa.id.commons.api.data.StorkAttribute;
+import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException;
+import at.gv.egovernment.moa.id.process.api.ExecutionContext;
+import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.MiscUtil;
+import eu.eidas.auth.commons.EidasStringUtil;
+import eu.eidas.auth.commons.attribute.AttributeDefinition;
+import eu.eidas.auth.commons.attribute.AttributeDefinition.Builder;
+import eu.eidas.auth.commons.light.impl.LightRequest;
+import eu.eidas.auth.commons.attribute.ImmutableAttributeMap;
+import eu.eidas.auth.commons.protocol.IRequestMessage;
+import eu.eidas.auth.commons.protocol.eidas.LevelOfAssurance;
+import eu.eidas.auth.commons.protocol.eidas.LevelOfAssuranceComparison;
+import eu.eidas.auth.commons.protocol.eidas.SpType;
+import eu.eidas.auth.commons.protocol.eidas.impl.EidasAuthenticationRequest;
+
+/**
+ * @author tlenz
+ *
+ */
+@Component("GenerateAuthnRequestTask")
+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{
+ //get service-provider configuration
+ IOAAuthParameters oaConfig = pendingReq.getOnlineApplicationConfiguration();
+
+ // get target and validate citizen countryCode
+ 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("eIDAS.03", new Object[] { "" });
+
+ }
+ CPEPS cpeps = authConfig.getStorkConfig().getCPEPSWithFullName(citizenCountryCode);
+ if(null == cpeps) {
+ Logger.error("PEPS unknown for country: " + citizenCountryCode);
+ throw new AuthenticationException("eIDAS.04", new Object[] {citizenCountryCode});
+ }
+ Logger.debug("Found eIDaS Node/C-PEPS configuration for citizen of country: " + citizenCountryCode);
+
+
+ //TODO: load authnReq End-Point URL from configuration
+ SingleSignOnService authnReqEndpoint = null;
+
+
+ //TODO: switch to entityID and set new status codes
+// revisionsLogger.logEvent(oaConfig, pendingReq,
+// MOAIDEventConstants.AUTHPROCESS_PEPS_SELECTED,
+// metadataUrl);
+
+ // assemble requested attributes
+ Collection<StorkAttribute> attributesFromConfig = oaConfig.getRequestedSTORKAttributes();
+
+ // - prepare attribute list
+
+ // - fill container
+ List<AttributeDefinition<?>> reqAttrList = new ArrayList<AttributeDefinition<?>>();
+ //TODO: update requested attribute builder
+// for (StorkAttribute current : attributesFromConfig) {
+// AttributeDefinition<?> newAttribute = SAMLEngineUtils.getMapOfAllAvailableAttributes().get(current.getName());
+//
+// if (newAttribute == null) {
+// Logger.warn("eIDAS attribute with friendlyName:" + current.getName() + " is not supported.");
+//
+// } else {
+// boolean globallyMandatory = false;
+// for (StorkAttribute currentGlobalAttribute : authConfig.getStorkConfig().getStorkAttributes())
+// if (current.getName().equals(currentGlobalAttribute.getName())) {
+// globallyMandatory = BooleanUtils.isTrue(currentGlobalAttribute.getMandatory());
+// break;
+// }
+//
+// Builder<?> attrBuilder = AttributeDefinition.builder(newAttribute).required(current.getMandatory() || globallyMandatory);
+// reqAttrList.add(attrBuilder.build());
+//
+// }
+// }
+
+ //request
+// if (reqAttrList.isEmpty()) {
+// Logger.info("No attributes requested by OA:" + pendingReq.getOnlineApplicationConfiguration().getPublicURLPrefix()
+// + " --> Request attr:" + Constants.eIDAS_ATTR_PERSONALIDENTIFIER + " by default");
+// AttributeDefinition<?> newAttribute = SAMLEngineUtils.getMapOfAllAvailableAttributes().get(Constants.eIDAS_ATTR_PERSONALIDENTIFIER);
+// Builder<?> attrBuilder = AttributeDefinition.builder(newAttribute).required(true);
+// reqAttrList.add(attrBuilder.build());
+//
+// }
+
+ //build requested attribute set
+ ImmutableAttributeMap reqAttrMap = new ImmutableAttributeMap.Builder().putAll(reqAttrList).build();
+
+ //build eIDAS AuthnRequest
+ LightRequest.Builder authnRequestBuilder = LightRequest.builder();
+
+ authnRequestBuilder.id(UUID.randomUUID().toString());
+ authnRequestBuilder.providerName(pendingReq.getAuthURL());
+ String issur = pendingReq.getAuthURL() + Constants.eIDAS_HTTP_ENDPOINT_METADATA;
+ authnRequestBuilder.issuer(issur);
+
+ //TODO:
+ //authnRequestBuilder.destination(authnReqEndpoint.getLocation());
+
+
+ authnRequestBuilder.nameIdFormat(Constants.eIDAS_REQ_NAMEID_FORMAT);
+
+ //set minimum required eIDAS LoA from OA config
+ String LoA = oaConfig.getQaaLevel();
+ //TODO:
+// if (MiscUtil.isNotEmpty(LoA))
+// authnRequestBuilder.levelOfAssurance(LevelOfAssurance.fromString(oaConfig.getQaaLevel()));
+// else
+ authnRequestBuilder.levelOfAssurance(LevelOfAssurance.HIGH.getValue());
+
+ //TODO: check if required
+ //authnRequestBuilder.levelOfAssuranceComparison(LevelOfAssuranceComparison.MINIMUM);
+
+
+ //set correct SPType for this online application
+ if (oaConfig.hasBaseIdTransferRestriction())
+ authnRequestBuilder.spType(SpType.PRIVATE.getValue());
+ else
+ authnRequestBuilder.spType(SpType.PUBLIC.getValue());
+
+
+ //TODO
+ //set service provider (eIDAS node) countryCode
+// authnRequestBuilder.serviceProviderCountryCode(
+// authConfig.getBasicMOAIDConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_COUNTRYCODE, "AT"));
+
+ //set citizen country code for foreign uses
+ authnRequestBuilder.citizenCountryCode(cpeps.getCountryCode());
+
+ //add requested attributes
+ authnRequestBuilder.requestedAttributes(reqAttrMap);
+
+
+ LightRequest lightAuthnReq = authnRequestBuilder.build();
+
+
+
+ //IRequestMessage authnRequest = engine.generateRequestMessage(authnRequestBuilder.build(), issur);
+
+ //encode AuthnRequest
+// byte[] token = authnRequest.getMessageBytes();
+// String SAMLRequest = EidasStringUtil.encodeToBase64(token);
+
+
+// if (SAMLConstants.SAML2_POST_BINDING_URI.equals(authnReqEndpoint.getBinding()))
+// buildPostBindingRequest(pendingReq, authnReqEndpoint, SAMLRequest, authnRequest, response);
+//
+// //TODO: redirect Binding is not completely implemented
+// //else if (SAMLConstants.SAML2_REDIRECT_BINDING_URI.equals(authnReqEndpoint.getBinding()))
+// //buildRedirecttBindingRequest(pendingReq, authnReqEndpoint, token, authnRequest, response);
+//
+// else {
+// Logger.error("eIDAS-node use an unsupported binding ("
+// + authnReqEndpoint.getBinding() + "). Request eIDAS node not possible.");
+// throw new MOAIDException("eIDAS.02", new Object[]{"eIDAS-node use an unsupported binding"});
+//
+// }
+
+
+
+// }catch (EIDASSAMLEngineException e){
+// throw new TaskExecutionException(pendingReq, "eIDAS AuthnRequest generation FAILED.",
+// new EIDASEngineException("eIDAS.00", new Object[]{e.getMessage()}, e));
+
+ } catch (MOAIDException e) {
+ throw new TaskExecutionException(pendingReq, "eIDAS AuthnRequest generation FAILED.", e);
+
+ } catch (Exception e) {
+ Logger.error("eIDAS AuthnRequest generation FAILED.", e);
+ throw new TaskExecutionException(pendingReq, e.getMessage(), e);
+
+ }
+ }
+
+ /**
+ * Encode the eIDAS request with POST binding
+ *
+ * @param pendingReq
+ * @param authnReqEndpoint
+ * @param SAMLRequest
+ * @param authnRequest
+ * @param response
+ * @throws MOAIDException
+ */
+ private void buildPostBindingRequest(IRequest pendingReq, SingleSignOnService authnReqEndpoint,
+ String SAMLRequest, IRequestMessage authnRequest, HttpServletResponse response)
+ throws MOAIDException {
+ //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);
+ context.put("RelayState", pendingReq.getRequestID());
+ context.put("action", authnReqEndpoint.getLocation());
+
+ Logger.debug("Using SingleSignOnService url as action: " + authnReqEndpoint.getLocation());
+ Logger.debug("Encoded " + actionType + " original: " + SAMLRequest);
+
+ 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());
+
+
+ byte[] content = writer.getBuffer().toString().getBytes("UTF-8");
+ response.setContentType(MediaType.HTML_UTF_8.toString());
+ response.setContentLength(content.length);
+ response.getOutputStream().write(content);
+
+ revisionsLogger.logEvent(pendingReq.getOnlineApplicationConfiguration(), pendingReq,
+ MOAIDEventConstants.AUTHPROCESS_PEPS_REQUESTED,
+ authnRequest.getRequest().getId());
+
+ } catch (Exception e) {
+ Logger.error("Velocity general error: " + e.getMessage());
+ throw new MOAIDException("eIDAS.02", new Object[]{e.getMessage()}, e);
+
+ }
+
+ }
+
+ /**
+ * Select a SingleSignOnService endPoint from eIDAS node metadata.
+ * This endPoint receives the Authn. request
+ *
+ * @param idpEntity
+ * @return
+ */
+ private SingleSignOnService selectSingleSignOnServiceFromMetadata(EntityDescriptor idpEntity) {
+ //select SingleSignOn Service endpoint from IDP metadata
+ SingleSignOnService endpoint = null;
+ if (idpEntity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS) == null) {
+ return null;
+
+ }
+
+ for (SingleSignOnService sss :
+ idpEntity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS).getSingleSignOnServices()) {
+
+ // use POST binding as default if it exists
+ if (sss.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI))
+ endpoint = sss;
+
+ //TODO: redirect Binding is not completely implemented
+ // use Redirect binding as backup
+// else if ( sss.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)
+// && endpoint == null )
+// endpoint = sss;
+
+ }
+
+ return endpoint;
+ }
+
+}
diff --git a/id/server/modules/moa-id-module-eIDAS-v2/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas_v2/tasks/ReceiveAuthnResponseTask.java b/id/server/modules/moa-id-module-eIDAS-v2/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas_v2/tasks/ReceiveAuthnResponseTask.java
new file mode 100644
index 000000000..9ead5e4fe
--- /dev/null
+++ b/id/server/modules/moa-id-module-eIDAS-v2/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas_v2/tasks/ReceiveAuthnResponseTask.java
@@ -0,0 +1,141 @@
+package at.gv.egovernment.moa.id.auth.modules.eidas_v2.tasks;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.opensaml.saml2.core.StatusCode;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants;
+import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionStorageConstants;
+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.engine.MOAeIDASChainingMetadataProvider;
+import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASEngineException;
+import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASResponseNotSuccessException;
+import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils;
+import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException;
+import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
+import at.gv.egovernment.moa.id.process.api.ExecutionContext;
+import at.gv.egovernment.moa.id.protocols.eidas.validator.eIDASResponseValidator;
+import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.MiscUtil;
+import eu.eidas.auth.commons.EidasStringUtil;
+import eu.eidas.auth.commons.protocol.IAuthenticationResponse;
+import eu.eidas.auth.engine.ProtocolEngineI;
+import eu.eidas.engine.exceptions.EIDASSAMLEngineException;
+
+@Component("ReceiveAuthnResponseTask")
+public class ReceiveAuthnResponseTask extends AbstractAuthServletTask {
+
+ @Autowired(required=true) MOAeIDASChainingMetadataProvider eIDASMetadataProvider;
+
+ @Override
+ public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) throws TaskExecutionException {
+
+ try{
+ //get SAML Response
+ 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);
+
+ }
+
+ //get MOASession
+ defaultTaskInitialization(request, executionContext);
+
+ //decode SAML response
+ byte[] decSamlToken = EidasStringUtil.decodeBytesFromBase64(base64SamlToken);
+
+ //get eIDAS SAML-engine
+ ProtocolEngineI engine = SAMLEngineUtils.createSAMLEngine(eIDASMetadataProvider);
+
+ //validate SAML token
+ IAuthenticationResponse samlResp = engine.unmarshallResponseAndValidate(decSamlToken,
+ request.getRemoteHost(),
+ Constants.CONFIG_PROPS_SKEWTIME_BEFORE,
+ Constants.CONFIG_PROPS_SKEWTIME_AFTER,
+ pendingReq.getAuthURL() + Constants.eIDAS_HTTP_ENDPOINT_METADATA);
+
+ if (samlResp.isEncrypted()) {
+ Logger.info("Received encrypted eIDAS SAML-Response.");
+ //TODO: check if additional decryption operation is required
+
+ }
+
+
+ //check response StatusCode
+ if (!samlResp.getStatusCode().equals(StatusCode.SUCCESS_URI)) {
+ Logger.info("Receice eIDAS Response with StatusCode:" + samlResp.getStatusCode()
+ + " Subcode:" + samlResp.getSubStatusCode() + " Msg:" + samlResp.getStatusMessage());
+ throw new EIDASResponseNotSuccessException("eIDAS.11", new Object[]{samlResp.getStatusMessage()});
+
+ }
+
+ // **********************************************************
+ // ******* MOA-ID specific response validation **********
+ // **********************************************************
+ String spCountry = authConfig.getBasicMOAIDConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_COUNTRYCODE, "AT");
+ eIDASResponseValidator.validateResponse(pendingReq, samlResp, spCountry);
+
+
+ // **********************************************************
+ // ******* Store resonse infos into session object **********
+ // **********************************************************
+
+ //update MOA-Session data with received information
+ Logger.debug("Store eIDAS response information into MOA-session.");
+
+ moasession.setQAALevel(samlResp.getLevelOfAssurance());
+
+ moasession.setGenericDataToSession(
+ AuthenticationSessionStorageConstants.eIDAS_ATTRIBUTELIST,
+ samlResp.getAttributes());
+
+ moasession.setGenericDataToSession(
+ AuthenticationSessionStorageConstants.eIDAS_RESPONSE,
+ decSamlToken);
+
+ //set issuer nation as PVP attribute into MOASession
+ moasession.setGenericDataToSession(PVPConstants.EID_ISSUING_NATION_NAME, samlResp.getCountry());
+
+ //store MOA-session to database
+ requestStoreage.storePendingRequest(pendingReq);
+
+ revisionsLogger.logEvent(pendingReq.getOnlineApplicationConfiguration(), pendingReq,
+ MOAIDEventConstants.AUTHPROCESS_PEPS_RECEIVED,
+ samlResp.getId());
+
+ } catch (MOAIDException e) {
+ throw new TaskExecutionException(pendingReq, "eIDAS Response processing FAILED.", e);
+
+ }catch (EIDASSAMLEngineException e) {
+ Logger.warn("eIDAS Response validation FAILED.", e);
+ Logger.debug("eIDAS response was: " + request.getParameter("SAMLResponse"));
+ revisionsLogger.logEvent(pendingReq.getOnlineApplicationConfiguration(), pendingReq,
+ MOAIDEventConstants.AUTHPROCESS_PEPS_RECEIVED_ERROR);
+ throw new TaskExecutionException(pendingReq, "eIDAS Response processing FAILED.",
+ new EIDASEngineException("eIDAS.09", new Object[]{e.getMessage()}, e));
+
+ } catch (MOADatabaseException e) {
+ revisionsLogger.logEvent(pendingReq.getOnlineApplicationConfiguration(), pendingReq,
+ MOAIDEventConstants.AUTHPROCESS_PEPS_RECEIVED_ERROR);
+ throw new TaskExecutionException(pendingReq, "eIDAS Response processing FAILED.",
+ new MOAIDException("init.04", new Object[]{""}, e));
+
+ } catch (Exception e) {
+ Logger.warn("eIDAS Response processing FAILED.", e);
+ revisionsLogger.logEvent(pendingReq.getOnlineApplicationConfiguration(), pendingReq,
+ MOAIDEventConstants.AUTHPROCESS_PEPS_RECEIVED_ERROR);
+ throw new TaskExecutionException(pendingReq, e.getMessage(),
+ new MOAIDException("eIDAS.10", new Object[]{e.getMessage()}, e));
+
+ }
+
+ }
+
+}