aboutsummaryrefslogtreecommitdiff
path: root/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules
diff options
context:
space:
mode:
authorThomas Knall <t.knall@datentechnik-innovation.com>2015-01-29 13:47:36 +0100
committerThomas Knall <t.knall@datentechnik-innovation.com>2015-01-29 13:47:36 +0100
commita3002d5966703675e982f5699b7a829d2dc22d84 (patch)
treef607f5c0ece9b96213abf770bef420409a626797 /id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules
parenta60b5f9a3c247056ab4b688d0e24c6d944b50b7e (diff)
downloadmoa-id-spss-a3002d5966703675e982f5699b7a829d2dc22d84.tar.gz
moa-id-spss-a3002d5966703675e982f5699b7a829d2dc22d84.tar.bz2
moa-id-spss-a3002d5966703675e982f5699b7a829d2dc22d84.zip
Integrate processes with module discovery.
- Fix AuthModuleImpl process resource uri. - Create package at.gv.egovernment.moa.id.auth.modules with submodule "internal" and "stork". - Rename AuthModuleImpl to DefaultAuthModuleImpl (placed in at.gv.egovernment.moa.id.auth.modules.internal). - Move stork specific tasks to "...stork.tasks" and internal modules to "...internal.tasks". - Fix bean classes in applicationContext.xml - Move process descriptions to at.gv.egovernment.moa.id.auth.modules.[internal|stork]. - Add STORKAuthModuleImpl.
Diffstat (limited to 'id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules')
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/DefaultAuthModuleImpl.java27
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/AbstractAuthServletTask.java379
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/CertificateReadRequestTask.java101
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/CreateIdentityLinkFormTask.java120
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GetForeignIDTask.java182
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GetMISSessionIDTask.java181
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/PrepareAuthBlockSignatureTask.java102
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyAuthenticationBlockTask.java246
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyCertificateTask.java164
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyIdentityLinkTask.java103
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/STORKAuthModuleImpl.java27
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/AbstractPepsConnectorWithLocalSigningTask.java257
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/CreateStorkAuthRequestFormTask.java114
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorHandleLocalSignResponseTask.java218
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorHandleResponseWithoutSignatureTask.java441
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorTask.java567
16 files changed, 3229 insertions, 0 deletions
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/DefaultAuthModuleImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/DefaultAuthModuleImpl.java
new file mode 100644
index 000000000..99c28fd7f
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/DefaultAuthModuleImpl.java
@@ -0,0 +1,27 @@
+package at.gv.egovernment.moa.id.auth.modules.internal;
+
+import org.apache.commons.lang3.StringUtils;
+
+import at.gv.egovernment.moa.id.moduls.moduleregistration.AuthModule;
+
+import com.datentechnik.process_engine.api.ExecutionContext;
+
+public class DefaultAuthModuleImpl implements AuthModule {
+
+ @Override
+ public int getPriority() {
+ // neutral priority between Integer.MIN_VALUE and Integer.MAX_VALUE
+ return 0;
+ }
+
+ @Override
+ public String selectProcess(ExecutionContext context) {
+ return StringUtils.isBlank((String) context.get("ccc")) ? "DefaultAuthentication" : null;
+ }
+
+ @Override
+ public String[] getProcessDefinitions() {
+ return new String[] { "classpath:at/gv/egovernment/moa/id/auth/modules/internal/DefaultAuthentication.process.xml" };
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/AbstractAuthServletTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/AbstractAuthServletTask.java
new file mode 100644
index 000000000..8a6c58953
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/AbstractAuthServletTask.java
@@ -0,0 +1,379 @@
+package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
+
+import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.FileItemFactory;
+import org.apache.commons.fileupload.FileUploadException;
+import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+import org.apache.commons.lang3.ArrayUtils;
+
+import at.gv.egovernment.moa.id.advancedlogging.StatisticLogger;
+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.exception.WrongParametersException;
+import at.gv.egovernment.moa.id.auth.servlet.AuthServlet;
+import at.gv.egovernment.moa.id.config.ConfigurationException;
+import at.gv.egovernment.moa.id.entrypoints.DispatcherServlet;
+import at.gv.egovernment.moa.id.storage.DBExceptionStoreImpl;
+import at.gv.egovernment.moa.id.storage.IExceptionStore;
+import at.gv.egovernment.moa.id.util.ServletUtils;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.MiscUtil;
+
+import com.datentechnik.process_engine.springweb.AbstractSpringWebSupportedTask;
+
+/**
+ * Task based counterpart to {@link AuthServlet}, providing the same utility methods (error handling, parameter parsing
+ * etc.).</p> The code has been taken from {@link AuthServlet}.
+ */
+public abstract class AbstractAuthServletTask extends AbstractSpringWebSupportedTask {
+
+ protected static final String ERROR_CODE_PARAM = "errorid";
+
+ protected void handleErrorNoRedirect(String errorMessage, Throwable exceptionThrown,
+ HttpServletRequest req, HttpServletResponse resp) {
+
+ if (null != errorMessage) {
+ Logger.error(errorMessage);
+ req.setAttribute("ErrorMessage", errorMessage);
+ }
+
+ if (null != exceptionThrown) {
+ if (null == errorMessage)
+ errorMessage = exceptionThrown.getMessage();
+ Logger.error(errorMessage, exceptionThrown);
+ req.setAttribute("ExceptionThrown", exceptionThrown);
+ }
+
+ if (Logger.isDebugEnabled()) {
+ req.setAttribute("LogLevel", "debug");
+ }
+
+
+ StatisticLogger logger = StatisticLogger.getInstance();
+ logger.logErrorOperation(exceptionThrown);
+
+
+ // forward this to errorpage-auth.jsp where the HTML error page is
+ // generated
+ ServletContext context = req.getServletContext();
+ RequestDispatcher dispatcher = context
+ .getRequestDispatcher("/errorpage-auth.jsp");
+ try {
+
+ resp.setHeader(HEADER_EXPIRES, HEADER_VALUE_EXPIRES);
+ resp.setHeader(HEADER_PRAGMA, HEADER_VALUE_PRAGMA);
+ resp.setHeader(HEADER_CACHE_CONTROL, HEADER_VALUE_CACHE_CONTROL);
+ resp.addHeader(HEADER_CACHE_CONTROL, HEADER_VALUE_CACHE_CONTROL_IE);
+
+ dispatcher.forward(req, resp);
+ } catch (ServletException e) {
+ Logger.error(e);
+ } catch (IOException e) {
+ Logger.error(e);
+ }
+ }
+
+ /**
+ * Handles an error. <br>>
+ * <ul>
+ * <li>Logs the error</li>
+ * <li>Places error message and exception thrown into the request as request
+ * attributes (to be used by <code>"/errorpage-auth.jsp"</code>)</li>
+ * <li>Sets HTTP status 500 (internal server error)</li>
+ * </ul>
+ *
+ * @param errorMessage
+ * error message
+ * @param exceptionThrown
+ * exception thrown
+ * @param req
+ * servlet request
+ * @param resp
+ * servlet response
+ */
+ protected void handleError(String errorMessage, Throwable exceptionThrown,
+ HttpServletRequest req, HttpServletResponse resp, String pendingRequestID) {
+
+ if (null != errorMessage) {
+ Logger.error(errorMessage);
+ req.setAttribute("ErrorMessage", errorMessage);
+ }
+
+ if (null != exceptionThrown) {
+ if (null == errorMessage)
+ errorMessage = exceptionThrown.getMessage();
+ Logger.error(errorMessage, exceptionThrown);
+ req.setAttribute("ExceptionThrown", exceptionThrown);
+ }
+
+ if (Logger.isDebugEnabled()) {
+ req.setAttribute("LogLevel", "debug");
+ }
+
+ if (!(exceptionThrown instanceof MOAIDException)) {
+ Logger.error("Receive an internal error: Message=" + exceptionThrown.getMessage(), exceptionThrown);
+
+ }
+
+ IExceptionStore store = DBExceptionStoreImpl.getStore();
+ String id = store.storeException(exceptionThrown);
+
+ if (id != null && MiscUtil.isNotEmpty(pendingRequestID)) {
+
+ String redirectURL = null;
+
+ redirectURL = ServletUtils.getBaseUrl(req);
+ redirectURL += "/dispatcher?" + ERROR_CODE_PARAM + "=" + id
+ + "&" + DispatcherServlet.PARAM_TARGET_PENDINGREQUESTID + "=" + pendingRequestID;
+
+ resp.setContentType("text/html");
+ resp.setStatus(302);
+
+ resp.addHeader("Location", redirectURL);
+ Logger.debug("REDIRECT TO: " + redirectURL);
+
+ return;
+
+ } else {
+
+ //Exception can not be stored in database
+ handleErrorNoRedirect(errorMessage, exceptionThrown, req, resp);
+ }
+ }
+
+ /**
+ * Handles a <code>WrongParametersException</code>.
+ *
+ * @param req
+ * servlet request
+ * @param resp
+ * servlet response
+ */
+ protected void handleWrongParameters(WrongParametersException ex,
+ HttpServletRequest req, HttpServletResponse resp) {
+ Logger.error(ex.toString());
+ req.setAttribute("WrongParameters", ex.getMessage());
+
+ // forward this to errorpage-auth.jsp where the HTML error page is
+ // generated
+ ServletContext context = req.getServletContext();
+ RequestDispatcher dispatcher = context
+ .getRequestDispatcher("/errorpage-auth.jsp");
+ try {
+ setNoCachingHeaders(resp);
+ dispatcher.forward(req, resp);
+ } catch (ServletException e) {
+ Logger.error(e);
+ } catch (IOException e) {
+ Logger.error(e);
+ }
+ }
+
+ /**
+ * Logs all servlet parameters for debugging purposes.
+ */
+ protected void logParameters(HttpServletRequest req) {
+ for (Enumeration params = req.getParameterNames(); params
+ .hasMoreElements();) {
+ String parname = (String) params.nextElement();
+ Logger.debug("Parameter " + parname + req.getParameter(parname));
+ }
+ }
+
+ /**
+ * Parses the request input stream for parameters, assuming parameters are
+ * encoded UTF-8 (no standard exists how browsers should encode them).
+ *
+ * @param req
+ * servlet request
+ *
+ * @return mapping parameter name -> value
+ *
+ * @throws IOException
+ * if parsing request parameters fails.
+ *
+ * @throws FileUploadException
+ * if parsing request parameters fails.
+ */
+ protected Map<String, String> getParameters(HttpServletRequest req) throws IOException,
+ FileUploadException {
+
+ Map<String, String> parameters = new HashMap<String, String>();
+
+ if (ServletFileUpload.isMultipartContent(req)) {
+ // request is encoded as mulitpart/form-data
+ FileItemFactory factory = new DiskFileItemFactory();
+ ServletFileUpload upload = null;
+ upload = new ServletFileUpload(factory);
+ List items = null;
+ items = upload.parseRequest(req);
+ for (int i = 0; i < items.size(); i++) {
+ FileItem item = (FileItem) items.get(i);
+ if (item.isFormField()) {
+ // Process only form fields - no file upload items
+ String logString = item.getString("UTF-8");
+
+ // TODO use RegExp
+ String startS = "<pr:Identification><pr:Value>";
+ String endS = "</pr:Value><pr:Type>urn:publicid:gv.at:baseid</pr:Type>";
+ String logWithMaskedBaseid = logString;
+ int start = logString.indexOf(startS);
+ if (start > -1) {
+ int end = logString.indexOf(endS);
+ if (end > -1) {
+ logWithMaskedBaseid = logString.substring(0, start);
+ logWithMaskedBaseid += startS;
+ logWithMaskedBaseid += "xxxxxxxxxxxxxxxxxxxxxxxx";
+ logWithMaskedBaseid += logString.substring(end,
+ logString.length());
+ }
+ }
+ parameters
+ .put(item.getFieldName(), item.getString("UTF-8"));
+ Logger.debug("Processed multipart/form-data request parameter: \nName: "
+ + item.getFieldName()
+ + "\nValue: "
+ + logWithMaskedBaseid);
+ }
+ }
+ }
+
+ else {
+ // request is encoded as application/x-www-urlencoded
+ // [tknall]: we must not consume request body input stream once servlet-api request parameters have been accessed
+
+ /*
+ InputStream in = req.getInputStream();
+
+ String paramName;
+ String paramValueURLEncoded;
+ do {
+ paramName = new String(readBytesUpTo(in, '='));
+ if (paramName.length() > 0) {
+ paramValueURLEncoded = readBytesUpTo(in, '&');
+ String paramValue = URLDecoder.decode(paramValueURLEncoded,
+ "UTF-8");
+ parameters.put(paramName, paramValue);
+ }
+ } while (paramName.length() > 0);
+ in.close();
+ */
+
+ Iterator<Entry<String, String[]>> requestParamIt = req.getParameterMap().entrySet().iterator();
+ while (requestParamIt.hasNext()) {
+ Entry<String, String[]> entry = requestParamIt.next();
+ String key = entry.getKey();
+ String[] values = entry.getValue();
+ // take the last value from the value array since the legacy code above also does it this way
+ parameters.put(key, ArrayUtils.isEmpty(values) ? null : values[values.length-1]);
+ }
+
+ }
+
+ return parameters;
+ }
+
+ /**
+ * Reads bytes up to a delimiter, consuming the delimiter.
+ *
+ * @param in
+ * input stream
+ * @param delimiter
+ * delimiter character
+ * @return String constructed from the read bytes
+ * @throws IOException
+ */
+ protected String readBytesUpTo(InputStream in, char delimiter)
+ throws IOException {
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ boolean done = false;
+ int b;
+ while (!done && (b = in.read()) >= 0) {
+ if (b == delimiter)
+ done = true;
+ else
+ bout.write(b);
+ }
+ return bout.toString();
+ }
+
+ /**
+ * Sets response headers that prevent caching (code taken from {@link AuthServlet}).
+ *
+ * @param resp
+ * The HttpServletResponse.
+ */
+ public void setNoCachingHeaders(HttpServletResponse resp) {
+ resp.setHeader(HEADER_EXPIRES, HEADER_VALUE_EXPIRES);
+ resp.setHeader(HEADER_PRAGMA, HEADER_VALUE_PRAGMA);
+ resp.setHeader(HEADER_CACHE_CONTROL, HEADER_VALUE_CACHE_CONTROL);
+ resp.addHeader(HEADER_CACHE_CONTROL, HEADER_VALUE_CACHE_CONTROL_IE);
+ }
+
+ /**
+ * Adds a parameter to a URL.
+ *
+ * @param url
+ * the URL
+ * @param paramname
+ * parameter name
+ * @param paramvalue
+ * parameter value
+ * @return the URL with parameter added
+ */
+ protected static String addURLParameter(String url, String paramname,
+ String paramvalue) {
+ String param = paramname + "=" + paramvalue;
+ if (url.indexOf("?") < 0)
+ return url + "?" + param;
+ else
+ return url + "&" + param;
+ }
+
+ /**
+ * Checks if HTTP requests are allowed
+ *
+ * @param authURL
+ * requestURL
+ * @throws AuthenticationException
+ * if HTTP requests are not allowed
+ * @throws ConfigurationException
+ */
+ protected void checkIfHTTPisAllowed(String authURL)
+ throws AuthenticationException, ConfigurationException {
+ // check if HTTP Connection may be allowed (through
+ // FRONTEND_SERVLETS_ENABLE_HTTP_CONNECTION_PROPERTY)
+
+ //Removed from MOA-ID 2.0 config
+// String boolStr = AuthConfigurationProvider
+// .getInstance()
+// .getGenericConfigurationParameter(
+// AuthConfigurationProvider.FRONTEND_SERVLETS_ENABLE_HTTP_CONNECTION_PROPERTY);
+ if ((!authURL.startsWith("https:"))
+ //&& (false == BoolUtils.valueOf(boolStr))
+ )
+ throw new AuthenticationException("auth.07", new Object[] { authURL
+ + "*" });
+
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/CertificateReadRequestTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/CertificateReadRequestTask.java
new file mode 100644
index 000000000..4af07950b
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/CertificateReadRequestTask.java
@@ -0,0 +1,101 @@
+package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
+
+import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang3.BooleanUtils;
+
+import at.gv.egovernment.moa.id.auth.AuthenticationServer;
+import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder;
+import at.gv.egovernment.moa.id.auth.builder.InfoboxReadRequestBuilderCertificate;
+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.exception.WrongParametersException;
+import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
+import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
+import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
+import at.gv.egovernment.moa.id.util.ServletUtils;
+import at.gv.egovernment.moa.logging.Logger;
+
+import com.datentechnik.process_engine.api.ExecutionContext;
+
+/**
+ * Creates {@code InfoBoxReadRequest} in order to read the subject's certificates.<p/>
+ * In detail:
+ * <ul>
+ * <li>Renames the moa session id.</li>
+ * <li>Creates {@code InfoBoxReadRequest} in order to read the subject's certificates.</li>
+ * <li>Responds with {@code InfoBoxReadRequest} (for CCE), {@code DataURL} is {@code /VerifyCertificate}</li>
+ * </ul>
+ * Expects:
+ * <ul>
+ * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}</li>
+ * </ul>
+ * Result:
+ * <ul>
+ * <li>Responds with {@code InfoBoxReadRequest} (for CCE), {@code DataURL} is {@code {/VerifyCertificate}</li>
+ * </ul>
+ * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.VerifyIdentityLinkServlet}.
+ * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
+ *
+ */
+public class CertificateReadRequestTask extends AbstractAuthServletTask {
+
+ @Override
+ public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
+ throws Exception {
+
+ // TODO[branch]: Foreign citizen or mandate mode; respond with IRR for certificates, dataURL = "/VerifyCertificate"
+ Logger.info("Send InfoboxReadRequest to BKU to get signer certificate.");
+
+ setNoCachingHeaders(resp);
+
+ String pendingRequestID = null;
+
+ try {
+
+ String sessionID = StringEscapeUtils.escapeHtml(req.getParameter(PARAM_SESSIONID));
+
+ // check parameter
+ if (!ParamValidatorUtils.isValidSessionID(sessionID)) {
+ throw new WrongParametersException("CertificateReadRequestTask", PARAM_SESSIONID, "auth.12");
+ }
+
+ pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(sessionID);
+
+ AuthenticationSession session = AuthenticationServer.getSession(sessionID);
+
+ boolean useMandate = session.getUseMandate();
+ boolean identityLinkAvailable = BooleanUtils.isTrue((Boolean) executionContext.get("identityLinkAvailable"));
+
+ if (!identityLinkAvailable && useMandate) {
+ Logger.error("Online-Mandate Mode for foreign citizencs not supported.");
+ throw new AuthenticationException("auth.13", null);
+ }
+
+ // change MOASessionID
+ AuthenticationSessionStoreage.changeSessionID(session);
+
+ // create the InfoboxReadRequest to get the certificate
+ String infoboxReadRequest = new InfoboxReadRequestBuilderCertificate().build(true);
+
+ // build dataurl (to the VerifyCertificateSerlvet)
+ String dataurl = new DataURLBuilder().buildDataURL(session.getAuthURL(), REQ_VERIFY_CERTIFICATE,
+ session.getSessionID());
+
+ ServletUtils.writeCreateXMLSignatureRequest(resp, infoboxReadRequest,
+ AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "VerifyIdentityLink", dataurl);
+
+ } catch (MOAIDException ex) {
+ handleError(null, ex, req, resp, pendingRequestID);
+ } finally {
+ ConfigurationDBUtils.closeSession();
+ }
+
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/CreateIdentityLinkFormTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/CreateIdentityLinkFormTask.java
new file mode 100644
index 000000000..d88042528
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/CreateIdentityLinkFormTask.java
@@ -0,0 +1,120 @@
+package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
+
+import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
+
+import java.io.PrintWriter;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang3.ObjectUtils;
+
+import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants;
+import at.gv.egovernment.moa.id.auth.builder.StartAuthenticationBuilder;
+import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
+import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
+import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
+import at.gv.egovernment.moa.id.auth.servlet.GenerateIFrameTemplateServlet;
+import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
+import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
+import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.MiscUtil;
+import at.gv.egovernment.moa.util.StringUtils;
+
+import com.datentechnik.process_engine.api.ExecutionContext;
+
+/**
+ * Creates a http form including an embedded {@code InfoBoxReadRequest} for reading the identity link.<p/>
+ * In detail:
+ * <ul>
+ * <li>Renames the moa session id.</li>
+ * <li>Removes ExecutionContext property {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}.</li>
+ * <li>Creates the http form mentioned above.</li>
+ * <li>Returns the http form via HttpServletResponse.</li>
+ * </ul>
+ * Expects:
+ * <ul>
+ * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID} <strong>or</strong></li>
+ * <li>ExecutionContext property {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID} (in case of legacy authentication without CCE selection, where the moa session is not provided by request parameter).</li>
+ * </ul>
+ * Result:
+ * <ul>
+ * <li>The identity link form via HttpServletResponse.</li>
+ * </ul>
+ * Possible branches:
+ * <ul>
+ * <li>In case of STORK authentication
+ * <ul>
+ * <li>Creates STORK auth SAML request.</li>
+ * <li>Creates and returns a form for submitting the SAML request to the CPEPS (post binding).</li>
+ * <li>Returns the form via HttpServletResponse.</li>
+ * </ul>
+ * </li>
+ * </ul>
+ * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.GenerateIFrameTemplateServlet}.
+ * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
+ *
+ */
+public class CreateIdentityLinkFormTask extends AbstractAuthServletTask {
+
+ @Override
+ public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
+ throws Exception {
+
+ String pendingRequestID = null;
+ String moasessionid = StringEscapeUtils.escapeHtml(ObjectUtils.defaultIfNull(req.getParameter(PARAM_SESSIONID), (String) executionContext.get(PARAM_SESSIONID)));
+ AuthenticationSession moasession = null;
+ try {
+
+ if (MiscUtil.isEmpty(moasessionid)) {
+ Logger.warn("MOASessionID is empty.");
+ throw new MOAIDException("auth.18", new Object[] {});
+ }
+
+ try {
+
+ pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(moasessionid);
+ moasession = AuthenticationSessionStoreage.getSession(moasessionid);
+ AuthenticationSessionStoreage.changeSessionID(moasession);
+ executionContext.remove(PARAM_SESSIONID);
+
+ } catch (MOADatabaseException e) {
+ Logger.info("MOASession with SessionID=" + moasessionid + " is not found in Database");
+ throw new MOAIDException("init.04", new Object[] { moasessionid });
+
+ } catch (Throwable e) {
+ Logger.info("No HTTP Session found!");
+ throw new MOAIDException("auth.18", new Object[] {});
+ }
+
+ StartAuthenticationBuilder startauth = StartAuthenticationBuilder.getInstance();
+ String getIdentityLinkForm = startauth.build(moasession, req, resp);
+
+ if (!StringUtils.isEmpty(getIdentityLinkForm)) {
+ resp.setContentType("text/html;charset=UTF-8");
+ PrintWriter out = new PrintWriter(resp.getOutputStream());
+ out.print(getIdentityLinkForm);
+ out.flush();
+ Logger.debug("Finished GET " + GenerateIFrameTemplateServlet.class);
+ }
+
+ } catch (WrongParametersException ex) {
+ handleWrongParameters(ex, req, resp);
+ }
+
+ catch (MOAIDException ex) {
+ handleError(null, ex, req, resp, pendingRequestID);
+
+ } catch (Exception e) {
+ Logger.error("CreateIdentityLinkFormTask has an interal Error.", e);
+
+ }
+
+ finally {
+ ConfigurationDBUtils.closeSession();
+ }
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GetForeignIDTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GetForeignIDTask.java
new file mode 100644
index 000000000..a661abc95
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GetForeignIDTask.java
@@ -0,0 +1,182 @@
+package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
+
+import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.security.cert.CertificateException;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.transform.TransformerException;
+
+import org.apache.commons.fileupload.FileUploadException;
+import org.apache.commons.lang.StringEscapeUtils;
+import org.w3c.dom.Element;
+
+import at.gv.egovernment.moa.id.auth.AuthenticationServer;
+import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder;
+import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
+import at.gv.egovernment.moa.id.auth.data.CreateXMLSignatureResponse;
+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.exception.ParseException;
+import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
+import at.gv.egovernment.moa.id.auth.parser.CreateXMLSignatureResponseParser;
+import at.gv.egovernment.moa.id.auth.parser.IdentityLinkAssertionParser;
+import at.gv.egovernment.moa.id.client.SZRGWClientException;
+import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
+import at.gv.egovernment.moa.id.moduls.ModulUtils;
+import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants;
+import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
+import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.DOMUtils;
+import at.gv.util.xsd.srzgw.CreateIdentityLinkResponse;
+
+import com.datentechnik.process_engine.api.ExecutionContext;
+
+/**
+ * Evaluates the {@code CreateXMLSignatureResponse}, extracts signature and certificate and asks the SZR Gateway for an identity link.<p/>
+ * In detail:
+ * <ul>
+ * <li>Renames the moa session id.</li>
+ * <li>Parses the CreateXMLSignatureResponse retrieved from POST parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_XMLRESPONSE}.</li>
+ * <li>Extracts signature and signer certificate.</li>
+ * <li>Send request to SZR Gateway in order to get an identity link.</li>
+ * <li>Updates moa session (sets identity link, QAA level 4, authentication data and foreigner flag).</li>
+ * <li>Redirects back to {@code /dispatcher} in order to finalize authentication.</li>
+ * </ul>
+ * Expects:
+ * <ul>
+ * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}</li>
+ * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_XMLRESPONSE} containing a {@code CreateXMLSignatureResponse}.</li>
+ * </ul>
+ * Result:
+ * <ul>
+ * <li>Identity link, QAA level 4 and foreigner flag put into moa session.</li>
+ * <li>Redirect to {@code /dispatcher}.</li>
+ * </ul>
+ * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.GetForeignIDServlet}.
+ * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
+ *
+ */
+public class GetForeignIDTask extends AbstractAuthServletTask {
+
+ @Override
+ public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
+ throws Exception {
+
+ Logger.debug("POST GetForeignIDServlet");
+
+ setNoCachingHeaders(resp);
+
+ Map<String, String> parameters;
+
+ try {
+ parameters = getParameters(req);
+ } catch (FileUploadException e) {
+ Logger.error("Parsing mulitpart/form-data request parameters failed: " + e.getMessage());
+ throw new IOException(e.getMessage());
+ }
+
+ String sessionID = StringEscapeUtils.escapeHtml(req.getParameter(PARAM_SESSIONID));
+ String pendingRequestID = null;
+ String redirectURL = null;
+ AuthenticationSession session = null;
+ try {
+ // check parameter
+ if (!ParamValidatorUtils.isValidSessionID(sessionID)) {
+ throw new WrongParametersException("GetForeignID", PARAM_SESSIONID, "auth.12");
+ }
+ String xmlCreateXMLSignatureResponse = (String) parameters.get(PARAM_XMLRESPONSE);
+ if (!ParamValidatorUtils.isValidXMLDocument(xmlCreateXMLSignatureResponse)) {
+ throw new WrongParametersException("GetForeignID", PARAM_XMLRESPONSE, "auth.12");
+ }
+ pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(sessionID);
+ session = AuthenticationServer.getSession(sessionID);
+
+ // change MOASessionID
+ sessionID = AuthenticationSessionStoreage.changeSessionID(session);
+
+ Logger.debug(xmlCreateXMLSignatureResponse);
+
+ CreateXMLSignatureResponse csresp = new CreateXMLSignatureResponseParser(xmlCreateXMLSignatureResponse)
+ .parseResponseDsig();
+
+ try {
+ String serializedAssertion = DOMUtils.serializeNode(csresp.getDsigSignature());
+ session.setAuthBlock(serializedAssertion);
+
+ } catch (TransformerException e) {
+ throw new ParseException("parser.04", new Object[] { REQ_VERIFY_AUTH_BLOCK, PARAM_XMLRESPONSE });
+
+ } catch (IOException e) {
+ throw new ParseException("parser.04", new Object[] { REQ_VERIFY_AUTH_BLOCK, PARAM_XMLRESPONSE });
+
+ }
+
+ Element signature = csresp.getDsigSignature();
+
+ try {
+ session.setSignerCertificate(AuthenticationServer.getCertificateFromXML(signature));
+ } catch (CertificateException e) {
+ Logger.error("Could not extract certificate from CreateXMLSignatureResponse");
+ throw new MOAIDException("auth.14", null);
+ }
+
+ // make SZR request to the identity link
+ CreateIdentityLinkResponse response = AuthenticationServer.getInstance().getIdentityLink(signature);
+
+ if (null != response.getErrorResponse()) {
+ // TODO fix exception parameter
+ throw new SZRGWClientException("service.08", (String) response.getErrorResponse().getErrorCode(),
+ (String) response.getErrorResponse().getInfo());
+ } else {
+ IdentityLinkAssertionParser ilParser = new IdentityLinkAssertionParser(new ByteArrayInputStream(
+ response.getIdentityLink()));
+ IdentityLink identitylink = ilParser.parseIdentityLink();
+ session.setIdentityLink(identitylink);
+
+ // set QAA Level four in case of card authentifcation
+ session.setQAALevel(PVPConstants.STORK_QAA_1_4);
+
+ AuthenticationServer.getInstance().getForeignAuthenticationData(session);
+
+ // session is implicit stored in changeSessionID!!!!
+ String newMOASessionID = AuthenticationSessionStoreage.changeSessionID(session);
+
+ Logger.info("Changed MOASession " + sessionID + " to Session " + newMOASessionID);
+ Logger.info("Daten angelegt zu MOASession " + newMOASessionID);
+
+ redirectURL = new DataURLBuilder().buildDataURL(session.getAuthURL(),
+ ModulUtils.buildAuthURL(session.getModul(), session.getAction(), pendingRequestID),
+ newMOASessionID);
+ redirectURL = resp.encodeRedirectURL(redirectURL);
+
+ // TODO[branch]: Final step back to /dispatcher
+
+ try {
+ AuthenticationSessionStoreage.storeSession(session);
+ } catch (MOADatabaseException e) {
+ throw new MOAIDException("Session store error", null);
+ }
+
+ resp.setContentType("text/html");
+ resp.setStatus(302);
+ resp.addHeader("Location", redirectURL);
+ Logger.debug("REDIRECT TO: " + redirectURL);
+ }
+
+ } catch (MOAIDException ex) {
+ handleError(null, ex, req, resp, pendingRequestID);
+
+ } catch (Exception e) {
+ Logger.error("GetForeignIDServlet has an interal Error.", e);
+
+ }
+
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GetMISSessionIDTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GetMISSessionIDTask.java
new file mode 100644
index 000000000..6e4d77b17
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GetMISSessionIDTask.java
@@ -0,0 +1,181 @@
+package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
+
+import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
+import iaik.pki.PKIException;
+
+import java.security.GeneralSecurityException;
+import java.util.List;
+
+import javax.net.ssl.SSLSocketFactory;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.xml.sax.SAXException;
+
+import at.gv.egovernment.moa.id.auth.AuthenticationServer;
+import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder;
+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.exception.WrongParametersException;
+import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
+import at.gv.egovernment.moa.id.config.ConnectionParameter;
+import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
+import at.gv.egovernment.moa.id.moduls.ModulUtils;
+import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants;
+import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
+import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
+import at.gv.egovernment.moa.id.util.SSLUtils;
+import at.gv.egovernment.moa.id.util.client.mis.simple.MISMandate;
+import at.gv.egovernment.moa.id.util.client.mis.simple.MISSimpleClient;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.DOMUtils;
+
+import com.datentechnik.process_engine.api.ExecutionContext;
+
+/**
+ * Retrieves a mandate from the online mandate issuing service.<p/>
+ * In detail:
+ * <ul>
+ * <li>Renames the moa session id.</li>
+ * <li>Retrieves the mandate referenced within the moa session from the online (external) mandate issuing service.</li>
+ * <li>Verifies the mandate.</li>
+ * <li>Puts mandate into moa session.</li>
+ * <li>Redirects back to {@code /dispatcher} in order to finalize the authentication.</li>
+ * </ul>
+ * Expects:
+ * <ul>
+ * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}</li>
+ * </ul>
+ * Result:
+ * <ul>
+ * <li>Mandate put into moa session.</li>
+ * <li>Redirect to {@code /dispatcher}.</li>
+ * </ul>
+ * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.GetMISSessionIDServlet}.
+ * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
+ *
+ */
+public class GetMISSessionIDTask extends AbstractAuthServletTask {
+
+ @Override
+ public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
+ throws Exception {
+
+ Logger.debug("POST GetMISSessionIDServlet");
+
+ String sessionID = req.getParameter(PARAM_SESSIONID);
+
+ // escape parameter strings
+ sessionID = StringEscapeUtils.escapeHtml(sessionID);
+
+ AuthenticationSession session = null;
+ String pendingRequestID = null;
+ try {
+ // check parameter
+ if (!ParamValidatorUtils.isValidSessionID(sessionID))
+ throw new WrongParametersException("VerifyCertificate",
+ PARAM_SESSIONID, "auth.12");
+
+ pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(sessionID);
+
+ session = AuthenticationServer.getSession(sessionID);
+
+ //change MOASessionID
+ sessionID = AuthenticationSessionStoreage.changeSessionID(session);
+
+ String misSessionID = session.getMISSessionID();
+
+ AuthConfigurationProvider authConf = AuthConfigurationProvider
+ .getInstance();
+ ConnectionParameter connectionParameters = authConf
+ .getOnlineMandatesConnectionParameter();
+ SSLSocketFactory sslFactory = SSLUtils.getSSLSocketFactory(
+ AuthConfigurationProvider.getInstance(),
+ connectionParameters);
+
+ List<MISMandate> list = MISSimpleClient.sendGetMandatesRequest(
+ connectionParameters.getUrl(), misSessionID, sslFactory);
+
+ if (list == null || list.size() == 0) {
+ Logger.error("Keine Vollmacht gefunden.");
+ throw new AuthenticationException("auth.15", null);
+ }
+
+ // for now: list contains only one element
+ MISMandate mandate = (MISMandate) list.get(0);
+
+ // TODO[tlenz]: UTF-8 ?
+ String sMandate = new String(mandate.getMandate());
+ if (sMandate == null || sMandate.compareToIgnoreCase("") == 0) {
+ Logger.error("Mandate is empty.");
+ throw new AuthenticationException("auth.15",
+ new Object[] { GET_MIS_SESSIONID });
+ }
+
+ //check if it is a parsable XML
+ byte[] byteMandate = mandate.getMandate();
+ // TODO[tlenz]: UTF-8 ?
+ String stringMandate = new String(byteMandate);
+ DOMUtils.parseDocument(stringMandate, false,
+ null, null).getDocumentElement();
+
+ // extract RepresentationType
+ AuthenticationServer.getInstance().verifyMandate(session, mandate);
+
+ session.setMISMandate(mandate);
+ session.setAuthenticatedUsed(false);
+ session.setAuthenticated(true);
+
+ //set QAA Level four in case of card authentifcation
+ session.setQAALevel(PVPConstants.STORK_QAA_1_4);
+
+ String oldsessionID = session.getSessionID();
+
+ //Session is implicite stored in changeSessionID!!!
+ String newMOASessionID = AuthenticationSessionStoreage.changeSessionID(session);
+
+ Logger.info("Changed MOASession " + oldsessionID + " to Session " + newMOASessionID);
+ Logger.info("Daten angelegt zu MOASession " + newMOASessionID);
+
+ String redirectURL = new DataURLBuilder().buildDataURL(
+ session.getAuthURL(),
+ ModulUtils.buildAuthURL(session.getModul(),
+ session.getAction(), pendingRequestID), newMOASessionID);
+ redirectURL = resp.encodeRedirectURL(redirectURL);
+
+ // TODO[branch]: Final step back to /dispatcher
+
+ resp.setContentType("text/html");
+ resp.setStatus(302);
+ resp.addHeader("Location", redirectURL);
+ Logger.debug("REDIRECT TO: " + redirectURL);
+
+ } catch (MOAIDException ex) {
+ handleError(null, ex, req, resp, pendingRequestID);
+
+ } catch (GeneralSecurityException ex) {
+ handleError(null, ex, req, resp, pendingRequestID);
+
+ } catch (PKIException e) {
+ handleError(null, e, req, resp, pendingRequestID);
+
+ } catch (SAXException e) {
+ handleError(null, e, req, resp, pendingRequestID);
+
+ } catch (ParserConfigurationException e) {
+ handleError(null, e, req, resp, pendingRequestID);
+
+ } catch (Exception e) {
+ Logger.error("MISMandateValidation has an interal Error.", e);
+
+ }
+ finally {
+ ConfigurationDBUtils.closeSession();
+ }
+
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/PrepareAuthBlockSignatureTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/PrepareAuthBlockSignatureTask.java
new file mode 100644
index 000000000..d7a95bfcc
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/PrepareAuthBlockSignatureTask.java
@@ -0,0 +1,102 @@
+package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
+
+import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang.StringEscapeUtils;
+
+import at.gv.egovernment.moa.id.auth.AuthenticationServer;
+import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
+import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
+import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
+import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
+import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
+import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
+import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
+import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
+import at.gv.egovernment.moa.id.util.ServletUtils;
+import at.gv.egovernment.moa.logging.Logger;
+
+import com.datentechnik.process_engine.api.ExecutionContext;
+
+/**
+ * Creates {@code CreateXMLSignatureRequest} for auth block signature.<p/>
+ * In detail:
+ * <ul>
+ * <li>Renames the moa session id.</li>
+ * <li>Creates {@code CreateXMLSignatureRequest} for auth block signature.</li>
+ * <li>Responds with {@code CreateXMLSignatureRequest} (for CCE), {@code DataURL} is {@code {/VerifyAuthBlock}</li>
+ * </ul>
+ * Expects:
+ * <ul>
+ * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}</li>
+ * </ul>
+ * Result:
+ * <ul>
+ * <li>Responds with {@code CreateXMLSignatureRequest} (for CCE), {@code DataURL} is {@code {/VerifyAuthBlock}</li>
+ * </ul>
+ * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.VerifyIdentityLinkServlet}.
+ * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
+ *
+ */
+public class PrepareAuthBlockSignatureTask extends AbstractAuthServletTask {
+
+ @Override
+ public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
+ throws Exception {
+ // note: code taken from at.gv.egovernment.moa.id.auth.servlet.VerifyIdentityLinkServlet
+
+ Logger.debug("Process IdentityLink");
+
+ setNoCachingHeaders(resp);
+
+ String pendingRequestID = null;
+
+ try {
+
+ String sessionID = StringEscapeUtils.escapeHtml(req.getParameter(PARAM_SESSIONID));
+
+ // check parameter
+ if (!ParamValidatorUtils.isValidSessionID(sessionID)) {
+ throw new WrongParametersException("VerifyIdentityLink", PARAM_SESSIONID, "auth.12");
+ }
+
+ pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(sessionID);
+
+ AuthenticationSession session = AuthenticationServer.getSession(sessionID);
+
+ // change MOASessionID
+ sessionID = AuthenticationSessionStoreage.changeSessionID(session);
+
+ Logger.info("Normal");
+
+ // TODO[branch]: Default behaviour; respond with CXSR for authblock signature, dataURL "/VerifyAuthBlock"
+
+ OAAuthParameter oaParam = AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(
+ session.getPublicOAURLPrefix());
+ AuthConfigurationProvider authConf = AuthConfigurationProvider.getInstance();
+
+ String createXMLSignatureRequest = AuthenticationServer.getInstance()
+ .getCreateXMLSignatureRequestAuthBlockOrRedirect(session, authConf, oaParam);
+
+ AuthenticationSessionStoreage.storeSession(session);
+
+ ServletUtils.writeCreateXMLSignatureRequestOrRedirect(resp, session,
+ createXMLSignatureRequest, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT,
+ "VerifyIdentityLink");
+
+ } catch (MOAIDException ex) {
+ handleError(null, ex, req, resp, pendingRequestID);
+
+ } catch (Exception e) {
+ Logger.error("IdentityLinkValidation has an interal Error.", e);
+ }
+
+ finally {
+ ConfigurationDBUtils.closeSession();
+ }
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyAuthenticationBlockTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyAuthenticationBlockTask.java
new file mode 100644
index 000000000..8c59c39ba
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyAuthenticationBlockTask.java
@@ -0,0 +1,246 @@
+package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
+
+import iaik.pki.PKIException;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.util.List;
+import java.util.Map;
+
+import javax.net.ssl.SSLSocketFactory;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.transform.TransformerException;
+
+import org.apache.commons.fileupload.FileUploadException;
+import org.apache.commons.lang.StringEscapeUtils;
+import org.w3c.dom.Element;
+
+import at.gv.egovernment.moa.id.auth.AuthenticationServer;
+import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder;
+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.MISSimpleClientException;
+import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
+import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
+import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
+import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
+import at.gv.egovernment.moa.id.config.ConnectionParameter;
+import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
+import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
+import at.gv.egovernment.moa.id.moduls.ModulUtils;
+import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
+import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
+import at.gv.egovernment.moa.id.util.SSLUtils;
+import at.gv.egovernment.moa.id.util.client.mis.simple.MISSessionId;
+import at.gv.egovernment.moa.id.util.client.mis.simple.MISSimpleClient;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.DOMUtils;
+
+import com.datentechnik.process_engine.api.ExecutionContext;
+import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
+
+/**
+ * Verifies the signed authentication block (provided as {@code CreateXMLSignatureResponse}).<p/>
+ * In detail:
+ * <ul>
+ * <li>Renames the moa session id.</li>
+ * <li>Takes the {@code CreateXMLSignatureResponse} from POST parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_XMLRESPONSE}.</li>
+ * <li>Verifies the {@code CreateXMLSignatureResponse}.</li>
+ * <li>Updates moa session.</li>
+ * <li>Redirects back to {@code /dispatcher} in order to finalize the authentication.</li>
+ * </ul>
+ * Expects:
+ * <ul>
+ * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}</li>
+ * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_XMLRESPONSE} containing a {@code CreateXMLSignatureResponse}.</li>
+ * </ul>
+ * Result:
+ * <ul>
+ * <li>Authentication data put into moa session.</li>
+ * <li>Redirect to {@code /dispatcher}.</li>
+ * </ul>
+ * Possible branches:
+ * <ul>
+ * <li>In case of mandate mode
+ * <ul>
+ * <li>Creates a mandate session at the external mandate issuing service.</li>
+ * <li>Redirects the user's browser to the online mandate issuing service GUI.</li>
+ * </ul>
+ * </li>
+ * </ul>
+ * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.VerifyAuthenticationBlockServlet}.
+ * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
+ *
+ */
+public class VerifyAuthenticationBlockTask extends AbstractAuthServletTask {
+
+ @Override
+ public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
+ throws Exception {
+
+ // note: code taken from at.gv.egovernment.moa.id.auth.servlet.VerifyAuthenticationBlockServlet
+
+ Logger.debug("POST VerifyAuthenticationBlock");
+
+ String pendingRequestID = null;
+
+ Map<String, String> parameters;
+ try
+ {
+ parameters = getParameters(req);
+ } catch (FileUploadException e)
+ {
+ Logger.error("Parsing mulitpart/form-data request parameters failed: " + e.getMessage());
+ throw new IOException(e.getMessage());
+
+ }
+ String sessionID = req.getParameter(PARAM_SESSIONID);
+ String createXMLSignatureResponse = (String)parameters.get(PARAM_XMLRESPONSE);
+
+ // escape parameter strings
+ sessionID = StringEscapeUtils.escapeHtml(sessionID);
+ pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(sessionID);
+
+ String redirectURL = null;
+ try {
+ // check parameter
+ if (!ParamValidatorUtils.isValidSessionID(sessionID))
+ throw new WrongParametersException("VerifyAuthenticationBlock", PARAM_SESSIONID, "auth.12");
+ if (!ParamValidatorUtils.isValidXMLDocument(createXMLSignatureResponse))
+ throw new WrongParametersException("VerifyAuthenticationBlock", PARAM_XMLRESPONSE, "auth.12");
+
+ AuthenticationSession session = AuthenticationServer.getSession(sessionID);
+
+ //change MOASessionID
+ sessionID = AuthenticationSessionStoreage.changeSessionID(session);
+
+ String authenticatedMOASessionId = AuthenticationServer.getInstance().verifyAuthenticationBlock(session, createXMLSignatureResponse);
+
+ if (authenticatedMOASessionId == null) {
+ //mandate Mode
+
+ AuthConfigurationProvider authConf= AuthConfigurationProvider.getInstance();
+ ConnectionParameter connectionParameters = authConf.getOnlineMandatesConnectionParameter();
+ SSLSocketFactory sslFactory = SSLUtils.getSSLSocketFactory(AuthConfigurationProvider.getInstance(), connectionParameters);
+
+ // get identitity link as byte[]
+ Element elem = session.getIdentityLink().getSamlAssertion();
+ String s = DOMUtils.serializeNode(elem);
+
+ //System.out.println("IDL: " + s);
+
+ byte[] idl = s.getBytes("UTF-8");
+
+ // redirect url
+ // build redirect(to the GetMISSessionIdSerlvet)
+
+ //change MOASessionID before MIS request
+ String newMOASessionID = AuthenticationSessionStoreage.changeSessionID(session);
+
+ redirectURL =
+ new DataURLBuilder().buildDataURL(
+ session.getAuthURL(),
+ GET_MIS_SESSIONID,
+ newMOASessionID);
+
+ String oaURL = session.getOAURLRequested();
+ OAAuthParameter oaParam = authConf.getOnlineApplicationParameter(oaURL);
+ List<String> profiles = oaParam.getMandateProfiles();
+
+ if (profiles == null) {
+ Logger.error("No Mandate/Profile for OA configured.");
+ throw new AuthenticationException("config.21", new Object[] { GET_MIS_SESSIONID});
+ }
+
+ String oaFriendlyName = oaParam.getFriendlyName();
+ String mandateReferenceValue = session.getMandateReferenceValue();
+ byte[] cert = session.getEncodedSignerCertificate();
+ byte[] authBlock = session.getAuthBlock().getBytes("UTF-8");
+
+ //TODO: check in case of SSO!!!
+ String targetType = null;
+ if(oaParam.getBusinessService()) {
+ String id = oaParam.getIdentityLinkDomainIdentifier();
+ if (id.startsWith(AuthenticationSession.REGISTERANDORDNR_PREFIX_))
+ targetType = id;
+ else
+ targetType = AuthenticationSession.REGISTERANDORDNR_PREFIX_+session.getDomainIdentifier();
+
+ } else {
+ targetType = AuthenticationSession.TARGET_PREFIX_ + oaParam.getTarget();
+ }
+
+ MISSessionId misSessionID = MISSimpleClient.sendSessionIdRequest(
+ connectionParameters.getUrl(),
+ idl,
+ cert,
+ oaFriendlyName,
+ redirectURL,
+ mandateReferenceValue,
+ profiles,
+ targetType,
+ authBlock,
+ sslFactory);
+
+ if (misSessionID == null) {
+ Logger.error("Fehler bei Anfrage an Vollmachten Service. MIS Session ID ist null.");
+ throw new MISSimpleClientException("Fehler bei Anfrage an Vollmachten Service.");
+ }
+
+ String redirectMISGUI = misSessionID.getRedirectURL();
+ session.setMISSessionID(misSessionID.getSessiondId());
+
+ try {
+ AuthenticationSessionStoreage.storeSession(session);
+ } catch (MOADatabaseException e) {
+ throw new MOAIDException("Session store error", null);
+ }
+
+ // TODO[branch]: Mandate; redirect to MIS website; website redirects back to "/GetMISSessionID"
+
+ resp.setStatus(302);
+ resp.addHeader("Location", redirectMISGUI);
+ Logger.debug("REDIRECT TO: " + redirectURL);
+ }
+ else {
+ // TODO[branch]: Final step back to /dispatcher
+ redirectURL = new DataURLBuilder().buildDataURL(session.getAuthURL(),
+ ModulUtils.buildAuthURL(session.getModul(), session.getAction(), pendingRequestID), authenticatedMOASessionId);
+
+ resp.setContentType("text/html");
+ resp.setStatus(302);
+
+ resp.addHeader("Location", redirectURL);
+ Logger.debug("REDIRECT TO: " + redirectURL);
+
+ }
+
+ }
+
+ catch (MOAIDException ex) {
+ handleError(null, ex, req, resp, pendingRequestID);
+
+ } catch (GeneralSecurityException e) {
+ handleError(null, e, req, resp, pendingRequestID);
+
+ } catch (PKIException e) {
+ handleError(null, e, req, resp, pendingRequestID);
+
+ } catch (TransformerException e) {
+ handleError(null, e, req, resp, pendingRequestID);
+
+ } catch (Exception e) {
+ Logger.error("AuthBlockValidation has an interal Error.", e);
+ }
+
+
+ finally {
+ ConfigurationDBUtils.closeSession();
+ }
+
+
+
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyCertificateTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyCertificateTask.java
new file mode 100644
index 000000000..7f9fed37a
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyCertificateTask.java
@@ -0,0 +1,164 @@
+package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
+
+import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
+import iaik.x509.X509Certificate;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.fileupload.FileUploadException;
+import org.apache.commons.lang.StringEscapeUtils;
+
+import at.gv.egovernment.moa.id.auth.AuthenticationServer;
+import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder;
+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.exception.WrongParametersException;
+import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
+import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
+import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
+import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
+import at.gv.egovernment.moa.id.util.ServletUtils;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.spss.util.CertificateUtils;
+
+import com.datentechnik.process_engine.api.ExecutionContext;
+
+/**
+ * Parses the certificate from {@code InfoBoxReadResponse} (via POST parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_XMLRESPONSE}), creates the auth block to be signed and returns a {@code CreateXMLSignatureRequest} for auth block signature.<p/>
+ * In detail:
+ * <ul>
+ * <li>Renames the moa session id.</li>
+ * <li>Retrieves the certificate via {@code InfoBoxReadResponse} from POST parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_XMLRESPONSE}.</li>
+ * <li>Verifies the certificate.</li>
+ * <li>Creates the auth block to be signed using information from the certificate (Organwalter, foreign citizen.</li>
+ * <li>Puts it in a {@code CreateXMLSignatureRequest}.</li>
+ * <li>Updates moa session.</li>
+ * <li>Responds with {@code CreateXMLSignatureRequest}.</li>
+ * </ul>
+ * Expects:
+ * <ul>
+ * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}</li>
+ * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_SESSIONID} containing a {@code InfoBoxReadResponse}.</li>
+ * </ul>
+ * Result:
+ * <ul>
+ * <li>{@code CreateXMLSignatureRequest} send as HttpServletResponse (for CCE).</li>
+ * </ul>
+ * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.VerifyCertificateServlet}.
+ * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
+ *
+ */
+public class VerifyCertificateTask extends AbstractAuthServletTask {
+
+ @Override
+ public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
+ throws Exception {
+
+ // note: code taken from at.gv.egovernment.moa.id.auth.servlet.VerifyCertificateServlet
+
+ Logger.debug("POST VerifyCertificateServlet");
+
+ String pendingRequestID = null;
+
+ Map<String, String> parameters;
+ try
+ {
+ parameters = getParameters(req);
+ } catch (FileUploadException e)
+ {
+ Logger.error("Parsing mulitpart/form-data request parameters failed: " + e.getMessage());
+ throw new IOException(e.getMessage());
+ }
+ String sessionID = req.getParameter(PARAM_SESSIONID);
+
+ // escape parameter strings
+ sessionID = StringEscapeUtils.escapeHtml(sessionID);
+
+ pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(sessionID);
+
+ AuthenticationSession session = null;
+ try {
+ // check parameter
+ if (!ParamValidatorUtils.isValidSessionID(sessionID))
+ throw new WrongParametersException("VerifyCertificate", PARAM_SESSIONID, "auth.12");
+
+ session = AuthenticationServer.getSession(sessionID);
+
+ //change MOASessionID
+ sessionID = AuthenticationSessionStoreage.changeSessionID(session);
+
+ X509Certificate cert = AuthenticationServer.getInstance().getCertificate(sessionID, parameters);
+ if (cert == null) {
+ Logger.error("Certificate could not be read.");
+ throw new AuthenticationException("auth.14", null);
+ }
+
+ boolean useMandate = session.getUseMandate();
+
+ if (useMandate) {
+
+ // verify certificate for OrganWalter
+ String createXMLSignatureRequestOrRedirect = AuthenticationServer.getInstance().verifyCertificate(session, cert);
+
+ try {
+ AuthenticationSessionStoreage.storeSession(session);
+ } catch (MOADatabaseException e) {
+ throw new MOAIDException("session store error", null);
+ }
+
+ // TODO[branch]: Mandate; respond with CXSR for authblock signature, dataURL "/VerifyAuthBlock"
+ ServletUtils.writeCreateXMLSignatureRequestOrRedirect(resp, session, createXMLSignatureRequestOrRedirect, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "VerifyCertificate");
+
+ }
+ else {
+
+
+ String countrycode = CertificateUtils.getIssuerCountry(cert);
+ if (countrycode != null) {
+ if (countrycode.compareToIgnoreCase("AT") == 0) {
+ Logger.error("Certificate issuer country code is \"AT\". Login not support in foreign identities mode.");
+ throw new AuthenticationException("auth.22", null);
+ }
+ }
+
+ // Foreign Identities Modus
+ String createXMLSignatureRequest = AuthenticationServer.getInstance().createXMLSignatureRequestForeignID(session, cert);
+ // build dataurl (to the GetForeignIDSerlvet)
+ String dataurl =
+ new DataURLBuilder().buildDataURL(
+ session.getAuthURL(),
+ REQ_GET_FOREIGN_ID,
+ session.getSessionID());
+
+ try {
+ AuthenticationSessionStoreage.storeSession(session);
+ } catch (MOADatabaseException e) {
+ throw new MOAIDException("session store error", null);
+ }
+
+ // TODO[branch]: Foreign citizen; respond with CXSR for authblock signature, dataURL "/GetForeignID"
+ ServletUtils.writeCreateXMLSignatureRequest(resp, createXMLSignatureRequest, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "GetForeignID", dataurl);
+
+ Logger.debug("Send CreateXMLSignatureRequest to BKU");
+ }
+ }
+ catch (MOAIDException ex) {
+ handleError(null, ex, req, resp, pendingRequestID);
+
+ } catch (Exception e) {
+ Logger.error("CertificateValidation has an interal Error.", e);
+ }
+
+
+ finally {
+ ConfigurationDBUtils.closeSession();
+ }
+
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyIdentityLinkTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyIdentityLinkTask.java
new file mode 100644
index 000000000..c880570b8
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyIdentityLinkTask.java
@@ -0,0 +1,103 @@
+package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
+
+import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang.StringEscapeUtils;
+
+import at.gv.egovernment.moa.id.auth.AuthenticationServer;
+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.MOAIDException;
+import at.gv.egovernment.moa.id.auth.exception.ParseException;
+import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
+import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
+import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
+import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
+import at.gv.egovernment.moa.logging.Logger;
+
+import com.datentechnik.process_engine.api.ExecutionContext;
+
+/**
+ * Verifies the identity link.<p/>
+ * In detail:
+ * <ul>
+ * <li>Renames the moa session id.</li>
+ * <li>Parses the identity link retrieved as {@code InfoBoxReadResponse} from POST parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_XMLRESPONSE}.</li>
+ * <li>Verifies the identity link.</li>
+ * <li>Updates moa session.</li>
+ * <li>Puts boolean flag {@code identityLinkAvailable} into {@code ExecutionContext}.</li>
+ * </ul>
+ * Expects:
+ * <ul>
+ * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}</li>
+ * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_XMLRESPONSE} containing a {@code InfoBoxReadResponse}.</li>
+ * </ul>
+ * Result:
+ * <ul>
+ * <li>Identity link put into moa session.</li>
+ * <li>Boolean flag {@code identityLinkAvailable} into {@code ExecutionContext}.</li>
+ * </ul>
+ * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.VerifyIdentityLinkServlet}.
+ * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
+ *
+ */
+public class VerifyIdentityLinkTask extends AbstractAuthServletTask {
+
+ @Override
+ public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
+ throws Exception {
+
+ // note: code taken from at.gv.egovernment.moa.id.auth.servlet.VerifyIdentityLinkServlet
+
+ Logger.debug("POST VerifyIdentityLink");
+
+ setNoCachingHeaders(resp);
+
+ Map<String, String> parameters;
+ String pendingRequestID = null;
+
+ try {
+ parameters = getParameters(req);
+ } catch (Exception e) {
+ Logger.error("Parsing mulitpart/form-data request parameters failed: " + e.getMessage());
+ throw new IOException(e.getMessage());
+ }
+
+ try {
+
+ String sessionID = StringEscapeUtils.escapeHtml(req.getParameter(PARAM_SESSIONID));
+ // check parameter
+ if (!ParamValidatorUtils.isValidSessionID(sessionID)) {
+ throw new WrongParametersException("VerifyIdentityLink", PARAM_SESSIONID, "auth.12");
+ }
+ pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(sessionID);
+
+ AuthenticationSession session = AuthenticationServer.getSession(sessionID);
+
+ boolean identityLinkAvailable = AuthenticationServer.getInstance().verifyIdentityLink(session, parameters) != null;
+ AuthenticationSessionStoreage.storeSession(session);
+
+ executionContext.put("identityLinkAvailable", identityLinkAvailable);
+
+ } catch (ParseException ex) {
+ handleError(null, ex, req, resp, pendingRequestID);
+
+ } catch (MOAIDException ex) {
+ handleError(null, ex, req, resp, pendingRequestID);
+
+ } catch (Exception e) {
+ Logger.error("IdentityLinkValidation has an interal Error.", e);
+ }
+
+ finally {
+ ConfigurationDBUtils.closeSession();
+ }
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/STORKAuthModuleImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/STORKAuthModuleImpl.java
new file mode 100644
index 000000000..140334b36
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/STORKAuthModuleImpl.java
@@ -0,0 +1,27 @@
+package at.gv.egovernment.moa.id.auth.modules.stork;
+
+import org.apache.commons.lang3.StringUtils;
+
+import com.datentechnik.process_engine.api.ExecutionContext;
+
+import at.gv.egovernment.moa.id.moduls.moduleregistration.AuthModule;
+
+public class STORKAuthModuleImpl implements AuthModule {
+
+ @Override
+ public int getPriority() {
+ // neutral priority between Integer.MIN_VALUE and Integer.MAX_VALUE
+ return 0;
+ }
+
+ @Override
+ public String selectProcess(ExecutionContext context) {
+ return StringUtils.isNotBlank((String) context.get("ccc")) ? "STORKAuthentication" : null;
+ }
+
+ @Override
+ public String[] getProcessDefinitions() {
+ return new String[] { "classpath:at/gv/egovernment/moa/id/auth/modules/stork/STORKAuthentication.process.xml" };
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/AbstractPepsConnectorWithLocalSigningTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/AbstractPepsConnectorWithLocalSigningTask.java
new file mode 100644
index 000000000..9ffcaaa1e
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/AbstractPepsConnectorWithLocalSigningTask.java
@@ -0,0 +1,257 @@
+package at.gv.egovernment.moa.id.auth.modules.stork.tasks;
+
+import iaik.x509.X509Certificate;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
+import java.security.cert.CertificateException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import javax.activation.DataSource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Source;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+import org.opensaml.saml2.core.StatusCode;
+import org.xml.sax.SAXException;
+
+import at.gv.egovernment.moa.id.auth.AuthenticationServer;
+import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder;
+import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
+import at.gv.egovernment.moa.id.auth.data.IdentityLink;
+import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
+import at.gv.egovernment.moa.id.auth.exception.BKUException;
+import at.gv.egovernment.moa.id.auth.exception.BuildException;
+import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
+import at.gv.egovernment.moa.id.auth.exception.ParseException;
+import at.gv.egovernment.moa.id.auth.exception.ServiceException;
+import at.gv.egovernment.moa.id.auth.modules.internal.tasks.AbstractAuthServletTask;
+import at.gv.egovernment.moa.id.auth.servlet.PEPSConnectorWithLocalSigningServlet;
+import at.gv.egovernment.moa.id.auth.stork.STORKException;
+import at.gv.egovernment.moa.id.auth.stork.STORKResponseProcessor;
+import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
+import at.gv.egovernment.moa.id.commons.db.dao.config.AttributeProviderPlugin;
+import at.gv.egovernment.moa.id.config.ConfigurationException;
+import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
+import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
+import at.gv.egovernment.moa.id.moduls.ModulUtils;
+import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants;
+import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
+import at.gv.egovernment.moa.id.util.HTTPUtils;
+import at.gv.egovernment.moa.id.util.VelocityProvider;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.spss.MOAException;
+import at.gv.egovernment.moa.spss.api.SPSSFactory;
+import at.gv.egovernment.moa.spss.api.SignatureVerificationService;
+import at.gv.egovernment.moa.spss.api.common.Content;
+import at.gv.egovernment.moa.spss.api.xmlverify.VerifySignatureInfo;
+import at.gv.egovernment.moa.spss.api.xmlverify.VerifySignatureLocation;
+import at.gv.egovernment.moa.spss.api.xmlverify.VerifyXMLSignatureRequest;
+import at.gv.egovernment.moa.spss.api.xmlverify.VerifyXMLSignatureResponse;
+import at.gv.egovernment.moa.util.StringUtils;
+import at.gv.util.xsd.xmldsig.SignatureType;
+import at.gv.util.xsd.xmldsig.X509DataType;
+
+import com.datentechnik.process_engine.api.ExecutionContext;
+
+import eu.stork.oasisdss.api.ApiUtils;
+import eu.stork.oasisdss.api.LightweightSourceResolver;
+import eu.stork.oasisdss.api.exceptions.ApiUtilsException;
+import eu.stork.oasisdss.api.exceptions.UtilsException;
+import eu.stork.oasisdss.profile.SignRequest;
+import eu.stork.oasisdss.profile.SignResponse;
+import eu.stork.peps.auth.commons.IPersonalAttributeList;
+import eu.stork.peps.auth.commons.PEPSUtil;
+import eu.stork.peps.auth.commons.PersonalAttribute;
+import eu.stork.peps.auth.commons.STORKAuthnRequest;
+import eu.stork.peps.auth.commons.STORKAuthnResponse;
+import eu.stork.peps.auth.engine.STORKSAMLEngine;
+import eu.stork.peps.exceptions.STORKSAMLEngineException;
+
+public abstract class AbstractPepsConnectorWithLocalSigningTask extends AbstractAuthServletTask {
+
+ String getCitizienSignatureFromSignResponse(SignResponse dssSignResponse) throws IllegalArgumentException,
+ TransformerConfigurationException, UtilsException, TransformerException,
+ TransformerFactoryConfigurationError, IOException, ApiUtilsException {
+ // fetch signed doc
+ DataSource ds = LightweightSourceResolver.getDataSource(dssSignResponse);
+ if (ds == null) {
+ throw new ApiUtilsException("No datasource found in response");
+ }
+
+ InputStream incoming = ds.getInputStream();
+ String citizenSignature = IOUtils.toString(incoming);
+ incoming.close();
+
+ return citizenSignature;
+ }
+
+ void SZRGInsertion(AuthenticationSession moaSession, IPersonalAttributeList personalAttributeList,
+ String authnContextClassRef, String citizenSignature) throws STORKException, MOAIDException {
+ Logger.debug("Foregin Citizen signature successfully extracted from STORK Assertion (signedDoc)");
+ Logger.debug("Citizen signature will be verified by SZR Gateway!");
+
+ Logger.debug("fetching OAParameters from database");
+
+ OAAuthParameter oaParam = AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(
+ moaSession.getPublicOAURLPrefix());
+ if (oaParam == null)
+ throw new AuthenticationException("auth.00", new Object[] { moaSession.getPublicOAURLPrefix() });
+
+ // retrieve target
+ // TODO: check in case of SSO!!!
+ String targetType = null;
+ if (oaParam.getBusinessService()) {
+ String id = oaParam.getIdentityLinkDomainIdentifier();
+ if (id.startsWith(AuthenticationSession.REGISTERANDORDNR_PREFIX_))
+ targetType = id;
+ else
+ targetType = AuthenticationSession.REGISTERANDORDNR_PREFIX_ + moaSession.getDomainIdentifier();
+ } else {
+ targetType = AuthenticationSession.TARGET_PREFIX_ + oaParam.getTarget();
+ }
+
+ Logger.debug("Starting connecting SZR Gateway");
+ // contact SZR Gateway
+ IdentityLink identityLink = null;
+
+ identityLink = STORKResponseProcessor.connectToSZRGateway(personalAttributeList, oaParam.getFriendlyName(),
+ targetType, null, oaParam.getMandateProfiles(), citizenSignature);
+ 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);
+ }
+ Logger.info("Received Identity Link from SZR Gateway");
+ moaSession.setIdentityLink(identityLink);
+
+ Logger.debug("Adding addtional STORK attributes to MOA session");
+ moaSession.setStorkAttributes(personalAttributeList);
+
+ // We don't have BKUURL, setting from null to "Not applicable"
+ moaSession.setBkuURL("Not applicable (STORK Authentication)");
+
+ // free for single use
+ moaSession.setAuthenticatedUsed(false);
+
+ // stork did the authentication step
+ moaSession.setAuthenticated(true);
+
+ // TODO: found better solution, but QAA Level in response could be not supported yet
+ try {
+ if (authnContextClassRef == null)
+ authnContextClassRef = PVPConstants.STORK_QAA_PREFIX + oaParam.getQaaLevel();
+ moaSession.setQAALevel(authnContextClassRef);
+
+ } catch (Throwable e) {
+ Logger.warn("STORK QAA-Level is not found in AuthnResponse. Set QAA Level to requested level");
+ moaSession.setQAALevel(PVPConstants.STORK_QAA_PREFIX + oaParam.getQaaLevel());
+
+ }
+
+ }
+
+ X509Certificate getSignerCertificate(String citizenSignature) throws CertificateException, JAXBException,
+ UnsupportedEncodingException {
+ JAXBContext ctx = JAXBContext.newInstance(SignatureType.class.getPackage().getName());
+ SignatureType root = ((JAXBElement<SignatureType>) ctx.createUnmarshaller().unmarshal(
+ IOUtils.toInputStream(citizenSignature))).getValue();
+
+ // extract certificate
+ for (Object current : root.getKeyInfo().getContent())
+ if (((JAXBElement<?>) current).getValue() instanceof X509DataType) {
+ for (Object currentX509Data : ((JAXBElement<X509DataType>) current).getValue()
+ .getX509IssuerSerialOrX509SKIOrX509SubjectName()) {
+ JAXBElement<?> casted = ((JAXBElement<?>) currentX509Data);
+ if (casted.getName().getLocalPart().equals("X509Certificate")) {
+ return new X509Certificate(((String) casted.getValue()).getBytes("UTF-8"));
+ }
+ }
+ }
+ return null;
+ }
+
+ VerifyXMLSignatureResponse verifyXMLSignature(String signature) throws AuthenticationException, ParseException,
+ BKUException, BuildException, ConfigurationException, ServiceException, UnsupportedEncodingException,
+ SAXException, IOException, ParserConfigurationException, MOAException {
+ // Based on MOA demo client
+ // Factory und Service instanzieren
+ SPSSFactory spssFac = SPSSFactory.getInstance();
+ SignatureVerificationService sigVerifyService = SignatureVerificationService.getInstance();
+
+ Content sigDocContent1 = spssFac.createContent(IOUtils.toInputStream(signature, "UTF-8"), null);
+
+ // Position der zu prüfenden Signatur im Dokument angeben
+ // (Nachdem im XPath-Ausdruck ein NS-Präfix verwendet wird, muss in einer Lookup-Tabelle
+ // der damit bezeichnete Namenraum mitgegeben werden)
+ HashMap nSMap = new HashMap();
+ nSMap.put("dsig", "http://www.w3.org/2000/09/xmldsig#");
+ VerifySignatureLocation sigLocation = spssFac.createVerifySignatureLocation("//dsig:Signature", nSMap);
+
+ // Zu prüfendes Dokument und Signaturposition zusammenfassen
+
+ VerifySignatureInfo sigInfo = spssFac.createVerifySignatureInfo(sigDocContent1, sigLocation);
+
+ // Prüfrequest zusammenstellen
+ VerifyXMLSignatureRequest verifyRequest = spssFac.createVerifyXMLSignatureRequest(null, // Wird Prüfzeit nicht
+ // angegeben, wird
+ // aktuelle Zeit
+ // verwendet
+ sigInfo, null, // Keine Ergänzungsobjekte notwendig
+ null, // Signaturmanifest-Prüfung soll nicht durchgeführt werden
+ false, // Hash-Inputdaten, d.h. tatsächlich signierte Daten werden nicht zurückgeliefert
+ "MOAIDBuergerkartePersonenbindungMitTestkarten");// TODO load from config
+ // "Test-Signaturdienste"); // ID des verwendeten Vertrauensprofils
+
+ VerifyXMLSignatureResponse verifyResponse = null;
+ try {
+ // Aufruf der Signaturprüfung
+ verifyResponse = sigVerifyService.verifyXMLSignature(verifyRequest);
+ } catch (MOAException e) {
+ // Service liefert Fehler
+ System.err.println("Die Signaturprüfung hat folgenden Fehler geliefert:");
+ System.err.println("Fehlercode: " + e.getMessageId());
+ System.err.println("Fehlernachricht: " + e.getMessage());
+ throw e;
+ }
+
+ return verifyResponse;
+ }
+
+ at.gv.egovernment.moa.id.auth.data.VerifyXMLSignatureResponse convert(
+ VerifyXMLSignatureResponse xMLVerifySignatureResponse) {
+ at.gv.egovernment.moa.id.auth.data.VerifyXMLSignatureResponse response = new at.gv.egovernment.moa.id.auth.data.VerifyXMLSignatureResponse();
+ response.setCertificateCheckCode(xMLVerifySignatureResponse.getCertificateCheck().getCode());
+ response.setPublicAuthority(xMLVerifySignatureResponse.getSignerInfo().isPublicAuthority());
+ // response.setPublicAuthorityCode(publicAuthorityCode)
+ response.setQualifiedCertificate(xMLVerifySignatureResponse.getSignerInfo().isQualifiedCertificate());
+ response.setSignatureCheckCode(xMLVerifySignatureResponse.getSignatureCheck().getCode());
+ response.setSignatureManifestCheckCode(xMLVerifySignatureResponse.getSignatureManifestCheck().getCode());
+ // response.setSigningDateTime()
+ // response.setX509certificate(x509certificate)
+ response.setXmlDSIGManifestCheckCode(xMLVerifySignatureResponse.getSignatureManifestCheck().getCode());
+ // response.setXmlDSIGManigest(xMLVerifySignatureResponse.getSignatureManifestCheck())
+ // response.setXmlDsigSubjectName(xmlDsigSubjectName)
+ return response;
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/CreateStorkAuthRequestFormTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/CreateStorkAuthRequestFormTask.java
new file mode 100644
index 000000000..d7480f063
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/CreateStorkAuthRequestFormTask.java
@@ -0,0 +1,114 @@
+package at.gv.egovernment.moa.id.auth.modules.stork.tasks;
+
+import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import at.gv.egovernment.moa.id.auth.AuthenticationServer;
+import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants;
+import at.gv.egovernment.moa.id.auth.builder.StartAuthenticationBuilder;
+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.exception.WrongParametersException;
+import at.gv.egovernment.moa.id.auth.modules.internal.tasks.AbstractAuthServletTask;
+import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
+import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
+import at.gv.egovernment.moa.id.config.stork.CPEPS;
+import at.gv.egovernment.moa.id.config.stork.STORKConfig;
+import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
+import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
+import at.gv.egovernment.moa.logging.Logger;
+
+import com.datentechnik.process_engine.api.ExecutionContext;
+
+/**
+ * Creates a SAML2 STORK authentication request, embeds it in a form (in order to satisfy saml post binging) and returns the form withing the HttpServletResponse.<p/>
+ * In detail:
+ * <ul>
+ * <li>Validates the stork configuration in order to make sure the selected country is supported.</li>
+ * <li>Puts a flag ({@link #PROCESS_CTX_KEY_CPEPS_ISXMLSIGSUPPORTED}) into the ExecutionContext reflecting the capability of the C-PEPS to create xml signatures.</li>
+ * <li>Invokes {@link AuthenticationServer#startSTORKAuthentication(HttpServletRequest, HttpServletResponse, AuthenticationSession)} which</li>
+ * <ul>
+ * <li>Creates and signs a SAML2 stork authentication request.</li>
+ * <li>Creates a signature request for auth block signature (either to be performed by the C-PEPS or locally).</li>
+ * <li>Using the velocity template engine in order to create a form with the embedded stork request.</li>
+ * <li>Writes the form to the response output stream.</li>
+ * </ul>
+ * </ul>
+ * Expects:
+ * <ul>
+ * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}</li>
+ * <li>Property {@code ccc} set within the moa session.</li>
+ * </ul>
+ * Result:
+ * <ul>
+ * <li>Form containing a SAML2 Stork authentication request and an action url pointing to the selected C-PEPS.</li>
+ * <li>Assertion consumer URL for C-PEPS set either to {@code /PEPSConnector} in case of a C-PEPS supporting xml signatures or {@code /PEPSConnectorWithLocalSigning} if the selected C-PEPS does not support xml signatures.</li>
+ * <li>In case of a C-PEPS not supporting xml signature: moasession with set signedDoc property (containing the signature request for local signing).</li>
+ * <li>ExecutionContext contains the boolean flag {@link #PROCESS_CTX_KEY_CPEPS_ISXMLSIGSUPPORTED}.
+ * </ul>
+ * Code taken from {@link StartAuthenticationBuilder#build(AuthenticationSession, HttpServletRequest, HttpServletResponse)}.<br/>
+ * Using {@link AuthenticationServer#startSTORKAuthentication(HttpServletRequest, HttpServletResponse, AuthenticationSession)}
+ * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
+ */
+public class CreateStorkAuthRequestFormTask extends AbstractAuthServletTask {
+
+ /**
+ * Boolean value reflecting the capability of the selected c-peps of creating xml signatures.
+ */
+ public static final String PROCESS_CTX_KEY_CPEPS_ISXMLSIGSUPPORTED = "C-PEPS:XMLSignatureSupported";
+
+ @Override
+ public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
+ throws Exception {
+
+ String pendingRequestID = null;
+ String sessionID = null;
+ try {
+ setNoCachingHeaders(resp);
+
+ sessionID = StringEscapeUtils.escapeHtml(req.getParameter(PARAM_SESSIONID));
+ // check parameter
+ if (!ParamValidatorUtils.isValidSessionID(sessionID)) {
+ throw new WrongParametersException("CreateStorkAuthRequestFormTask", PARAM_SESSIONID, "auth.12");
+ }
+ AuthenticationSession moasession = AuthenticationServer.getSession(sessionID);
+ pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(sessionID);
+
+ if (StringUtils.isEmpty(moasession.getCcc())) {
+ // illegal state; task should not have been executed without a selected country
+ throw new AuthenticationException("stork.22", new Object[] { sessionID });
+ }
+ STORKConfig storkConfig = AuthConfigurationProvider.getInstance().getStorkConfig();
+ if (!storkConfig.isSTORKAuthentication(moasession.getCcc())) {
+ throw new AuthenticationException("stork.23", new Object[] { moasession.getCcc(), sessionID });
+ }
+
+ // STORK authentication
+ // cpeps cannot be null
+ CPEPS cpeps = storkConfig.getCPEPS(moasession.getCcc());
+ Logger.debug("Found C-PEPS configuration for citizen of country: " + moasession.getCcc());
+ executionContext.put(PROCESS_CTX_KEY_CPEPS_ISXMLSIGSUPPORTED, cpeps.isXMLSignatureSupported());
+
+ Logger.info("Starting STORK authentication for a citizen of country: " + moasession.getCcc());
+ AuthenticationServer.startSTORKAuthentication(req, resp, moasession);
+
+ } catch (MOAIDException ex) {
+ handleError(null, ex, req, resp, pendingRequestID);
+
+ } catch (Exception e) {
+ Logger.error("CreateStorkAuthRequestFormTask has an interal Error.", e);
+ throw new MOAIDException("Internal error.", new Object[] { sessionID }, e);
+ }
+
+ finally {
+ ConfigurationDBUtils.closeSession();
+ }
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorHandleLocalSignResponseTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorHandleLocalSignResponseTask.java
new file mode 100644
index 000000000..d772a50c0
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorHandleLocalSignResponseTask.java
@@ -0,0 +1,218 @@
+package at.gv.egovernment.moa.id.auth.modules.stork.tasks;
+
+import iaik.x509.X509Certificate;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+
+import at.gv.egovernment.moa.id.auth.AuthenticationServer;
+import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder;
+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.stork.STORKException;
+import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
+import at.gv.egovernment.moa.id.moduls.ModulUtils;
+import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
+import at.gv.egovernment.moa.id.util.VelocityProvider;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.spss.api.xmlverify.VerifyXMLSignatureResponse;
+
+import com.datentechnik.process_engine.api.ExecutionContext;
+
+import eu.stork.oasisdss.api.ApiUtils;
+import eu.stork.oasisdss.profile.SignResponse;
+import eu.stork.peps.auth.commons.IPersonalAttributeList;
+import eu.stork.peps.auth.commons.PersonalAttribute;
+
+/**
+ * Processes the citizen's signature, creates identity link using szr gateway and finalizes authentication.
+ * <p/>
+ * In detail:
+ * <ul>
+ * <li>Changes moa session id.</li>
+ * <li>Decodes and validates the sign response, extracting the citizen's signature.</li>
+ * <li>Verifies the citizen's signature.</li>
+ * <li>Create {@code signedDoc} attribute.</li>
+ * <li>Retrieve identity link from SZR gateway using the citizen's signature.</li>
+ * <li>If the S-PEPS did not provide any gender information, the szr gateway will not be able to issue an identity link.
+ * Therefore a form is presented asking for the subject's gender. The form finally submits the user back to the
+ * {@code /PepsConnectorWithLocalSigning} servlet (this task).</li>
+ * <li>The moa session is updated with authentication information.</li>
+ * <li>Change moa session id.</li>
+ * <li>Redirects back to {@code /dispatcher} in order to finalize the authentication.</li>
+ * </ul>
+ * Expects:
+ * <ul>
+ * <li>HttpServletRequest parameter {@code moaSessionID}</li>
+ * <li>HttpServletRequest parameter {@code signresponse}</li>
+ * </ul>
+ * Result:
+ * <ul>
+ * <li>Updated moa id session (signed auth block, signer certificate etc.)</li>
+ * <li>Redirect to {@code /dispatcher}.</li>
+ * <li>{@link ExecutionContext} contains boolean flag {@code identityLinkAvailable} indicating if an identitylink has been successfully creates or not.</li>
+ * </ul>
+ * Possible branches:
+ * <ul>
+ * <li>In case the szr gateway throws exception due to missing gender information:
+ * <ul>
+ * <li>Returns a form for gender selection with action url back to this servlet/task.</li>
+ * </ul>
+ * </li>
+ * </ul>
+ * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.PEPSConnectorWithLocalSigningServlet}.<br/>
+ *
+ * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
+ */
+public class PepsConnectorHandleLocalSignResponseTask extends AbstractPepsConnectorWithLocalSigningTask {
+
+ @Override
+ public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response)
+ throws Exception {
+ String moaSessionID = request.getParameter("moaSessionID");
+ String signResponse = request.getParameter("signresponse");
+ Logger.info("moaSessionID:" + moaSessionID);
+ Logger.info("signResponse:" + signResponse);
+
+ if (moaSessionID != null && signResponse != null) {
+ // redirect from oasis with signresponse
+ handleSignResponse(executionContext, request, response);
+ } else {
+ // should not occur
+ throw new IOException("should not occur");
+ }
+ return;
+ }
+
+ private void handleSignResponse(ExecutionContext executionContext, HttpServletRequest request,
+ HttpServletResponse response) {
+ Logger.info("handleSignResponse started");
+ String moaSessionID = request.getParameter("moaSessionID");
+ String signResponse = request.getParameter("signresponse");
+ Logger.info("moaSessionID:" + moaSessionID);
+ Logger.info("signResponse:" + signResponse);
+ String pendingRequestID = null;
+ try {
+
+ // load MOASession from database
+ AuthenticationSession moaSession = AuthenticationServer.getSession(moaSessionID);
+ // change MOASessionID
+ moaSessionID = AuthenticationSessionStoreage.changeSessionID(moaSession);
+
+ pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(moaSessionID);
+ Logger.info("pendingRequestID:" + pendingRequestID);
+ String signResponseString = new String(Base64.decodeBase64(signResponse), "UTF8");
+ Logger.info("RECEIVED signresponse:" + signResponseString);
+ // create SignResponse object
+ Source response1 = new StreamSource(new java.io.StringReader(signResponseString));
+ SignResponse dssSignResponse = ApiUtils.unmarshal(response1, SignResponse.class);
+
+ // SignResponse dssSignResponse = (SignResponse) ApiUtils.unmarshal(new StreamSource(new
+ // java.io.StringReader(Base64.signResponse)));
+
+ String citizenSignature = getCitizienSignatureFromSignResponse(dssSignResponse);
+
+ // memorize signature into authblock
+ moaSession.setAuthBlock(citizenSignature);
+
+ X509Certificate cert = getSignerCertificate(citizenSignature);
+ moaSession.setSignerCertificate(cert);
+ VerifyXMLSignatureResponse xMLVerifySignatureResponse = verifyXMLSignature(citizenSignature);
+ at.gv.egovernment.moa.id.auth.data.VerifyXMLSignatureResponse tmp = convert(xMLVerifySignatureResponse);
+
+ moaSession.setXMLVerifySignatureResponse(tmp);
+ executionContext.put("identityLinkAvailable", false);
+ try {
+ IPersonalAttributeList personalAttributeList = moaSession.getAuthnResponseGetPersonalAttributeList();
+ // Add SignResponse TODO Add signature (extracted from signResponse)?
+ List<String> values = new ArrayList<String>();
+ values.add(signResponseString);
+ // values.add(citizenSignature);
+ Logger.debug("Assembling signedDoc attribute");
+ PersonalAttribute signedDocAttribute = new PersonalAttribute("signedDoc", false, values, "Available");
+ personalAttributeList.add(signedDocAttribute);
+
+ String authnContextClassRef = moaSession.getAuthnContextClassRef();
+ SZRGInsertion(moaSession, personalAttributeList, authnContextClassRef, citizenSignature);
+ executionContext.put("identityLinkAvailable", true);
+ } catch (STORKException e) {
+ // this is really nasty but we work against the system here. We are supposed to get the gender attribute
+ // from
+ // stork. If we do not, we cannot register the person in the ERnP - we have to have the
+ // gender for the represented person. So here comes the dirty hack.
+ if (e.getCause() instanceof STORKException
+ && e.getCause().getMessage().equals("gender not found in response")) {
+ try {
+ Logger.trace("Initialize VelocityEngine...");
+
+ VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine();
+ Template template = velocityEngine.getTemplate("/resources/templates/fetchGender.html");
+ VelocityContext context = new VelocityContext();
+ context.put("SAMLResponse", request.getParameter("SAMLResponse"));
+ context.put("action", request.getRequestURL());
+
+ StringWriter writer = new StringWriter();
+ template.merge(context, writer);
+ response.getOutputStream().write(writer.toString().getBytes("UTF-8"));
+ } catch (Exception e1) {
+ Logger.error("Error sending gender retrival form.", e1);
+ // httpSession.invalidate();
+ throw new MOAIDException("stork.10", null);
+ }
+
+ return;
+ }
+
+ Logger.error("Error connecting SZR Gateway", e);
+ throw new MOAIDException("stork.10", null);
+ }
+
+ Logger.debug("Add full STORK AuthnResponse to MOA session");
+ moaSession.setStorkAuthnResponse(request.getParameter("SAMLResponse"));// TODO ask Florian/Thomas
+ // authnResponse?
+ moaSession.setForeigner(true);
+
+ // session is implicit stored in changeSessionID!!!!
+ String newMOASessionID = AuthenticationSessionStoreage.changeSessionID(moaSession);
+
+ Logger.info("Changed MOASession " + moaSessionID + " to Session " + newMOASessionID);
+
+ // redirect
+ String redirectURL = null;
+ redirectURL = new DataURLBuilder().buildDataURL(moaSession.getAuthURL(),
+ ModulUtils.buildAuthURL(moaSession.getModul(), moaSession.getAction(), pendingRequestID),
+ newMOASessionID);
+ redirectURL = response.encodeRedirectURL(redirectURL);
+
+ response.sendRedirect(redirectURL);
+ Logger.info("REDIRECT TO: " + redirectURL);
+
+ } catch (AuthenticationException e) {
+ handleError(null, e, request, response, pendingRequestID);
+
+ } catch (MOAIDException e) {
+ handleError(null, e, request, response, pendingRequestID);
+
+ } catch (Exception e) {
+ Logger.error("PEPSConnector has an interal Error.", e);
+ }
+
+ finally {
+ ConfigurationDBUtils.closeSession();
+ }
+ }
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorHandleResponseWithoutSignatureTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorHandleResponseWithoutSignatureTask.java
new file mode 100644
index 000000000..8ed1cf44f
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorHandleResponseWithoutSignatureTask.java
@@ -0,0 +1,441 @@
+package at.gv.egovernment.moa.id.auth.modules.stork.tasks;
+
+import iaik.x509.X509Certificate;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+import org.opensaml.saml2.core.StatusCode;
+
+import at.gv.egovernment.moa.id.auth.AuthenticationServer;
+import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder;
+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.servlet.PEPSConnectorWithLocalSigningServlet;
+import at.gv.egovernment.moa.id.auth.stork.STORKException;
+import at.gv.egovernment.moa.id.auth.stork.STORKResponseProcessor;
+import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
+import at.gv.egovernment.moa.id.commons.db.dao.config.AttributeProviderPlugin;
+import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
+import at.gv.egovernment.moa.id.moduls.ModulUtils;
+import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
+import at.gv.egovernment.moa.id.util.HTTPUtils;
+import at.gv.egovernment.moa.id.util.VelocityProvider;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.StringUtils;
+
+import com.datentechnik.process_engine.api.ExecutionContext;
+
+import eu.stork.oasisdss.api.ApiUtils;
+import eu.stork.oasisdss.profile.SignRequest;
+import eu.stork.oasisdss.profile.SignResponse;
+import eu.stork.peps.auth.commons.IPersonalAttributeList;
+import eu.stork.peps.auth.commons.PEPSUtil;
+import eu.stork.peps.auth.commons.PersonalAttribute;
+import eu.stork.peps.auth.commons.STORKAuthnRequest;
+import eu.stork.peps.auth.commons.STORKAuthnResponse;
+import eu.stork.peps.auth.engine.STORKSAMLEngine;
+import eu.stork.peps.exceptions.STORKSAMLEngineException;
+
+/**
+ * Validates the SAML response from C-PEPS.
+ * <p/>
+ * In detail:
+ * <ul>
+ * <li>Decodes and validates SAML response from C-PEPS.</li>
+ * <li>Retrieves the moa session using the session id provided by HttpServletRequest parameter {@code RelayState} or by {@code inResponseTo} attribute of the saml response.</li>
+ * <li>Store saml response in moa session.</li>
+ * <li>Change moa session id.</li>
+ * <li>Redirect to {@code /PEPSConnectorWithLocalSigning}, with providing the moa session id as request parameter.</li>
+ * </ul>
+ * Expects:
+ * <ul>
+ * <li>HttpServletRequest parameter {@code moaSessionID} <strong>to be {@code null}</strong></li>
+ * <li>HttpServletRequest parameter {@code signresponse} <strong>to be {@code null}</strong></li>
+ * <li>HttpServletRequest parameter {@code SAMLResponse}</li>
+ * <li>Either HttpServletRequest parameter {@code RelayState} or {@code inResponseTo} attribute within the saml response, both reflecting the moa session id.</li>
+ * </ul>
+ * Result:
+ * <ul>
+ * <li>Updated moa session (with saml response).</li>
+ * <li>Redirect to {@code /PEPSConnectorWithLocalSigning}, with providing the moa session id as request parameter.</li>
+ * </ul>
+ * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.PEPSConnectorWithLocalSigningServlet}.<br/>
+ *
+ * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
+ */
+public class PepsConnectorHandleResponseWithoutSignatureTask extends AbstractPepsConnectorWithLocalSigningTask {
+
+ private String oasisDssWebFormURL = "https://testvidp.buergerkarte.at/oasis-dss/DSSWebFormServlet";
+ // load from config below
+
+ @Override
+ public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response)
+ throws Exception {
+ String moaSessionID = request.getParameter("moaSessionID");
+ String signResponse = request.getParameter("signresponse");
+ Logger.info("moaSessionID:" + moaSessionID);
+ Logger.info("signResponse:" + signResponse);
+
+ if (moaSessionID == null && signResponse == null) {
+ // normal saml response
+ handleSAMLResponse(executionContext, request, response);
+
+ } else {
+ // should not occur
+ throw new IOException("should not occur");
+ }
+ return;
+ }
+
+ private void handleSAMLResponse(ExecutionContext executionContext, HttpServletRequest request,
+ HttpServletResponse response) {
+ Logger.info("handleSAMLResponse started");
+ String pendingRequestID = null;
+
+ setNoCachingHeaders(response);
+ try {
+ Logger.info("PEPSConnector Servlet invoked, expecting C-PEPS message.");
+ Logger.debug("This ACS endpoint is: " + HTTPUtils.getBaseURL(request));
+
+ Logger.trace("No Caching headers set for HTTP response");
+
+ // check if https or only http
+ super.checkIfHTTPisAllowed(request.getRequestURL().toString());
+
+ Logger.debug("Beginning to extract SAMLResponse out of HTTP Request");
+
+ // extract STORK Response from HTTP Request
+ // Decodes SAML Response
+ byte[] decSamlToken;
+ try {
+ decSamlToken = PEPSUtil.decodeSAMLToken(request.getParameter("SAMLResponse"));
+ Logger.debug("SAMLResponse: " + new String(decSamlToken));
+
+ } catch (NullPointerException e) {
+ Logger.error("Unable to retrieve STORK Response", e);
+ throw new MOAIDException("stork.04", null);
+ }
+
+ // Get SAMLEngine instance
+ STORKSAMLEngine engine = STORKSAMLEngine.getInstance("outgoing");
+
+ STORKAuthnResponse authnResponse = null;
+ try {
+ // validate SAML Token
+ Logger.debug("Starting validation of SAML response");
+ authnResponse = engine.validateSTORKAuthnResponse(decSamlToken, (String) request.getRemoteHost());
+ Logger.info("SAML response succesfully verified!");
+ } catch (STORKSAMLEngineException e) {
+ Logger.error("Failed to verify STORK SAML Response", e);
+ throw new MOAIDException("stork.05", null);
+ }
+
+ Logger.info("STORK SAML Response message succesfully extracted");
+ Logger.debug("STORK response: ");
+ Logger.debug(authnResponse.toString());
+
+ Logger.debug("Trying to find MOA Session-ID ...");
+ // String moaSessionID = request.getParameter(PARAM_SESSIONID);
+ // first use SAML2 relayState
+ String moaSessionID = request.getParameter("RelayState");
+
+ // escape parameter strings
+ moaSessionID = StringEscapeUtils.escapeHtml(moaSessionID);
+
+ // check if SAML2 relaystate includes a MOA sessionID
+ if (StringUtils.isEmpty(moaSessionID)) {
+ // if relaystate is emtpty, use SAML response -> inResponseTo element as session identifier
+
+ moaSessionID = authnResponse.getInResponseTo();
+ moaSessionID = StringEscapeUtils.escapeHtml(moaSessionID);
+
+ if (StringUtils.isEmpty(moaSessionID)) {
+ // No authentication session has been started before
+ Logger.error("MOA-SessionID was not found, no previous AuthnRequest had been started");
+ Logger.debug("PEPSConnectorURL was: " + request.getRequestURL());
+ throw new AuthenticationException("auth.02", new Object[] { moaSessionID });
+
+ } else
+ Logger.trace("Use MOA SessionID " + moaSessionID + " from AuthnResponse->inResponseTo attribute.");
+
+ } else
+ // Logger.trace("MOA SessionID " + moaSessionID + " is found in http GET parameter.");
+ Logger.trace("MOA SessionID " + moaSessionID + " is found in SAML2 relayState.");
+
+ /*
+ * INFO!!!! SAML message IDs has an different format then MOASessionIDs This is only a workaround because
+ * many PEPS does not support SAML2 relayState or MOASessionID as AttributConsumerServiceURL GET parameter
+ */
+ // if (!ParamValidatorUtils.isValidSessionID(moaSessionID))
+ // throw new WrongParametersException("VerifyAuthenticationBlock", PARAM_SESSIONID, "auth.12");
+
+ pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(moaSessionID);
+
+ // load MOASession from database
+ AuthenticationSession moaSession = AuthenticationServer.getSession(moaSessionID);
+ // change MOASessionID
+ moaSessionID = AuthenticationSessionStoreage.changeSessionID(moaSession);
+
+ Logger.info("Found MOA sessionID: " + moaSessionID);
+
+ String statusCodeValue = authnResponse.getStatusCode();
+
+ if (!statusCodeValue.equals(StatusCode.SUCCESS_URI)) {
+ Logger.error("Received ErrorResponse from PEPS: " + statusCodeValue);
+ throw new MOAIDException("stork.06", new Object[] { statusCodeValue });
+ }
+
+ Logger.info("Got SAML response with authentication success message.");
+
+ Logger.debug("MOA session is still valid");
+
+ STORKAuthnRequest storkAuthnRequest = moaSession.getStorkAuthnRequest();
+
+ if (storkAuthnRequest == null) {
+ Logger.error("Could not find any preceeding STORK AuthnRequest to this MOA session: " + moaSessionID);
+ throw new MOAIDException("stork.07", null);
+ }
+
+ Logger.debug("Found a preceeding STORK AuthnRequest to this MOA session: " + moaSessionID);
+
+ // //////////// incorporate gender from parameters if not in stork response
+
+ IPersonalAttributeList attributeList = authnResponse.getPersonalAttributeList();
+
+ // but first, check if we have a representation case
+ if (STORKResponseProcessor.hasAttribute("mandateContent", attributeList)
+ || STORKResponseProcessor.hasAttribute("representative", attributeList)
+ || STORKResponseProcessor.hasAttribute("represented", attributeList)) {
+ // in a representation case...
+ moaSession.setUseMandate("true");
+
+ // and check if we have the gender value
+ PersonalAttribute gender = attributeList.get("gender");
+ if (null == gender) {
+ String gendervalue = (String) request.getParameter("gender");
+ if (null != gendervalue) {
+ gender = new PersonalAttribute();
+ gender.setName("gender");
+ ArrayList<String> tmp = new ArrayList<String>();
+ tmp.add(gendervalue);
+ gender.setValue(tmp);
+
+ authnResponse.getPersonalAttributeList().add(gender);
+ }
+ }
+ }
+
+
+
+ // ////////////////////////////////////////////////////////////////////////
+
+ Logger.debug("Starting extraction of signedDoc attribute");
+ // extract signed doc element and citizen signature
+ String citizenSignature = null;
+ try {
+ PersonalAttribute signedDoc = authnResponse.getPersonalAttributeList().get("signedDoc");
+ String signatureInfo = null;
+ // FIXME: Remove nonsense code (signedDoc attribute... (throw Exception for "should not occur" situations)), adjust error messages in order to reflect the true problem...
+ if (signedDoc != null) {
+ signatureInfo = signedDoc.getValue().get(0);
+ // should not occur
+ } else {
+
+ // store SAMLResponse
+ moaSession.setSAMLResponse(request.getParameter("SAMLResponse"));
+ // store authnResponse
+
+ // moaSession.setAuthnResponse(authnResponse);//not serializable
+ moaSession.setAuthnResponseGetPersonalAttributeList(authnResponse.getPersonalAttributeList());
+
+ String authnContextClassRef = null;
+ try {
+ authnContextClassRef = authnResponse.getAssertions().get(0).getAuthnStatements().get(0)
+ .getAuthnContext().getAuthnContextClassRef().getAuthnContextClassRef();
+ } catch (Throwable e) {
+ Logger.warn("STORK QAA-Level is not found in AuthnResponse. Set QAA Level to requested level");
+ }
+
+ moaSession.setAuthnContextClassRef(authnContextClassRef);
+ moaSession.setReturnURL(request.getRequestURL());
+
+ // load signedDoc
+ String signRequest = moaSession.getSignedDoc();
+
+ // session is implicit stored in changeSessionID!!!!
+ String newMOASessionID = AuthenticationSessionStoreage.changeSessionID(moaSession);
+
+ // set return url to PEPSConnectorWithLocalSigningServlet and add newMOASessionID
+ // signRequest
+
+ String issuerValue = AuthConfigurationProvider.getInstance().getPublicURLPrefix();
+ String acsURL = issuerValue
+ + PEPSConnectorWithLocalSigningServlet.PEPSCONNECTOR_SERVLET_URL_PATTERN;
+
+ String url = acsURL + "?moaSessionID=" + newMOASessionID;
+ // redirect to OASIS module and sign there
+
+ boolean found = false;
+ try {
+ List<AttributeProviderPlugin> aps = AuthConfigurationProvider.getInstance()
+ .getOnlineApplicationParameter(moaSession.getPublicOAURLPrefix()).getStorkAPs();
+ Logger.info("Found AttributeProviderPlugins:" + aps.size());
+ for (AttributeProviderPlugin ap : aps) {
+ Logger.info("Found AttributeProviderPlugin attribute:" + ap.getAttributes());
+ if (ap.getAttributes().equalsIgnoreCase("signedDoc")) {
+ // FIXME: A servlet's class field is not thread safe!!!
+ oasisDssWebFormURL = ap.getUrl();
+ found = true;
+ Logger.info("Loaded signedDoc attribute provider url from config:" + oasisDssWebFormURL);
+ break;
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ Logger.error("Loading the signedDoc attribute provider url from config failed");
+ }
+ if (!found) {
+ Logger.error("Failed to load the signedDoc attribute provider url from config");
+ }
+ performRedirect(url, request, response, signRequest);
+
+ return;
+ }
+
+ // FIXME: This servlet/task is intended to handle peps responses without signature, so why do we try to process that signature here?
+ SignResponse dssSignResponse = (SignResponse) ApiUtils.unmarshal(new StreamSource(
+ new java.io.StringReader(signatureInfo)));
+
+ citizenSignature = getCitizienSignatureFromSignResponse(dssSignResponse);
+
+ // memorize signature into authblock
+ moaSession.setAuthBlock(citizenSignature);
+
+ X509Certificate cert = getSignerCertificate(citizenSignature);
+ moaSession.setSignerCertificate(cert);
+ moaSession.setForeigner(true);
+
+ } catch (Throwable e) {
+ Logger.error("Could not extract citizen signature from C-PEPS", e);
+ throw new MOAIDException("stork.09", null);
+ }
+
+ // FIXME: Same here; we do not have the citizen's signature, so this code might be regarded as dead code.
+ try {
+ SZRGInsertion(moaSession, authnResponse.getPersonalAttributeList(), authnResponse.getAssertions()
+ .get(0).getAuthnStatements().get(0).getAuthnContext().getAuthnContextClassRef()
+ .getAuthnContextClassRef(), citizenSignature);
+ } catch (STORKException e) {
+ // this is really nasty but we work against the system here. We are supposed to get the gender attribute
+ // from
+ // stork. If we do not, we cannot register the person in the ERnP - we have to have the
+ // gender for the represented person. So here comes the dirty hack.
+ if (e.getCause() instanceof STORKException
+ && e.getCause().getMessage().equals("gender not found in response")) {
+ try {
+ Logger.trace("Initialize VelocityEngine...");
+
+ VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine();
+ Template template = velocityEngine.getTemplate("/resources/templates/fetchGender.html");
+ VelocityContext context = new VelocityContext();
+ context.put("SAMLResponse", request.getParameter("SAMLResponse"));
+ context.put("action", request.getRequestURL());
+
+ StringWriter writer = new StringWriter();
+ template.merge(context, writer);
+
+ response.getOutputStream().write(writer.toString().getBytes("UTF-8"));
+ } catch (Exception e1) {
+ Logger.error("Error sending gender retrival form.", e1);
+ // httpSession.invalidate();
+ throw new MOAIDException("stork.10", null);
+ }
+
+ return;
+ }
+
+ Logger.error("Error connecting SZR Gateway", e);
+ throw new MOAIDException("stork.10", null);
+ }
+
+ Logger.debug("Add full STORK AuthnResponse to MOA session");
+ moaSession.setStorkAuthnResponse(request.getParameter("SAMLResponse"));// TODO ask Florian/Thomas
+ // authnResponse?
+
+ // session is implicit stored in changeSessionID!!!!
+ String newMOASessionID = AuthenticationSessionStoreage.changeSessionID(moaSession);
+
+ Logger.info("Changed MOASession " + moaSessionID + " to Session " + newMOASessionID);
+
+ // redirect
+ String redirectURL = null;
+ redirectURL = new DataURLBuilder().buildDataURL(moaSession.getAuthURL(),
+ ModulUtils.buildAuthURL(moaSession.getModul(), moaSession.getAction(), pendingRequestID),
+ newMOASessionID);
+ redirectURL = response.encodeRedirectURL(redirectURL);
+
+ response.setContentType("text/html");
+ response.setStatus(302);
+ response.addHeader("Location", redirectURL);
+ Logger.info("REDIRECT TO: " + redirectURL);
+
+ } catch (AuthenticationException e) {
+ handleError(null, e, request, response, pendingRequestID);
+
+ } catch (MOAIDException e) {
+ handleError(null, e, request, response, pendingRequestID);
+
+ } catch (Exception e) {
+ Logger.error("PEPSConnector has an interal Error.", e);
+ }
+
+ finally {
+ ConfigurationDBUtils.closeSession();
+ }
+
+ }
+
+ private void performRedirect(String url, HttpServletRequest req, HttpServletResponse resp, String signRequestString)
+ throws MOAIDException {
+
+ try {
+ Logger.trace("Initialize VelocityEngine...");
+
+ VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine();
+ Template template = velocityEngine.getTemplate("/resources/templates/oasis_dss_webform_binding.vm");
+ VelocityContext context = new VelocityContext();
+
+ Logger.debug("performRedirect, signrequest:" + signRequestString);
+ Source signDoc = new StreamSource(new java.io.StringReader(signRequestString));
+ SignRequest signRequest = ApiUtils.unmarshal(signDoc, SignRequest.class);
+ signRequest.setReturnURL("TODO");
+ signRequestString = IOUtils.toString(ApiUtils.marshalToInputStream(signRequest));
+ context.put("signrequest", Base64.encodeBase64String(signRequestString.getBytes("UTF8")));
+ context.put("clienturl", url);
+ context.put("action", oasisDssWebFormURL);
+
+ StringWriter writer = new StringWriter();
+ template.merge(context, writer);
+
+ resp.getOutputStream().write(writer.toString().getBytes("UTF-8"));
+ } catch (Exception e) {
+ Logger.error("Error sending DSS signrequest.", e);
+ throw new MOAIDException("stork.11", null);
+ }
+ }
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorTask.java
new file mode 100644
index 000000000..296132e76
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorTask.java
@@ -0,0 +1,567 @@
+package at.gv.egovernment.moa.id.auth.modules.stork.tasks;
+
+import iaik.x509.X509Certificate;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Properties;
+
+import javax.activation.DataSource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.namespace.QName;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.ws.BindingProvider;
+import javax.xml.ws.Service;
+import javax.xml.ws.soap.SOAPBinding;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+import org.opensaml.saml2.core.StatusCode;
+
+import com.datentechnik.process_engine.api.ExecutionContext;
+
+import eu.stork.documentservice.DocumentService;
+import eu.stork.documentservice.data.DatabaseConnectorMySQLImpl;
+import eu.stork.oasisdss.api.ApiUtils;
+import eu.stork.oasisdss.api.LightweightSourceResolver;
+import eu.stork.oasisdss.api.exceptions.ApiUtilsException;
+import eu.stork.oasisdss.profile.DocumentType;
+import eu.stork.oasisdss.profile.DocumentWithSignature;
+import eu.stork.oasisdss.profile.SignResponse;
+import eu.stork.peps.auth.commons.IPersonalAttributeList;
+import eu.stork.peps.auth.commons.PEPSUtil;
+import eu.stork.peps.auth.commons.PersonalAttribute;
+import eu.stork.peps.auth.commons.PersonalAttributeList;
+import eu.stork.peps.auth.commons.STORKAttrQueryRequest;
+import eu.stork.peps.auth.commons.STORKAuthnRequest;
+import eu.stork.peps.auth.commons.STORKAuthnResponse;
+import eu.stork.peps.auth.engine.STORKSAMLEngine;
+import eu.stork.peps.exceptions.STORKSAMLEngineException;
+import at.gv.egovernment.moa.id.auth.AuthenticationServer;
+import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder;
+import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
+import at.gv.egovernment.moa.id.auth.data.IdentityLink;
+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.internal.tasks.AbstractAuthServletTask;
+import at.gv.egovernment.moa.id.auth.stork.STORKException;
+import at.gv.egovernment.moa.id.auth.stork.STORKResponseProcessor;
+import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
+import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
+import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
+import at.gv.egovernment.moa.id.moduls.ModulUtils;
+import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants;
+import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
+import at.gv.egovernment.moa.id.util.HTTPUtils;
+import at.gv.egovernment.moa.id.util.VelocityProvider;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.StringUtils;
+import at.gv.util.xsd.xmldsig.SignatureType;
+import at.gv.util.xsd.xmldsig.X509DataType;
+
+/**
+ * Evaluates the SAML response from the C-PEPS and authenticates the user.
+ * <p/>
+ * In detail:
+ * <ul>
+ * <li>Decodes and validates the SAML response from the C-PEPS.</li>
+ * <li>Change moa session id.</li>
+ * <li>Extracts the subject's gender from request parameter {@code gender} if not available from the saml response.</li>
+ * <li>Extracts the {@code signedDoc} attribute from the response, get signed doc payload using stork attribute query request.</li>
+ * <li>Request SZR gateway for verification of the citizen's signature and for creating of an identity link.</li>
+ * <li>In case of mandate mode: If the S-PEPS did not provide any gender information, the szr gateway will not be able to issue an identity link. Therefore a form is presented asking for the subject's gender. The form submits the user back to the {@code /PepsConnector} servlet (this task).</li>
+ * <li>The moa session is updated with authentication information.</li>
+ * <li>Change moa session id.</li>
+ * <li>Redirects back to {@code /dispatcher} in order to finalize the authentication.</li>
+ * </ul>
+ * Expects:
+ * <ul>
+ * <li>HttpServletRequest parameter {@code SAMLResponse}</li>
+ * <li>Either HttpServletRequest parameter {@code RelayState} or {@code inResponseTo} attribute from the SAML response (both depicting the moa session id)</li>
+ * <li>HttpServletRequest parameter {@code gender} in case the request comes from the gender selection form</li>
+ * <li>{@code signedDoc} attribute within the SAML response.</li>
+ * </ul>
+ * Result:
+ * <ul>
+ * <li>Updated moa id session (identity link, stork attributes...)</li>
+ * <li>{@link ExecutionContext} contains boolean flag {@code identityLinkAvailable} indicating if an identitylink has been successfully creates or not.</li>
+ * <li>Redirect to {@code /dispatcher}.</li>
+ * </ul>
+ * Possible branches:
+ * <ul>
+ * <li>In case the szr gateway throws exception due to missing gender information:
+ * <ul>
+ * <li>Returns a form for gender selection with action url back to this servlet/task.</li>
+ * </ul>
+ * </li>
+ * </ul>
+ * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.PEPSConnectorServlet}.<br/>
+ *
+ * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
+ */
+public class PepsConnectorTask extends AbstractAuthServletTask {
+
+ private String dtlUrl = null;
+
+ public PepsConnectorTask() {
+ super();
+ Properties props = new Properties();
+ try {
+ props.load(DatabaseConnectorMySQLImpl.class.getResourceAsStream("docservice.properties"));
+ dtlUrl = props.getProperty("docservice.url");
+ } catch (IOException e) {
+ dtlUrl = "http://testvidp.buergerkarte.at/DocumentService/DocumentService";
+ Logger.error("Loading DTL config failed, using default value:" + dtlUrl);
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response)
+ throws Exception {
+ String pendingRequestID = null;
+
+ setNoCachingHeaders(response);
+
+ try {
+
+ Logger.info("PEPSConnector Servlet invoked, expecting C-PEPS message.");
+ Logger.debug("This ACS endpoint is: " + HTTPUtils.getBaseURL(request));
+
+ // check if https or only http
+ super.checkIfHTTPisAllowed(request.getRequestURL().toString());
+
+ Logger.debug("Beginning to extract SAMLResponse out of HTTP Request");
+
+ // extract STORK Response from HTTP Request
+ // Decodes SAML Response
+ byte[] decSamlToken;
+ try {
+ decSamlToken = PEPSUtil.decodeSAMLToken(request.getParameter("SAMLResponse"));
+ Logger.debug("SAMLResponse: " + new String(decSamlToken));
+
+ } catch (NullPointerException e) {
+ Logger.error("Unable to retrieve STORK Response", e);
+ throw new MOAIDException("stork.04", null);
+ }
+
+ // Get SAMLEngine instance
+ STORKSAMLEngine engine = STORKSAMLEngine.getInstance("outgoing");
+
+ STORKAuthnResponse authnResponse = null;
+ try {
+ // validate SAML Token
+ Logger.debug("Starting validation of SAML response");
+ authnResponse = engine.validateSTORKAuthnResponse(decSamlToken, (String) request.getRemoteHost());
+ Logger.info("SAML response succesfully verified!");
+ } catch (STORKSAMLEngineException e) {
+ Logger.error("Failed to verify STORK SAML Response", e);
+ throw new MOAIDException("stork.05", null);
+ }
+
+ Logger.info("STORK SAML Response message succesfully extracted");
+ Logger.debug("STORK response: ");
+ Logger.debug(authnResponse.toString());
+
+ Logger.debug("Trying to find MOA Session-ID ...");
+ // String moaSessionID = request.getParameter(PARAM_SESSIONID);
+ // first use SAML2 relayState
+ String moaSessionID = request.getParameter("RelayState");
+
+ // escape parameter strings
+ moaSessionID = StringEscapeUtils.escapeHtml(moaSessionID);
+
+ // check if SAML2 relaystate includes a MOA sessionID
+ if (StringUtils.isEmpty(moaSessionID)) {
+ // if relaystate is emtpty, use SAML response -> inResponseTo element as session identifier
+
+ moaSessionID = authnResponse.getInResponseTo();
+ moaSessionID = StringEscapeUtils.escapeHtml(moaSessionID);
+
+ if (StringUtils.isEmpty(moaSessionID)) {
+ // No authentication session has been started before
+ Logger.error("MOA-SessionID was not found, no previous AuthnRequest had been started");
+ Logger.debug("PEPSConnectorURL was: " + request.getRequestURL());
+ throw new AuthenticationException("auth.02", new Object[] { moaSessionID });
+
+ } else
+ Logger.trace("Use MOA SessionID " + moaSessionID + " from AuthnResponse->inResponseTo attribute.");
+
+ } else
+ // Logger.trace("MOA SessionID " + moaSessionID + " is found in http GET parameter.");
+ Logger.trace("MOA SessionID " + moaSessionID + " is found in SAML2 relayState.");
+
+ /*
+ * INFO!!!! SAML message IDs has an different format then MOASessionIDs This is only a workaround because
+ * many PEPS does not support SAML2 relayState or MOASessionID as AttributConsumerServiceURL GET parameter
+ */
+ // if (!ParamValidatorUtils.isValidSessionID(moaSessionID))
+ // throw new WrongParametersException("VerifyAuthenticationBlock", PARAM_SESSIONID, "auth.12");
+
+ pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(moaSessionID);
+
+ // load MOASession from database
+ AuthenticationSession moaSession = AuthenticationServer.getSession(moaSessionID);
+ // change MOASessionID
+ moaSessionID = AuthenticationSessionStoreage.changeSessionID(moaSession);
+
+ Logger.info("Found MOA sessionID: " + moaSessionID);
+
+ String statusCodeValue = authnResponse.getStatusCode();
+
+ if (!statusCodeValue.equals(StatusCode.SUCCESS_URI)) {
+ Logger.error("Received ErrorResponse from PEPS: " + statusCodeValue);
+ throw new MOAIDException("stork.06", new Object[] { statusCodeValue });
+ }
+
+ Logger.info("Got SAML response with authentication success message.");
+
+ Logger.debug("MOA session is still valid");
+
+ STORKAuthnRequest storkAuthnRequest = moaSession.getStorkAuthnRequest();
+
+ if (storkAuthnRequest == null) {
+ Logger.error("Could not find any preceeding STORK AuthnRequest to this MOA session: " + moaSessionID);
+ throw new MOAIDException("stork.07", null);
+ }
+
+ Logger.debug("Found a preceeding STORK AuthnRequest to this MOA session: " + moaSessionID);
+
+ // //////////// incorporate gender from parameters if not in stork response
+
+ IPersonalAttributeList attributeList = authnResponse.getPersonalAttributeList();
+
+ // but first, check if we have a representation case
+ if (STORKResponseProcessor.hasAttribute("mandateContent", attributeList)
+ || STORKResponseProcessor.hasAttribute("representative", attributeList)
+ || STORKResponseProcessor.hasAttribute("represented", attributeList)) {
+ // in a representation case...
+ moaSession.setUseMandate("true");
+
+ // and check if we have the gender value
+ PersonalAttribute gender = attributeList.get("gender"); // TODO Do we need to check gender value if
+ // there is no representation case?
+ if (null == gender) {
+ String gendervalue = (String) request.getParameter("gender");
+ if (null != gendervalue) {
+ gender = new PersonalAttribute();
+ gender.setName("gender");
+ ArrayList<String> tmp = new ArrayList<String>();
+ tmp.add(gendervalue);
+ gender.setValue(tmp);
+
+ authnResponse.getPersonalAttributeList().add(gender);
+ }
+ }
+ }
+
+ // ////////////////////////////////////////////////////////////////////////
+
+ Logger.debug("Starting extraction of signedDoc attribute");
+ // extract signed doc element and citizen signature
+ String citizenSignature = null;
+ try {
+ String signatureInfo = authnResponse.getPersonalAttributeList().get("signedDoc").getValue().get(0); // TODO ERROR HANDLING
+
+ Logger.debug("signatureInfo:" + signatureInfo);
+
+ SignResponse dssSignResponse = (SignResponse) ApiUtils.unmarshal(new StreamSource(
+ new java.io.StringReader(signatureInfo)));
+
+ // fetch signed doc
+ DataSource ds = LightweightSourceResolver.getDataSource(dssSignResponse);
+ if (ds == null) {
+ throw new ApiUtilsException("No datasource found in response");
+ }
+
+ InputStream incoming = ds.getInputStream();
+ citizenSignature = IOUtils.toString(incoming);
+ incoming.close();
+
+ Logger.debug("citizenSignature:" + citizenSignature);
+ if (isDocumentServiceUsed(citizenSignature) == true) {
+ Logger.debug("Loading document from DocumentService.");
+ String url = getDtlUrlFromResponse(dssSignResponse);
+ // get Transferrequest
+ String transferRequest = getDocTransferRequest(dssSignResponse.getDocUI(), url);
+ // Load document from DocujmentService
+ byte[] data = getDocumentFromDtl(transferRequest, url);
+ citizenSignature = new String(data, "UTF-8");
+ Logger.debug("Overridung citizenSignature with:" + citizenSignature);
+ }
+
+ JAXBContext ctx = JAXBContext.newInstance(SignatureType.class.getPackage().getName());
+ SignatureType root = ((JAXBElement<SignatureType>) ctx.createUnmarshaller().unmarshal(
+ IOUtils.toInputStream(citizenSignature))).getValue();
+
+ // memorize signature into authblock
+ moaSession.setAuthBlock(citizenSignature);
+
+ // extract certificate
+ for (Object current : root.getKeyInfo().getContent())
+ if (((JAXBElement<?>) current).getValue() instanceof X509DataType) {
+ for (Object currentX509Data : ((JAXBElement<X509DataType>) current).getValue()
+ .getX509IssuerSerialOrX509SKIOrX509SubjectName()) {
+ JAXBElement<?> casted = ((JAXBElement<?>) currentX509Data);
+ if (casted.getName().getLocalPart().equals("X509Certificate")) {
+ moaSession.setSignerCertificate(new X509Certificate(((String) casted.getValue())
+ .getBytes("UTF-8")));
+ break;
+ }
+ }
+ }
+
+ } catch (Throwable e) {
+ Logger.error("Could not extract citizen signature from C-PEPS", e);
+ throw new MOAIDException("stork.09", null);
+ }
+ Logger.debug("Foregin Citizen signature successfully extracted from STORK Assertion (signedDoc)");
+ Logger.debug("Citizen signature will be verified by SZR Gateway!");
+
+ Logger.debug("fetching OAParameters from database");
+
+ // //read configuration paramters of OA
+ // AuthenticationSession moasession;
+ // try {
+ // moasession = AuthenticationSessionStoreage.getSession(moaSessionID);
+ // } catch (MOADatabaseException e2) {
+ // Logger.error("could not retrieve moa session");
+ // throw new AuthenticationException("auth.01", null);
+ // }
+ OAAuthParameter oaParam = AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(
+ moaSession.getPublicOAURLPrefix());
+ if (oaParam == null)
+ throw new AuthenticationException("auth.00", new Object[] { moaSession.getPublicOAURLPrefix() });
+
+ // retrieve target
+ // TODO: check in case of SSO!!!
+ String targetType = null;
+ if (oaParam.getBusinessService()) {
+ String id = oaParam.getIdentityLinkDomainIdentifier();
+ if (id.startsWith(AuthenticationSession.REGISTERANDORDNR_PREFIX_))
+ targetType = id;
+ else
+ targetType = AuthenticationSession.REGISTERANDORDNR_PREFIX_ + moaSession.getDomainIdentifier();
+ } else {
+ targetType = AuthenticationSession.TARGET_PREFIX_ + oaParam.getTarget();
+ }
+
+ Logger.debug("Starting connecting SZR Gateway");
+ // contact SZR Gateway
+ IdentityLink identityLink = null;
+ executionContext.put("identityLinkAvailable", false);
+ try {
+ identityLink = STORKResponseProcessor.connectToSZRGateway(authnResponse.getPersonalAttributeList(),
+ oaParam.getFriendlyName(), targetType, null, oaParam.getMandateProfiles(), citizenSignature);
+ } catch (STORKException e) {
+ // this is really nasty but we work against the system here. We are supposed to get the gender attribute
+ // from
+ // stork. If we do not, we cannot register the person in the ERnP - we have to have the
+ // gender for the represented person. So here comes the dirty hack.
+ if (e.getCause() instanceof STORKException
+ && e.getCause().getMessage().equals("gender not found in response")) {
+ try {
+ Logger.trace("Initialize VelocityEngine...");
+
+ VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine();
+ Template template = velocityEngine.getTemplate("/resources/templates/fetchGender.html");
+ VelocityContext context = new VelocityContext();
+ context.put("SAMLResponse", request.getParameter("SAMLResponse"));
+ context.put("action", request.getRequestURL());
+
+ StringWriter writer = new StringWriter();
+ template.merge(context, writer);
+
+ response.getOutputStream().write(writer.toString().getBytes("UTF-8"));
+ } catch (Exception e1) {
+ Logger.error("Error sending gender retrival form.", e1);
+ // httpSession.invalidate();
+ throw new MOAIDException("stork.10", null);
+ }
+
+ return;
+ }
+
+ Logger.error("Error connecting SZR Gateway", e);
+ throw new MOAIDException("stork.10", null);
+ }
+ 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);
+ }
+ moaSession.setForeigner(true);
+
+ Logger.info("Received Identity Link from SZR Gateway");
+ executionContext.put("identityLinkAvailable", true);
+ moaSession.setIdentityLink(identityLink);
+
+ Logger.debug("Adding addtional STORK attributes to MOA session");
+ moaSession.setStorkAttributes(authnResponse.getPersonalAttributeList());
+
+ Logger.debug("Add full STORK AuthnResponse to MOA session");
+ moaSession.setStorkAuthnResponse(request.getParameter("SAMLResponse"));
+
+ // We don't have BKUURL, setting from null to "Not applicable"
+ moaSession.setBkuURL("Not applicable (STORK Authentication)");
+
+ // free for single use
+ moaSession.setAuthenticatedUsed(false);
+
+ // stork did the authentication step
+ moaSession.setAuthenticated(true);
+
+ // TODO: found better solution, but QAA Level in response could be not supported yet
+ try {
+
+ moaSession.setQAALevel(authnResponse.getAssertions().get(0).getAuthnStatements().get(0)
+ .getAuthnContext().getAuthnContextClassRef().getAuthnContextClassRef());
+
+ } catch (Throwable e) {
+ Logger.warn("STORK QAA-Level is not found in AuthnResponse. Set QAA Level to requested level");
+ moaSession.setQAALevel(PVPConstants.STORK_QAA_PREFIX + oaParam.getQaaLevel());
+
+ }
+
+ // session is implicit stored in changeSessionID!!!!
+ String newMOASessionID = AuthenticationSessionStoreage.changeSessionID(moaSession);
+
+ Logger.info("Changed MOASession " + moaSessionID + " to Session " + newMOASessionID);
+
+ // redirect
+ String redirectURL = null;
+ redirectURL = new DataURLBuilder().buildDataURL(moaSession.getAuthURL(),
+ ModulUtils.buildAuthURL(moaSession.getModul(), moaSession.getAction(), pendingRequestID),
+ newMOASessionID);
+ redirectURL = response.encodeRedirectURL(redirectURL);
+
+ // response.setContentType("text/html");
+ // response.setStatus(302);
+ // response.addHeader("Location", redirectURL);
+ response.sendRedirect(redirectURL);
+ Logger.info("REDIRECT TO: " + redirectURL);
+
+ } catch (AuthenticationException e) {
+ handleError(null, e, request, response, pendingRequestID);
+
+ } catch (MOAIDException e) {
+ handleError(null, e, request, response, pendingRequestID);
+
+ } catch (Exception e) {
+ Logger.error("PEPSConnector has an interal Error.", e);
+ }
+
+ finally {
+ ConfigurationDBUtils.closeSession();
+ }
+
+ }
+
+ private boolean isDocumentServiceUsed(String citizenSignature) // TODo add better check
+ {
+ if (citizenSignature
+ .contains("<table border=\"0\"><tr><td>Service Name:</td><td>{http://stork.eu}DocumentService</td></tr><tr><td>Port Name:</td><td>{http://stork.eu}DocumentServicePort</td></tr></table>"))
+ return true;
+ return false;
+ }
+
+ /**
+ * Get DTL uril from the oasis sign response
+ *
+ * @param signRequest
+ * The signature response
+ * @return The URL of DTL service
+ * @throws SimpleException
+ */
+ private String getDtlUrlFromResponse(SignResponse dssSignResponse) {
+ List<DocumentWithSignature> documents = ApiUtils.findNamedElement(dssSignResponse.getOptionalOutputs(),
+ ApiUtils.OPTIONAL_OUTPUT_DOCUMENTWITHSIGNATURE, DocumentWithSignature.class);
+ DocumentType sourceDocument = documents.get(0).getDocument();
+
+ if (sourceDocument.getDocumentURL() != null)
+ return sourceDocument.getDocumentURL();
+ else
+ return null;// throw new Exception("No document url found");
+ }
+
+ // From DTLPEPSUTIL
+
+ /**
+ * Get document from DTL
+ *
+ * @param transferRequest
+ * The transfer request (attribute query)
+ * @param eDtlUrl
+ * The DTL url of external DTL
+ * @return the document data
+ * @throws SimpleException
+ */
+ private byte[] getDocumentFromDtl(String transferRequest, String eDtlUrl) throws Exception {
+ URL url = null;
+ try {
+ url = new URL(dtlUrl);
+ QName qname = new QName("http://stork.eu", "DocumentService");
+
+ Service service = Service.create(url, qname);
+ DocumentService docservice = service.getPort(DocumentService.class);
+
+ BindingProvider bp = (BindingProvider) docservice;
+ SOAPBinding binding = (SOAPBinding) bp.getBinding();
+ binding.setMTOMEnabled(true);
+
+ if (eDtlUrl.equalsIgnoreCase(dtlUrl))
+ return docservice.getDocument(transferRequest, "");
+ else
+ return docservice.getDocument(transferRequest, eDtlUrl);
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new Exception("Error in getDocumentFromDtl", e);
+ }
+ }
+
+ /**
+ * Get a document transfer request (attribute query)
+ *
+ * @param docId
+ * @return
+ * @throws SimpleException
+ */
+ private String getDocTransferRequest(String docId, String destinationUrl) throws Exception {
+ String spCountry = docId.substring(0, docId.indexOf("/"));
+ final STORKSAMLEngine engine = STORKSAMLEngine.getInstance("VIDP");
+ STORKAttrQueryRequest req = new STORKAttrQueryRequest();
+ req.setAssertionConsumerServiceURL(dtlUrl);
+ req.setDestination(destinationUrl);
+ req.setSpCountry(spCountry);
+ req.setQaa(3);// TODO
+ PersonalAttributeList pal = new PersonalAttributeList();
+ PersonalAttribute attr = new PersonalAttribute();
+ attr.setName("docRequest");
+ attr.setIsRequired(true);
+ attr.setValue(Arrays.asList(docId));
+ pal.add(attr);
+ req.setPersonalAttributeList(pal);
+
+ STORKAttrQueryRequest req1;
+ try {
+ req1 = engine.generateSTORKAttrQueryRequest(req);
+ return PEPSUtil.encodeSAMLTokenUrlSafe(req1.getTokenSaml());
+ } catch (STORKSAMLEngineException e) {
+ e.printStackTrace();
+ throw new Exception("Error in doc request attribute query generation", e);
+ }
+ }
+
+}