aboutsummaryrefslogtreecommitdiff
path: root/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz
diff options
context:
space:
mode:
Diffstat (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz')
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/Constants.java66
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/eIDASAuthenticationModulImpl.java8
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/eIDASAuthenticationSpringResourceProvider.java2
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/eIDASSignalServlet.java89
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/exception/SZRCommunicationException.java15
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/exception/eIDASAttributeException.java15
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/exception/eIDASAuthenticationException.java8
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/exception/eIDASValidationException.java14
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/service/eIDASAttributeRegistry.java114
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/szr/SZRClient.java372
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/szr/SZRService.java139
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/CreateIdentityLinkTask.java391
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/GenerateAuthnRequestTask.java425
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/ReceiveAuthnResponseTask.java163
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/utils/LoggingHandler.java52
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/utils/eIDASResponseUtils.java98
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/validator/eIDASResponseValidator.java135
17 files changed, 1654 insertions, 452 deletions
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/Constants.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/Constants.java
index de7d9100..b1cd128f 100644
--- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/Constants.java
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/Constants.java
@@ -7,13 +7,60 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import at.gv.egiz.eaaf.core.api.data.EAAFConstants;
+
public class Constants {
+ public static final String EXECUTIONCONTEXT_SELECTED_COUNTRY = "selectedCountry";
+ public static final String DATA_REQUESTERID = "req_requesterId";
+ public static final String DATA_PROVIDERNAME = "req_providerName";
+ public static final String DATA_REQUESTED_LOA_LIST = "req_requestedLoA";
+ public static final String DATA_REQUESTED_LOA_COMPERISON = "req_requestedLoAComperision";
+ public static final String DATA_FULL_EIDAS_RESPONSE = "resp_fulleIDASResponse";
+
+
+ //templates for post-binding forwarding
+ public static final String TEMPLATE_POST_FORWARD_NAME = "eidas_node_forward.html";
+ public static final String TEMPLATE_POST_FORWARD_ENDPOINT = "endPoint";
+ public static final String TEMPLATE_POST_FORWARD_TOKEN_NAME = "tokenName";
+ public static final String TEMPLATE_POST_FORWARD_TOKEN_VALUE = "tokenValue";
+
+
//configuration properties
public static final String CONIG_PROPS_EIDAS_PREFIX="auth.eIDAS";
public static final String CONIG_PROPS_EIDAS_NODE= CONIG_PROPS_EIDAS_PREFIX + ".node_v2";
public static final String CONIG_PROPS_EIDAS_NODE_COUNTRYCODE = CONIG_PROPS_EIDAS_NODE + ".countrycode";
+ public static final String CONIG_PROPS_EIDAS_NODE_PUBLICSECTOR_TARGETS = CONIG_PROPS_EIDAS_NODE + ".publicSectorTargets";
+ public static final String CONIG_PROPS_EIDAS_NODE_ENTITYID = CONIG_PROPS_EIDAS_NODE + ".entityId";
+ public static final String CONIG_PROPS_EIDAS_NODE_FORWARD_URL = CONIG_PROPS_EIDAS_NODE + ".forward.endpoint";
+ public static final String CONIG_PROPS_EIDAS_NODE_FORWARD_METHOD = CONIG_PROPS_EIDAS_NODE + ".forward.method";
+ public static final String CONIG_PROPS_EIDAS_NODE_ATTRIBUTES_REQUESTED_ONLYNATURAL = CONIG_PROPS_EIDAS_NODE + ".attributes.requested.onlynatural.";
+ public static final String CONIG_PROPS_EIDAS_NODE_ATTRIBUTES_REQUESTED_REPRESENTATION = CONIG_PROPS_EIDAS_NODE + ".attributes.requested.representation.";
+ public static final String CONIG_PROPS_EIDAS_NODE_WORKAROUND_ADD_ALWAYS_PROVIDERNAME = CONIG_PROPS_EIDAS_NODE + ".workarounds.addAlwaysProviderName";;
+ public static final String CONIG_PROPS_EIDAS_NODE_WORKAROUND_USEREQUESTIDASTRANSACTIONIDENTIFIER = CONIG_PROPS_EIDAS_NODE + ".workarounds.useRequestIdAsTransactionIdentifier";
+ public static final String FORWARD_METHOD_POST = "POST";
+ public static final String FORWARD_METHOD_GET = "GET";
+
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT= CONIG_PROPS_EIDAS_PREFIX + ".szrclient";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_USETESTSERVICE= CONIG_PROPS_EIDAS_SZRCLIENT + ".useTestService";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_DEBUG_TRACEMESSAGES= CONIG_PROPS_EIDAS_SZRCLIENT + ".debug.logfullmessages";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_DEBUG_USEDUMMY= CONIG_PROPS_EIDAS_SZRCLIENT + ".debug.useDummySolution";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_DEBUG_INSERTERNB= CONIG_PROPS_EIDAS_SZRCLIENT + ".debug.insertERnB";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_TIMEOUT_CONNECTION= CONIG_PROPS_EIDAS_SZRCLIENT + ".timeout.connection";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_TIMEOUT_RESPONSE= CONIG_PROPS_EIDAS_SZRCLIENT + ".timeout.response";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_ENDPOINT_PROD= CONIG_PROPS_EIDAS_SZRCLIENT + ".endpoint.prod";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_ENDPOINT_TEST= CONIG_PROPS_EIDAS_SZRCLIENT + ".endpoint.test";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_SSL_KEYSTORE_PATH = CONIG_PROPS_EIDAS_SZRCLIENT + ".ssl.keyStore.path";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_SSL_KEYSTORE_PASSWORD = CONIG_PROPS_EIDAS_SZRCLIENT + ".ssl.keyStore.password";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_SSL_TRUSTSTORE_PATH = CONIG_PROPS_EIDAS_SZRCLIENT + ".ssl.trustStore.path";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_SSL_TRUSTSTORE_PASSWORD = CONIG_PROPS_EIDAS_SZRCLIENT + ".ssl.trustStore.password";
+
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_EDOCUMENTTYPE = CONIG_PROPS_EIDAS_SZRCLIENT + ".params.documenttype";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_VKZ = CONIG_PROPS_EIDAS_SZRCLIENT + ".params.vkz";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_ISSUING_DATE = CONIG_PROPS_EIDAS_SZRCLIENT + ".params.issuingdate";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_ISSUING_AUTHORITY = CONIG_PROPS_EIDAS_SZRCLIENT + ".params.issuingauthority";
+ public static final String CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_KEYS_USEDUMMY= CONIG_PROPS_EIDAS_SZRCLIENT + ".params.usedummykeys";
//http endpoint descriptions
public static final String eIDAS_HTTP_ENDPOINT_SP_POST = "/eidas/light/sp/post";
@@ -42,4 +89,23 @@ public class Constants {
// add(eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.PERSON_IDENTIFIER.getNameUri());
}
});
+
+ public static final String POLICY_DEFAULT_ALLOWED_TARGETS =
+ EAAFConstants.URN_PREFIX_CDID.replaceAll("\\.", "\\\\.").replaceAll("\\+", "\\\\+") + ".*";
+
+ //SAML2 Constants
+ public static final String SUCCESS_URI = "urn:oasis:names:tc:SAML:2.0:status:Success";
+
+ public static final String HTTP_CLIENT_DEFAULT_TIMEOUT_CONNECTION = "30"; //seconds
+ public static final String HTTP_CLIENT_DEFAULT_TIMEOUT_RESPONSE = "60"; //seconds
+
+
+ //Default values for SZR communication
+ public static final String SZR_CONSTANTS_DEFAULT_DOCUMENT_TYPE = "ELEKTR_DOKUMENT";
+
+ //TODO remove!!!
+ public static final String SZR_CONSTANTS_DEFAULT_ISSUING_DATE = "2014-01-01";
+ public static final String SZR_CONSTANTS_DEFAULT_ISSUING_AUTHORITY = "ms-specific eIDAS-Node for AT";
+ public final static byte[] SZR_CONSTANTS_DEFAULT_PUBL_KEY = new byte[] {48, -127, -97, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 1, 5, 0, 3, -127, -115, 0, 48, -127, -119, 2, -127, -127, 0, -106, 114, -113, -1, -84, 116, 35, 3, 70, -81, 81, -110, -10, -59, 114, 4, -109, 86, 127, -50, 125, 47, 4, 80, 79, 53, 117, -36, 15, -16, -61, 110, 39, 89, 29, -43, 37, -127, 80, -109, -38, 65, 125, -119, 44, -111, -21, 47, -98, 38, -112, -24, 107, -110, 17, -10, 51, -4, -36, -72, -28, -18, -14, 117, -67, 76, -31, 32, 92, 104, -21, 68, 31, -12, 30, -104, -104, 42, -107, 126, 84, 50, 85, -117, 44, -100, -4, 102, -100, 52, -68, 77, -32, 9, -16, -30, -104, -90, 107, -88, 7, 97, -94, 72, -61, -40, 80, -112, -65, -25, -72, -19, -95, -54, 31, 15, 24, -105, 123, -81, 23, -123, 92, -103, -101, 47, 47, -105, 2, 3, 1, 0, 1};
+
}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/eIDASAuthenticationModulImpl.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/eIDASAuthenticationModulImpl.java
index 1ce2f949..fef9cbfa 100644
--- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/eIDASAuthenticationModulImpl.java
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/eIDASAuthenticationModulImpl.java
@@ -4,8 +4,8 @@ package at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2;
import org.apache.commons.lang3.StringUtils;
-import at.gv.egovernment.moa.id.auth.modules.AuthModule;
-import at.gv.egovernment.moa.id.process.api.ExecutionContext;
+import at.gv.egiz.eaaf.core.api.idp.auth.modules.AuthModule;
+import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;
/**
* @author tlenz
@@ -33,8 +33,8 @@ public class eIDASAuthenticationModulImpl implements AuthModule {
*/
@Override
public String selectProcess(ExecutionContext context) {
- if (StringUtils.isNotBlank((String) context.get("ccc")) ||
- StringUtils.isNotBlank((String) context.get("CCC")))
+ if (StringUtils.isNotBlank((String) context.get(Constants.EXECUTIONCONTEXT_SELECTED_COUNTRY)) ||
+ StringUtils.isNotBlank((String) context.get(Constants.EXECUTIONCONTEXT_SELECTED_COUNTRY)))
return "eIDASAuthentication_v2";
else
return null;
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/eIDASAuthenticationSpringResourceProvider.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/eIDASAuthenticationSpringResourceProvider.java
index b491b8d8..e067acfb 100644
--- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/eIDASAuthenticationSpringResourceProvider.java
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/eIDASAuthenticationSpringResourceProvider.java
@@ -22,7 +22,7 @@ public class eIDASAuthenticationSpringResourceProvider implements SpringResource
@Override
public Resource[] getResourcesToLoad() {
- ClassPathResource eIDASAuthConfig = new ClassPathResource("/eidas_v2_auth.beans", eIDASAuthenticationSpringResourceProvider.class);
+ ClassPathResource eIDASAuthConfig = new ClassPathResource("/eidas_v2_auth.beans.xml", eIDASAuthenticationSpringResourceProvider.class);
return new Resource[] {eIDASAuthConfig};
}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/eIDASSignalServlet.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/eIDASSignalServlet.java
index 51d1bd0c..77f799e7 100644
--- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/eIDASSignalServlet.java
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/eIDASSignalServlet.java
@@ -8,14 +8,25 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.text.StringEscapeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
-import at.gv.egovernment.moa.id.auth.servlet.AbstractProcessEngineSignalController;
+import com.google.common.collect.ImmutableSortedSet;
+
+import at.gv.egiz.eaaf.core.impl.idp.controller.AbstractProcessEngineSignalController;
+import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.exception.eIDASAuthenticationException;
+import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.service.eIDASAttributeRegistry;
+import eu.eidas.auth.commons.EidasParameterKeys;
+import eu.eidas.auth.commons.light.ILightResponse;
+import eu.eidas.specificcommunication.SpecificCommunicationDefinitionBeanNames;
+import eu.eidas.specificcommunication.exception.SpecificCommunicationException;
+import eu.eidas.specificcommunication.protocol.impl.SpecificConnectorCommunicationServiceImpl;
+
/**
* @author tlenz
@@ -25,9 +36,10 @@ import at.gv.egovernment.moa.id.auth.servlet.AbstractProcessEngineSignalControll
public class eIDASSignalServlet extends AbstractProcessEngineSignalController {
private static final Logger log = LoggerFactory.getLogger(eIDASSignalServlet.class);
+ @Autowired private ApplicationContext context;
+ @Autowired private eIDASAttributeRegistry attrRegistry;
-
- public eIDASSignalServlet() {
+ public eIDASSignalServlet() {
super();
log.debug("Registering servlet " + getClass().getName() +
" with mappings '"+ Constants.eIDAS_HTTP_ENDPOINT_SP_POST +
@@ -39,11 +51,11 @@ public class eIDASSignalServlet extends AbstractProcessEngineSignalController {
Constants.eIDAS_HTTP_ENDPOINT_SP_REDIRECT
},
method = {RequestMethod.POST, RequestMethod.GET})
- public void performCitizenCardAuthentication(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ public void restoreEidasAuthProcess(HttpServletRequest req, HttpServletResponse resp) throws IOException {
signalProcessManagement(req, resp);
}
- @Override
+
/**
* Protocol specific implementation to get the pending-requestID
* from http request object
@@ -52,31 +64,68 @@ public class eIDASSignalServlet extends AbstractProcessEngineSignalController {
* @return The Pending-request id
*
*/
+ @Override
public String getPendingRequestId(HttpServletRequest request) {
- String sessionId = super.getPendingRequestId(request);
+ //String sessionId = super.getPendingRequestId(request);
try {
-
- // use SAML2 relayState
- if (sessionId == null) {
- log.trace("No transaction identifier from pendingReq. Search for SAML2 'RelayState' ...");
- sessionId = StringEscapeUtils.escapeHtml4(request.getParameter("RelayState"));
-
- if (StringUtils.isEmpty(sessionId))
- log.info("NO transaction identifier found! Stopping process ....");
- else
- log.debug("Find transaction identifier in SAML2 'RelayState': " + sessionId);
+ //get token from Request
+ final String tokenBase64 = request.getParameter(EidasParameterKeys.TOKEN.toString());
+ if (StringUtils.isEmpty(tokenBase64)) {
+ log.warn("NO eIDAS message token found.");
+ throw new eIDASAuthenticationException("eidas.04", null);
+ }
+ log.trace("Receive eIDAS-node token: " + tokenBase64 + " Starting transaction-restore process ... ");
- } else
- log.trace("Find transaction identifier from pendingReq.");
+
+
+ final SpecificConnectorCommunicationServiceImpl specificConnectorCommunicationService =
+ (SpecificConnectorCommunicationServiceImpl) context.getBean(SpecificCommunicationDefinitionBeanNames.SPECIFIC_CONNECTOR_COMMUNICATION_SERVICE.toString());
+ ILightResponse eIDASResponse = specificConnectorCommunicationService.getAndRemoveResponse(tokenBase64,
+ ImmutableSortedSet.copyOf(attrRegistry.getCoreAttributeRegistry().getAttributes()));
+
+ String pendingReqId = null;
+ if (StringUtils.isEmpty(eIDASResponse.getRelayState())) {
+ log.debug("eIDAS Node returns no RelayState. ");
+
+ if (authConfig.getBasicMOAIDConfigurationBoolean(
+ Constants.CONIG_PROPS_EIDAS_NODE_WORKAROUND_USEREQUESTIDASTRANSACTIONIDENTIFIER,
+ false)) {
+ log.trace("Use lightRequestId to recover session ... ");
+ pendingReqId = transactionStorage.get(eIDASResponse.getInResponseToId(), String.class);
+ if (StringUtils.isNotEmpty(pendingReqId)) {
+ log.debug("Restoring session with lightRequestId ... ");
+ transactionStorage.remove(eIDASResponse.getInResponseToId());
+
+ }
+ }
+
+ } else {
+ log.debug("Find transaction identifier in SAML2 'RelayState': " + eIDASResponse.getRelayState());
+ pendingReqId = eIDASResponse.getRelayState();
+
+ }
+ if (StringUtils.isNotEmpty(pendingReqId)) {
+ request.setAttribute(Constants.DATA_FULL_EIDAS_RESPONSE, eIDASResponse);
+ return pendingReqId;
+
+ }
+
+ log.info("NO transaction identifier found! Stopping process ....");
+ log.trace("FullResponse: " + eIDASResponse.toString());
+
+ } catch (SpecificCommunicationException e) {
+ log.warn("Can NOT load eIDAS Response from cache.", e);
+ log.debug("eIDAS response token was: " + request.getParameter(EidasParameterKeys.TOKEN.toString()));
+
} catch (Exception e) {
log.warn("Unable to retrieve moa session id.", e);
}
- return sessionId;
+ return null;
}
}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/exception/SZRCommunicationException.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/exception/SZRCommunicationException.java
new file mode 100644
index 00000000..a0c3cf88
--- /dev/null
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/exception/SZRCommunicationException.java
@@ -0,0 +1,15 @@
+package at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.exception;
+
+public class SZRCommunicationException extends eIDASAuthenticationException {
+
+ private static final long serialVersionUID = 1L;
+
+ public SZRCommunicationException(String internalMsgId, Object[] params) {
+ super(internalMsgId, params);
+ }
+
+ public SZRCommunicationException(String internalMsgId, Object[] params, Throwable e) {
+ super(internalMsgId, params, e);
+ }
+
+}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/exception/eIDASAttributeException.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/exception/eIDASAttributeException.java
new file mode 100644
index 00000000..f1d4280f
--- /dev/null
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/exception/eIDASAttributeException.java
@@ -0,0 +1,15 @@
+package at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.exception;
+
+public class eIDASAttributeException extends eIDASAuthenticationException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ public eIDASAttributeException(String attrbuteName) {
+ super("eidas.00", new Object[] {attrbuteName});
+
+ }
+
+}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/exception/eIDASAuthenticationException.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/exception/eIDASAuthenticationException.java
index fff6773e..939e7471 100644
--- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/exception/eIDASAuthenticationException.java
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/exception/eIDASAuthenticationException.java
@@ -9,12 +9,12 @@ public class eIDASAuthenticationException extends EAAFAuthenticationException{
*/
private static final long serialVersionUID = 1L;
- public eIDASAuthenticationException(String internalMsgId, Object[] params, String msg) {
- super(internalMsgId, params, msg);
+ public eIDASAuthenticationException(String internalMsgId, Object[] params) {
+ super(internalMsgId, params);
}
- public eIDASAuthenticationException(String internalMsgId, Object[] params, String msg, Throwable e) {
- super(internalMsgId, params, msg, e);
+ public eIDASAuthenticationException(String internalMsgId, Object[] params, Throwable e) {
+ super(internalMsgId, params, e);
}
}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/exception/eIDASValidationException.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/exception/eIDASValidationException.java
new file mode 100644
index 00000000..7b81eacd
--- /dev/null
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/exception/eIDASValidationException.java
@@ -0,0 +1,14 @@
+package at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.exception;
+
+public class eIDASValidationException extends eIDASAuthenticationException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ public eIDASValidationException(String internalMsgId, Object[] params) {
+ super(internalMsgId, params);
+ }
+
+}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/service/eIDASAttributeRegistry.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/service/eIDASAttributeRegistry.java
new file mode 100644
index 00000000..b3855635
--- /dev/null
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/service/eIDASAttributeRegistry.java
@@ -0,0 +1,114 @@
+package at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.service;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.PostConstruct;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.exceptions.EAAFConfigurationException;
+import at.gv.egiz.eaaf.core.impl.utils.KeyValueUtils;
+import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.Constants;
+import eu.eidas.auth.commons.attribute.AttributeRegistries;
+import eu.eidas.auth.commons.attribute.AttributeRegistry;
+
+@Service("attributeRegistry")
+public class eIDASAttributeRegistry {
+ private static final Logger log = LoggerFactory.getLogger(eIDASAttributeRegistry.class);
+ @Autowired private IConfiguration basicConfig;
+
+ private AttributeRegistry coreAttributeRegistry;
+
+ private String eidasAttributesFile;
+ private String additionalAttributesFile;
+
+ @PostConstruct
+ private void initialize() throws RuntimeException {
+ try {
+ if (eidasAttributesFile.isEmpty()) {
+ log.error("Basic eIDAS addribute definition NOT defined");
+ throw new EAAFConfigurationException("Basic eIDAS addribute definition NOT defined");
+
+ }
+
+ boolean additionalAttrAvailabe = false;
+ if (!additionalAttributesFile.isEmpty()) {
+ File file = new File(additionalAttributesFile);
+ if (file.exists())
+ additionalAttrAvailabe = true;
+
+ }
+
+ if (!additionalAttrAvailabe) {
+ log.info("Start eIDAS ref. impl. Core without additional eIDAS attribute definitions ... ");
+ coreAttributeRegistry = AttributeRegistries.fromFiles(eidasAttributesFile, null);
+
+ } else {
+ //load attribute definitions
+ log.info("Start eIDAS ref. impl. Core with additional eIDAS attribute definitions ... ");
+ coreAttributeRegistry = AttributeRegistries.fromFiles(eidasAttributesFile, null, additionalAttributesFile);
+
+ }
+
+ } catch (Throwable e) {
+ log.error("Can NOT initialize eIDAS attribute definition." , e);
+ new RuntimeException("Can NOT initialize eIDAS attribute definition.", e);
+
+ }
+ }
+
+
+ public AttributeRegistry getCoreAttributeRegistry() {
+ return coreAttributeRegistry;
+ }
+
+ public Map<String, Boolean> getAttributeSetFromConfiguration() {
+ Map<String, Boolean> result = new HashMap<String, Boolean>();
+
+ /*TODO: select set for representation if mandates should be used.
+ * It's an open task in respect to requested eIDAS attributes and isRequired flag,
+ * because there can be a decision problem in case of natural or legal person representation!
+ * From an Austrian use-case point of view, an Austrian service provider can support mandates for
+ * natural and legal persons at the same time. However, we CAN NOT request attributes for natural AND
+ * legal persons on the same time, because it's not possible to represent both simultaneously.
+ */
+ Map<String, String> configAttributes =
+ basicConfig.getBasicMOAIDConfigurationWithPrefix(
+ Constants.CONIG_PROPS_EIDAS_NODE_ATTRIBUTES_REQUESTED_ONLYNATURAL);
+ for (String el: configAttributes.values()) {
+ if (StringUtils.isNotEmpty(el.trim())) {
+ List<String> attrDef = KeyValueUtils.getListOfCSVValues(el.trim());
+ boolean isRequired = false;
+ if (attrDef.size() == 2)
+ isRequired = Boolean.parseBoolean(attrDef.get(1));
+
+ result.put(attrDef.get(0), isRequired);
+
+ }
+ }
+
+ log.trace("Load #" + result.size() + " requested attributes from configuration");
+ return result;
+
+ }
+
+
+ public void setEidasAttributesFile(String eidasAttributesFile) {
+ this.eidasAttributesFile = eidasAttributesFile;
+ }
+
+ public void setAdditionalAttributesFile(String additionalAttributesFile) {
+ this.additionalAttributesFile = additionalAttributesFile;
+ }
+
+
+}
+
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/szr/SZRClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/szr/SZRClient.java
new file mode 100644
index 00000000..86f0d0bb
--- /dev/null
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/szr/SZRClient.java
@@ -0,0 +1,372 @@
+package at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.szr;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.UnrecoverableKeyException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.Resource;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Marshaller;
+import javax.xml.namespace.QName;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.ws.BindingProvider;
+import javax.xml.ws.Dispatch;
+import javax.xml.ws.WebServiceContext;
+import javax.xml.ws.handler.Handler;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.cxf.configuration.jsse.TLSClientParameters;
+import org.apache.cxf.endpoint.Client;
+import org.apache.cxf.frontend.ClientProxy;
+import org.apache.cxf.jaxws.DispatchImpl;
+import org.apache.cxf.transport.http.HTTPConduit;
+import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
+import org.apache.xpath.XPathAPI;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.w3._2000._09.xmldsig.KeyValueType;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import at.gv.egiz.eaaf.core.api.data.XMLNamespaceConstants;
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.impl.utils.DOMUtils;
+import at.gv.egiz.eaaf.core.impl.utils.FileUtils;
+import at.gv.egiz.eaaf.core.impl.utils.KeyStoreUtils;
+import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.Constants;
+import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.exception.SZRCommunicationException;
+import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.utils.LoggingHandler;
+import szrservices.GetBPK;
+import szrservices.GetBPKResponse;
+import szrservices.GetIdentityLink;
+import szrservices.GetIdentityLinkResponse;
+import szrservices.IdentityLinkType;
+import szrservices.PersonInfoType;
+import szrservices.SZR;
+import szrservices.SZRException_Exception;
+
+@Service("SZRClientForeIDAS")
+public class SZRClient {
+ private static final Logger log = LoggerFactory.getLogger(SZRClient.class);
+
+ private static final String CLIENT_DEFAULT = "DefaultClient";
+ private static final String CLIENT_RAW = "RawClient";
+
+ @Autowired private IConfiguration basicConfig;
+ @Resource private WebServiceContext wsContext;
+
+ //client for anything, without identitylink
+ private SZR szr = null;
+
+ //RAW client is needed for identitylink
+ private Dispatch<Source> dispatch = null;
+
+
+ private SZRService szrService = null;
+ private String szrURL = null;
+ private QName qname = null;
+
+ public IdentityLinkType getIdentityLink(PersonInfoType personInfo, List<KeyValueType> keyValue, Boolean insertERnP) throws SZRCommunicationException {
+ try {
+ return szr.getIdentityLink(
+ personInfo,
+ keyValue,
+ insertERnP);
+
+ } catch (SZRException_Exception e) {
+ log.warn("SZR communication FAILED. Reason: " + e.getMessage(), e);
+ throw new SZRCommunicationException("ernb.02", new Object[] {e.getMessage()}, e);
+
+ }
+
+ }
+
+ public IdentityLinkType getIdentityLinkInRawMode(PersonInfoType personInfo, List<KeyValueType> keyValue, Boolean insertERnP) throws SZRCommunicationException {
+ try {
+ GetIdentityLink getIDL = new GetIdentityLink();
+ getIDL.setInsertERnP(insertERnP);
+ getIDL.setPersonInfo(personInfo);
+ getIDL.getKeyValue().addAll(keyValue);
+
+ JAXBContext jaxbContext = JAXBContext.newInstance(GetIdentityLink.class);
+ Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
+
+ final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ jaxbMarshaller.marshal(getIDL, outputStream);
+ outputStream.flush();
+
+ Source source = new StreamSource(new ByteArrayInputStream(outputStream.toByteArray()));
+ outputStream.close();
+
+ log.trace("Requesting SZR ... ");
+ Source response = dispatch.invoke(source);
+ log.trace("Receive RAW response from SZR");
+
+ byte[] szrResponse = sourceToByteArray(response);
+ JAXBContext ctx = JAXBContext.newInstance(IdentityLinkType.class
+ .getPackage().getName());
+ GetIdentityLinkResponse jaxbElement = (GetIdentityLinkResponse) ctx
+ .createUnmarshaller().unmarshal(new ByteArrayInputStream(szrResponse));
+
+
+ //build response
+ log.trace(new String(szrResponse));
+ log.trace("Signature successfully created. Extracting from MOA-SS container.");
+
+ // ok, we have success
+ Document doc = DOMUtils.parseDocument(
+ new ByteArrayInputStream(szrResponse),
+ true, XMLNamespaceConstants.ALL_SCHEMA_LOCATIONS, null, null
+ );
+ String xpathExpression = "//saml:Assertion";
+ Element nsNode = doc.createElementNS("urn:oasis:names:tc:SAML:1.0:assertion", "saml:NSNode");
+
+ log.trace("Selecting signed doc " + xpathExpression);
+ Element documentNode = (Element) XPathAPI.selectSingleNode(doc,
+ xpathExpression, nsNode);
+ log.trace("Signed document: " + DOMUtils.serializeNode(documentNode));
+
+
+ IdentityLinkType idl = new IdentityLinkType();
+ idl.setAssertion(documentNode);
+ idl.setPersonInfo(jaxbElement.getGetIdentityLinkReturn().getPersonInfo());
+
+ return idl;
+
+
+ //IdentityLinkType idlResp = this.szr.getIdentityLink(personInfo, keyValue, insertERnP);
+
+ } catch ( Exception e) {
+ log.warn("SZR communication FAILED. Reason: " + e.getMessage(), e);
+ throw new SZRCommunicationException("ernb.02", new Object[] {e.getMessage()}, e);
+
+ }
+
+ }
+
+ public String getBPK(PersonInfoType personInfo, String target, String vkz) throws SZRCommunicationException {
+ try {
+ GetBPK parameters = new GetBPK();
+ parameters.setPersonInfo(personInfo);
+ parameters.setBereichsKennung(target);
+ parameters.setVKZ(vkz);
+ GetBPKResponse result = this.szr.getBPK(parameters);
+
+ return result.getGetBPKReturn();
+
+ } catch (SZRException_Exception e) {
+ log.warn("SZR communication FAILED. Reason: " + e.getMessage(), e);
+ throw new SZRCommunicationException("ernb.02", new Object[] {e.getMessage()}, e);
+
+ }
+
+ }
+
+
+ @PostConstruct
+ private void initialize() {
+ log.info("Starting SZR-Client initialization .... ");
+ URL url = SZRClient.class.getResource("/szr_client/SZR-1.WSDL");
+
+ boolean useTestSZR = basicConfig.getBasicMOAIDConfigurationBoolean(
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_USETESTSERVICE,
+ true);
+
+ if (useTestSZR) {
+ log.debug("Initializing SZR test environment configuration.");
+ qname = SZRService.SZRTestumgebung;
+ szrService = new SZRService(url, new QName("urn:SZRServices", "SZRService"));
+ szr = szrService.getSZRTestumgebung();
+ szrURL = basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_ENDPOINT_TEST);
+
+
+ } else {
+ log.debug("Initializing SZR productive configuration.");
+ qname = SZRService.SZRProduktionsumgebung;
+ szrService = new SZRService(url, new QName("urn:SZRServices", "SZRService"));
+ szr = szrService.getSZRProduktionsumgebung();
+ szrURL = basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_ENDPOINT_PROD);
+
+ }
+
+ //create raw client;
+ dispatch = szrService.createDispatch(qname, Source.class, javax.xml.ws.Service.Mode.PAYLOAD);
+
+ if (StringUtils.isEmpty(szrURL)) {
+ log.error("No SZR service-URL found. SZR-Client initalisiation failed.");
+ throw new RuntimeException("No SZR service URL found. SZR-Client initalisiation failed.");
+
+ }
+
+ log.info("Use SZR service-URL: " + szrURL);
+ injectBindingProvider((BindingProvider) szr, CLIENT_DEFAULT);
+ injectBindingProvider((BindingProvider) dispatch, CLIENT_RAW);
+
+ log.debug("Inject HTTP client settings ... ");
+ injectHTTPClient(szr, CLIENT_DEFAULT);
+ injectHTTPClient(dispatch, CLIENT_RAW);
+
+ log.info("SZR-Client initialization successfull");
+ }
+
+ private void injectHTTPClient(Object raw, String clientType) {
+ //extract client from implementation
+ Client client = null;
+ if (raw instanceof DispatchImpl<?>)
+ client = ((DispatchImpl<?>)raw).getClient();
+ else if (raw instanceof Client)
+ client = ClientProxy.getClient(raw);
+ else
+ throw new RuntimeException("SOAP Client for SZR connection is of UNSUPPORTED type: " + raw.getClass().getName());
+
+ //set basic connection policies
+ HTTPConduit http = (HTTPConduit) client.getConduit();
+
+ //set timeout policy
+ HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
+ httpClientPolicy.setConnectionTimeout(
+ Integer.parseInt(basicConfig.getBasicConfiguration(
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_TIMEOUT_CONNECTION,
+ Constants.HTTP_CLIENT_DEFAULT_TIMEOUT_CONNECTION)) * 1000);
+ httpClientPolicy.setReceiveTimeout(
+ Integer.parseInt(basicConfig.getBasicConfiguration(
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_TIMEOUT_RESPONSE,
+ Constants.HTTP_CLIENT_DEFAULT_TIMEOUT_RESPONSE)) * 1000);
+ http.setClient(httpClientPolicy);
+
+ //inject SSL context in case of https
+ if (szrURL.toLowerCase().startsWith("https")) {
+ log.debug("Adding SSLContext to client: " + clientType +" ... ");
+ TLSClientParameters tlsParams = new TLSClientParameters();
+ tlsParams.setSSLSocketFactory(createSSLContext(clientType).getSocketFactory());
+ http.setTlsClientParameters(tlsParams );
+ log.info("SSLContext initialized for client: " + clientType);
+
+ }
+
+ }
+
+ private void injectBindingProvider(BindingProvider bindingProvider, String clientType) {
+ Map<String, Object> requestContext = bindingProvider.getRequestContext();
+ requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, szrURL);
+
+ log.trace("Adding JAX-WS request/response trace handler to client: " + clientType);
+ List<Handler> handlerList = bindingProvider.getBinding().getHandlerChain();
+ if (handlerList == null) {
+ handlerList = new ArrayList<Handler>();
+ bindingProvider.getBinding().setHandlerChain(handlerList);
+
+ }
+
+ //add logging handler to trace messages if required
+ if (basicConfig.getBasicMOAIDConfigurationBoolean(
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_DEBUG_TRACEMESSAGES,
+ false)) {
+ LoggingHandler loggingHandler = new LoggingHandler();
+ handlerList.add(loggingHandler);
+
+ }
+ }
+
+ private SSLContext createSSLContext(String clientType) {
+ try {
+ SSLContext context = SSLContext.getInstance("TLS");
+
+ //initialize key-mangager for SSL client-authentication
+ KeyManager[] keyManager = null;
+ String keyStorePath = basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_SSL_KEYSTORE_PATH);
+ String keyStorePassword = basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_SSL_KEYSTORE_PASSWORD);
+ if (StringUtils.isNotEmpty(keyStorePath)) {
+ log.trace("Find keyStore path: " + keyStorePath + " Injecting SSL client certificate ... ");
+ try {
+ KeyStore keyStore = KeyStoreUtils.loadKeyStore(
+ FileUtils.makeAbsoluteURL(keyStorePath, basicConfig.getConfigurationRootDirectory()),
+ keyStorePassword);
+
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+ kmf.init(keyStore, keyStorePassword.toCharArray());
+ keyManager = kmf.getKeyManagers();
+ log.debug("SSL client certificate injected to client: " + clientType);
+
+ } catch (KeyStoreException | IOException | UnrecoverableKeyException e) {
+ log.error("Can NOT load SSL client certificate from path: " + keyStorePath);
+ throw new RuntimeException("Can NOT load SSL client certificate from path: " + keyStorePath, e);
+
+ }
+ }
+
+
+ //initialize SSL TrustStore
+ TrustManager[] trustManager = null;
+ String trustStorePath = basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_SSL_TRUSTSTORE_PATH);
+ String trustStorePassword = basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_SSL_TRUSTSTORE_PASSWORD);
+ if (StringUtils.isNotEmpty(trustStorePath)) {
+ log.trace("Find trustStore path: " + trustStorePath + " Injecting SSL TrustStore ... ");
+ try {
+ KeyStore trustStore = KeyStoreUtils.loadKeyStore(
+ FileUtils.makeAbsoluteURL(trustStorePath, basicConfig.getConfigurationRootDirectory()),
+ trustStorePassword);
+
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
+ tmf.init(trustStore);
+ trustManager = tmf.getTrustManagers();
+ log.debug("SSL TrustStore injected to client: " + clientType);
+
+ } catch (KeyStoreException | IOException e) {
+ log.error("Can NOT open SSL TrustStore from path: " + trustStorePath);
+ throw new RuntimeException("Can NOT open SSL TrustStore from path: " + trustStorePath, e);
+
+ }
+
+ }
+
+
+ context.init(keyManager, trustManager, new SecureRandom());
+ return context;
+
+ } catch (NoSuchAlgorithmException | KeyManagementException e) {
+ log.error("SSLContext initialization FAILED.", e);
+ throw new RuntimeException("SSLContext initialization FAILED.", e);
+
+ }
+
+ }
+
+ private byte[] sourceToByteArray(Source result) throws TransformerException {
+ TransformerFactory factory = TransformerFactory.newInstance();
+ Transformer transformer = factory.newTransformer();
+ transformer.setOutputProperty("omit-xml-declaration", "yes");
+ transformer.setOutputProperty("method", "xml");
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ StreamResult streamResult = new StreamResult();
+ streamResult.setOutputStream(out);
+ transformer.transform(result, streamResult);
+ return out.toByteArray();
+ }
+
+
+
+}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/szr/SZRService.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/szr/SZRService.java
new file mode 100644
index 00000000..8e4911b9
--- /dev/null
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/szr/SZRService.java
@@ -0,0 +1,139 @@
+package at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.szr;
+
+import java.net.URL;
+
+import javax.xml.namespace.QName;
+import javax.xml.ws.Service;
+import javax.xml.ws.WebEndpoint;
+import javax.xml.ws.WebServiceClient;
+import javax.xml.ws.WebServiceFeature;
+
+import szrservices.SZR;
+
+/**
+ * This class was generated by Apache CXF 3.1.16
+ * 2018-07-10T09:36:01.466+02:00
+ * Generated source version: 3.1.16
+ *
+ */
+@WebServiceClient(name = "SZRService",
+ wsdlLocation = "./src/main/resources/szr_client/SZR-1.WSDL",
+ targetNamespace = "urn:SZRServices")
+public class SZRService extends Service {
+
+ public final static URL WSDL_LOCATION;
+
+ public final static QName SERVICE = new QName("urn:SZRServices", "SZRService");
+ public final static QName SZRProduktionsumgebung = new QName("urn:SZRServices", "SZRProduktionsumgebung");
+ public final static QName SZRTestumgebung = new QName("urn:SZRServices", "SZRTestumgebung");
+ public final static QName SZRBusinesspartnerTestumgebung = new QName("urn:SZRServices", "SZRBusinesspartnerTestumgebung");
+ static {
+ URL url = SZRService.class.getResource("./src/main/resources/szr_client/SZR-1.WSDL");
+ if (url == null) {
+ url = SZRService.class.getClassLoader().getResource("/szr_client/SZR-1.WSDL");
+ }
+ if (url == null) {
+ java.util.logging.Logger.getLogger(SZRService.class.getName())
+ .log(java.util.logging.Level.INFO,
+ "Can not initialize the default wsdl from {0}", "/szr_client/SZR-1.WSDL");
+ }
+ WSDL_LOCATION = url;
+
+ }
+
+ public SZRService(URL wsdlLocation) {
+ super(wsdlLocation, SERVICE);
+ }
+
+ public SZRService(URL wsdlLocation, QName serviceName) {
+ super(wsdlLocation, serviceName);
+ }
+
+ public SZRService() {
+ super(WSDL_LOCATION, SERVICE);
+ }
+
+ public SZRService(WebServiceFeature ... features) {
+ super(WSDL_LOCATION, SERVICE, features);
+ }
+
+ public SZRService(URL wsdlLocation, WebServiceFeature ... features) {
+ super(wsdlLocation, SERVICE, features);
+ }
+
+ public SZRService(URL wsdlLocation, QName serviceName, WebServiceFeature ... features) {
+ super(wsdlLocation, serviceName, features);
+ }
+
+
+
+
+ /**
+ *
+ * @return
+ * returns SZR
+ */
+ @WebEndpoint(name = "SZRProduktionsumgebung")
+ public SZR getSZRProduktionsumgebung() {
+ return super.getPort(SZRProduktionsumgebung, SZR.class);
+ }
+
+ /**
+ *
+ * @param features
+ * A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy. Supported features not in the <code>features</code> parameter will have their default values.
+ * @return
+ * returns SZR
+ */
+ @WebEndpoint(name = "SZRProduktionsumgebung")
+ public SZR getSZRProduktionsumgebung(WebServiceFeature... features) {
+ return super.getPort(SZRProduktionsumgebung, SZR.class, features);
+ }
+
+
+ /**
+ *
+ * @return
+ * returns SZR
+ */
+ @WebEndpoint(name = "SZRTestumgebung")
+ public SZR getSZRTestumgebung() {
+ return super.getPort(SZRTestumgebung, SZR.class);
+ }
+
+ /**
+ *
+ * @param features
+ * A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy. Supported features not in the <code>features</code> parameter will have their default values.
+ * @return
+ * returns SZR
+ */
+ @WebEndpoint(name = "SZRTestumgebung")
+ public SZR getSZRTestumgebung(WebServiceFeature... features) {
+ return super.getPort(SZRTestumgebung, SZR.class, features);
+ }
+
+
+ /**
+ *
+ * @return
+ * returns SZR
+ */
+ @WebEndpoint(name = "SZRBusinesspartnerTestumgebung")
+ public SZR getSZRBusinesspartnerTestumgebung() {
+ return super.getPort(SZRBusinesspartnerTestumgebung, SZR.class);
+ }
+
+ /**
+ *
+ * @param features
+ * A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy. Supported features not in the <code>features</code> parameter will have their default values.
+ * @return
+ * returns SZR
+ */
+ @WebEndpoint(name = "SZRBusinesspartnerTestumgebung")
+ public SZR getSZRBusinesspartnerTestumgebung(WebServiceFeature... features) {
+ return super.getPort(SZRBusinesspartnerTestumgebung, SZR.class, features);
+ }
+
+}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/CreateIdentityLinkTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/CreateIdentityLinkTask.java
index dfd945c9..b31b6a21 100644
--- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/CreateIdentityLinkTask.java
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/CreateIdentityLinkTask.java
@@ -3,41 +3,80 @@
package at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.tasks;
import java.io.InputStream;
+import java.math.BigInteger;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
+import org.springframework.util.Base64Utils;
+import org.w3._2000._09.xmldsig.KeyValueType;
+import org.w3._2000._09.xmldsig.RSAKeyValueType;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
-import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants;
-import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionStorageConstants;
-import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask;
-import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException;
-import at.gv.egovernment.moa.id.auth.modules.eidas.Constants;
-import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.eIDASAttributeException;
-import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils;
-import at.gv.egovernment.moa.id.auth.parser.IdentityLinkAssertionParser;
-import at.gv.egovernment.moa.id.commons.api.data.IIdentityLink;
-import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException;
-import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
-import at.gv.egovernment.moa.id.process.api.ExecutionContext;
-import at.gv.egovernment.moa.id.util.IdentityLinkReSigner;
-import at.gv.egovernment.moa.logging.Logger;
-import at.gv.egovernment.moa.util.DOMUtils;
-import at.gv.egovernment.moa.util.XPathUtils;
-import eu.eidas.auth.commons.attribute.ImmutableAttributeMap;
-
-/**
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
+import at.gv.e_government.reference.namespace.persondata._20020228.PersonNameType;
+import at.gv.e_government.reference.namespace.persondata._20020228.PhysicalPersonType;
+import at.gv.egiz.eaaf.core.api.data.EAAFConstants;
+import at.gv.egiz.eaaf.core.api.data.PVPAttributeDefinitions;
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.api.idp.auth.data.IIdentityLink;
+import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;
+import at.gv.egiz.eaaf.core.exceptions.EAAFException;
+import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;
+import at.gv.egiz.eaaf.core.impl.data.Pair;
+import at.gv.egiz.eaaf.core.impl.data.Trible;
+import at.gv.egiz.eaaf.core.impl.idp.auth.builder.BPKBuilder;
+import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper;
+import at.gv.egiz.eaaf.core.impl.idp.auth.data.SimpleIdentityLinkAssertionParser;
+import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask;
+import at.gv.egiz.eaaf.core.impl.utils.DOMUtils;
+import at.gv.egiz.eaaf.core.impl.utils.XPathUtils;
+import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.Constants;
+import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.exception.SZRCommunicationException;
+import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.exception.eIDASAttributeException;
+import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.szr.SZRClient;
+import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.utils.eIDASResponseUtils;
+import eu.eidas.auth.commons.attribute.AttributeDefinition;
+import eu.eidas.auth.commons.attribute.AttributeValue;
+import eu.eidas.auth.commons.light.ILightResponse;
+import eu.eidas.auth.commons.protocol.eidas.impl.PostalAddress;
+import szrservices.IdentityLinkType;
+import szrservices.PersonInfoType;
+import szrservices.TravelDocumentType;
+
+/**
* @author tlenz
- *
+ *
*/
@Component("CreateIdentityLinkTask")
public class CreateIdentityLinkTask extends AbstractAuthServletTask {
-
+ private static final Logger log = LoggerFactory.getLogger(CreateIdentityLinkTask.class);
+
+ //@Autowired private eIDASAttributeRegistry attrRegistry;
+ @Autowired private IConfiguration basicConfig;
+ @Autowired private SZRClient szrClient;
+
+
/* (non-Javadoc)
* @see at.gv.egovernment.moa.id.process.springweb.MoaIdTask#execute(at.gv.egovernment.moa.id.process.api.ExecutionContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
@@ -46,115 +85,293 @@ public class CreateIdentityLinkTask extends AbstractAuthServletTask {
HttpServletRequest request, HttpServletResponse response)
throws TaskExecutionException {
try{
- defaultTaskInitialization(request, executionContext);
-
- //get eIDAS attributes from MOA-Session
- ImmutableAttributeMap eIDASAttributes = moasession.getGenericDataFromSession(
- AuthenticationSessionStorageConstants.eIDAS_ATTRIBUTELIST,
- ImmutableAttributeMap.class);
-
- IIdentityLink identityLink = null;
-
+ AuthProcessDataWrapper authProcessData = pendingReq.getSessionData(AuthProcessDataWrapper.class);
+ ILightResponse eIDASResponse = authProcessData.getGenericDataFromSession(
+ Constants.DATA_FULL_EIDAS_RESPONSE, ILightResponse.class);
+ Map<String, Object> simpleAttrMap = converteIDASAttrToSimpleMap(eIDASResponse.getAttributes().getAttributeMap());
+
+ IIdentityLink identityLink = null;
+ String bPK = null;
+
+ //extract attributes
+ Object eIdentifierObj = simpleAttrMap.get(Constants.eIDAS_ATTR_PERSONALIDENTIFIER);
+ Object familyNameObj = simpleAttrMap.get(Constants.eIDAS_ATTR_CURRENTFAMILYNAME);
+ Object givenNameObj = simpleAttrMap.get(Constants.eIDAS_ATTR_CURRENTGIVENNAME);
+ Object dateOfBirthObj = simpleAttrMap.get(Constants.eIDAS_ATTR_DATEOFBIRTH);
+
+ //check if availabe
+ if (eIdentifierObj == null || !(eIdentifierObj instanceof String))
+ throw new eIDASAttributeException(Constants.eIDAS_ATTR_PERSONALIDENTIFIER);
+
+ if (familyNameObj == null || !(familyNameObj instanceof String))
+ throw new eIDASAttributeException(Constants.eIDAS_ATTR_CURRENTFAMILYNAME);
+
+ if (givenNameObj == null || !(givenNameObj instanceof String))
+ throw new eIDASAttributeException(Constants.eIDAS_ATTR_CURRENTGIVENNAME);
+
+ if (dateOfBirthObj == null || !(dateOfBirthObj instanceof DateTime))
+ throw new eIDASAttributeException(Constants.eIDAS_ATTR_DATEOFBIRTH);
+
//connect SZR-Gateway
- //TODO: implement SZR-Gateway communication!!!!
- if(true) {
-
+ if(basicConfig.getBasicMOAIDConfigurationBoolean(
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_DEBUG_USEDUMMY, false)) {
+ log.warn("SZR-Dummy IS ACTIVE! IdentityLink is NOT VALID!!!!");
// create fake IdL
// - fetch IdL template from resources
InputStream s = CreateIdentityLinkTask.class.getResourceAsStream("/resources/xmldata/fakeIdL_IdL_template.xml");
Element idlTemplate = DOMUtils.parseXmlValidating(s);
- identityLink = new IdentityLinkAssertionParser(idlTemplate).parseIdentityLink();
+ identityLink = new SimpleIdentityLinkAssertionParser(idlTemplate).parseIdentityLink();
// replace data
Element idlassertion = identityLink.getSamlAssertion();
// - set fake baseID;
- Node prIdentification = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_IDENT_VALUE_XPATH);
-
-
- Object eIdentifier = eIDASAttributes.getFirstValue(
- SAMLEngineUtils.getMapOfAllAvailableAttributes().get(
- Constants.eIDAS_ATTR_PERSONALIDENTIFIER));
- if (eIdentifier == null || !(eIdentifier instanceof String))
- throw new eIDASAttributeException(Constants.eIDAS_ATTR_PERSONALIDENTIFIER);
- prIdentification.getFirstChild().setNodeValue((String) eIdentifier);
+ Node prIdentification = XPathUtils.selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_IDENT_VALUE_XPATH);
+ prIdentification.getFirstChild().setNodeValue((String) eIdentifierObj);
//build personal identifier which looks like a baseID
// String fakeBaseID = new BPKBuilder().buildBPK(eIdentifier, "baseID");
// Logger.info("Map eIDAS eIdentifier:" + eIdentifier + " to fake baseID:" + fakeBaseID);
// prIdentification.getFirstChild().setNodeValue(fakeBaseID);
-
+
// - set last name
- Node prFamilyName = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_FAMILY_NAME_XPATH);
- Object familyName = eIDASAttributes.getFirstValue(
- SAMLEngineUtils.getMapOfAllAvailableAttributes().get(
- Constants.eIDAS_ATTR_CURRENTFAMILYNAME));
- if (familyName == null || !(familyName instanceof String))
- throw new eIDASAttributeException(Constants.eIDAS_ATTR_CURRENTFAMILYNAME);
- prFamilyName.getFirstChild().setNodeValue((String) familyName);
+ Node prFamilyName = XPathUtils.selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_FAMILY_NAME_XPATH);
+ prFamilyName.getFirstChild().setNodeValue((String) familyNameObj);
// - set first name
- Node prGivenName = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_GIVEN_NAME_XPATH);
- Object givenName = eIDASAttributes.getFirstValue(
- SAMLEngineUtils.getMapOfAllAvailableAttributes().get(
- Constants.eIDAS_ATTR_CURRENTGIVENNAME));
- if (givenName == null || !(givenName instanceof String))
- throw new eIDASAttributeException(Constants.eIDAS_ATTR_CURRENTGIVENNAME);
- prGivenName.getFirstChild().setNodeValue((String) givenName);
+ Node prGivenName = XPathUtils.selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_GIVEN_NAME_XPATH);
+ prGivenName.getFirstChild().setNodeValue((String) givenNameObj);
// - set date of birth
- Node prDateOfBirth = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_DATE_OF_BIRTH_XPATH);
- Object dateOfBirth = eIDASAttributes.getFirstValue(
- SAMLEngineUtils.getMapOfAllAvailableAttributes().get(
- Constants.eIDAS_ATTR_DATEOFBIRTH));
- if (dateOfBirth == null || !(dateOfBirth instanceof DateTime))
- throw new eIDASAttributeException(Constants.eIDAS_ATTR_DATEOFBIRTH);
-
- String formatedDateOfBirth = new SimpleDateFormat("yyyy-MM-dd").format(((DateTime)dateOfBirth).toDate());
+ Node prDateOfBirth = XPathUtils.selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_DATE_OF_BIRTH_XPATH);
+ String formatedDateOfBirth = new SimpleDateFormat("yyyy-MM-dd").format(((DateTime)dateOfBirthObj).toDate());
prDateOfBirth.getFirstChild().setNodeValue(formatedDateOfBirth);
- identityLink = new IdentityLinkAssertionParser(idlassertion).parseIdentityLink();
+ identityLink = new SimpleIdentityLinkAssertionParser(idlassertion).parseIdentityLink();
- //resign IDL
- IdentityLinkReSigner identitylinkresigner = IdentityLinkReSigner.getInstance();
- Element resignedilAssertion = identitylinkresigner.resignIdentityLink(identityLink.getSamlAssertion(), authConfig.getStorkFakeIdLResigningKey());
- identityLink = new IdentityLinkAssertionParser(resignedilAssertion).parseIdentityLink();
-
+ Pair<String, String> bPKCalc = new BPKBuilder().generateAreaSpecificPersonIdentifier(
+ identityLink.getIdentificationValue(),
+ identityLink.getIdentificationType(),
+ pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier());
+ bPK = bPKCalc.getFirst();
+
+
} else {
//contact SZR Gateway
- Logger.debug("Starting connecting SZR Gateway");
+ log.debug("Starting connecting SZR Gateway");
+ PersonInfoType personInfo = new PersonInfoType();
+ PersonNameType personName = new PersonNameType();
+ PhysicalPersonType naturalPerson = new PhysicalPersonType();
+ TravelDocumentType eDocument = new TravelDocumentType();
+
+ naturalPerson.setName(personName );
+ personInfo.setPerson(naturalPerson );
+ personInfo.setTravelDocument(eDocument );
+
+ //parse some eID attributes
+ String dateOfBirth = new SimpleDateFormat("yyyy-MM-dd").format(((DateTime)dateOfBirthObj).toDate());
+ Trible<String, String, String> eIdentifier =
+ eIDASResponseUtils.parseEidasPersonalIdentifier((String)eIdentifierObj);
+ String uniqueId = (String)eIdentifierObj;
+ String citizenCountry = eIdentifier.getFirst();
+
+ //person information
+ personName.setFamilyName((String)familyNameObj);
+ personName.setGivenName((String)givenNameObj);
+ naturalPerson.setDateOfBirth(dateOfBirth);
+ eDocument.setIssuingCountry(citizenCountry);
+ eDocument.setDocumentNumber(uniqueId);
+
+ //eID document information
+ eDocument.setDocumentType(basicConfig.getBasicConfiguration(
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_EDOCUMENTTYPE,
+ Constants.SZR_CONSTANTS_DEFAULT_DOCUMENT_TYPE));
+
+ //TODO: that should be removed
+ eDocument.setIssueDate(basicConfig.getBasicConfiguration(
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_ISSUING_DATE,
+ Constants.SZR_CONSTANTS_DEFAULT_ISSUING_DATE));
+ eDocument.setIssuingAuthority(basicConfig.getBasicConfiguration(
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_ISSUING_AUTHORITY,
+ Constants.SZR_CONSTANTS_DEFAULT_ISSUING_AUTHORITY));
+
+ //TODO: keys are not available in eIDAS
+ List<KeyValueType> keyValue = dummyCodeForKeys();
+
+ /*TODO:
+ * Validate if IDL signature is valid after using this method
+ * MAYBE we had to switch to 'getIdentityLinkInRawMode' method!
+ */
+ IdentityLinkType result = szrClient.getIdentityLink(
+ personInfo,
+ keyValue,
+ basicConfig.getBasicMOAIDConfigurationBoolean(
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_DEBUG_INSERTERNB,
+ true)
+ );
+
+ Element idlFromSZR = (Element)result.getAssertion();
+ identityLink = new SimpleIdentityLinkAssertionParser(idlFromSZR).parseIdentityLink();
+
+
+ //get bPK from SZR
+ bPK = szrClient.getBPK(
+ personInfo,
+ pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier(),
+ basicConfig.getBasicConfiguration(
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_VKZ,
+ "no VKZ defined"));
+
+ }
+
+ if (identityLink == null) {
+ log.error("ERnB did not return an identity link.");
+ throw new SZRCommunicationException("ernb.00", null);
+
+ }
- //TODO:!!!!!!
+ if (bPK == null) {
+ log.error("ERnB did not return a bPK for target: " + pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier());
+ throw new SZRCommunicationException("ernb.01", null);
}
- Logger.debug("SZR communication was successfull");
+ log.debug("ERnB communication was successfull");
+
+ revisionsLogger.logEvent(pendingReq, -1);
+ authProcessData.setForeigner(true);
+ authProcessData.setIdentityLink(identityLink);
+ authProcessData.setGenericDataToSession(
+ PVPAttributeDefinitions.EID_ISSUING_NATION_NAME,
+ eIDASResponseUtils.parseEidasPersonalIdentifier((String) simpleAttrMap.get(Constants.eIDAS_ATTR_PERSONALIDENTIFIER)).getFirst());
+
+ //set bPK and bPKType into auth session
+ authProcessData.setGenericDataToSession(
+ PVPAttributeDefinitions.BPK_NAME,
+ extendBPKbyPrefix(
+ bPK,
+ pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier())
+ );
+ authProcessData.setGenericDataToSession(
+ PVPAttributeDefinitions.EID_SECTOR_FOR_IDENTIFIER_NAME,
+ pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier());
- if (identityLink == null) {
- Logger.error("SZR Gateway did not return an identity link.");
- throw new MOAIDException("stork.10", null);
- }
- revisionsLogger.logEvent(pendingReq, MOAIDEventConstants.AUTHPROCESS_PEPS_IDL_RECEIVED);
- moasession.setForeigner(true);
- moasession.setIdentityLink(identityLink);
- moasession.setBkuURL("Not applicable (eIDASAuthentication)");
- //store MOA-session to database
+ //store pending-request
requestStoreage.storePendingRequest(pendingReq);
-
+
} catch (eIDASAttributeException e) {
throw new TaskExecutionException(pendingReq, "Minimum required eIDAS attributeset not found.", e);
- } catch (MOAIDException | MOADatabaseException e) {
+ } catch (EAAFException e) {
throw new TaskExecutionException(pendingReq, "IdentityLink generation for foreign person FAILED.", e);
} catch (Exception e) {
- Logger.error("IdentityLink generation for foreign person FAILED.", e);
+ log.error("IdentityLink generation for foreign person FAILED.", e);
throw new TaskExecutionException(pendingReq, "IdentityLink generation for foreign person FAILED.", e);
}
}
+ private List<KeyValueType> dummyCodeForKeys() {
+ if (basicConfig.getBasicMOAIDConfigurationBoolean(
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_KEYS_USEDUMMY,
+ false)) {
+ List<KeyValueType> keyvalueList = new ArrayList<KeyValueType>();
+ try {
+ PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(Constants.SZR_CONSTANTS_DEFAULT_PUBL_KEY);
+ KeyFactory kf = KeyFactory.getInstance("RSA");
+
+ PublicKey pb = kf.generatePublic(spec);
+
+ RSAPublicKey rsapb = (RSAPublicKey)pb;
+ BigInteger modulus = rsapb.getModulus();
+ BigInteger exponent = rsapb.getPublicExponent();
+
+ // set key values
+ RSAKeyValueType rsa = new RSAKeyValueType();
+ rsa.setExponent(new String(Base64Utils.encode(exponent.toByteArray())));
+ rsa.setModulus(new String(Base64Utils.encode(modulus.toByteArray())));
+
+ KeyValueType key = new KeyValueType();
+ key.setRSAKeyValue(rsa);
+
+ keyvalueList.add(key);
+
+ return keyvalueList;
+ } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
+ log.error("TestCode has an internal ERROR", e);
+
+ }
+
+ }
+
+ return null;
+
+ }
+
+ private String extendBPKbyPrefix(String bpk, String type) {
+ String bPKType = null;
+
+ if (type.startsWith(EAAFConstants.URN_PREFIX_WBPK))
+ bPKType = type.substring((EAAFConstants.URN_PREFIX_WBPK).length());
+
+ else if (type.startsWith(EAAFConstants.URN_PREFIX_CDID))
+ bPKType = type.substring((EAAFConstants.URN_PREFIX_CDID).length());
+
+ else if (type.startsWith(EAAFConstants.URN_PREFIX_EIDAS))
+ bPKType = type.substring((EAAFConstants.URN_PREFIX_EIDAS).length());
+
+
+ if (bPKType != null ) {
+ log.trace("Authenticate user with bPK/wbPK " + bpk + " and Type=" + bPKType);
+ return bPKType + ":" + bpk;
+
+ } else {
+ log.warn("Service Provider Target with: " + type + " is NOT supported. Set bPK as it is ...");
+ return bpk;
+
+ }
+
+ }
+
+ //TODO: update for complexe attributes
+ private Map<String, Object> converteIDASAttrToSimpleMap(
+ ImmutableMap<AttributeDefinition<?>, ImmutableSet<? extends AttributeValue<?>>> attributeMap) {
+ Map<String, Object> result = new HashMap<String, Object>();
+
+ for (AttributeDefinition<?> el : attributeMap.keySet()) {
+
+ final Class parameterizedType = el.getParameterizedType();
+ if ((DateTime.class).equals(parameterizedType)) {
+ DateTime attribute = eIDASResponseUtils.translateDateAttribute(el, attributeMap.get(el).asList());
+ if (attribute != null)
+ result.put(el.getFriendlyName(), attribute);
+ else
+ log.info("Ignore empty 'DateTime' attribute");
+
+ } else if ((PostalAddress.class).equals(parameterizedType)) {
+ PostalAddress addressAttribute = eIDASResponseUtils.translateAddressAttribute(el, attributeMap.get(el).asList());
+ if (addressAttribute != null)
+ result.put(el.getFriendlyName(), addressAttribute);
+ else
+ log.info("Ignore empty 'PostalAddress' attribute");
+
+ } else {
+ List<String> natPersonIdObj = eIDASResponseUtils.translateStringListAttribute(el, attributeMap.get(el).asList());
+ String stringAttr = natPersonIdObj.get(0);
+ if (StringUtils.isNotEmpty(stringAttr))
+ result.put(el.getFriendlyName(), stringAttr);
+ else
+ log.info("Ignore empty 'String' attribute");
+
+ }
+ }
+
+ return result;
+ }
+
+
}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/GenerateAuthnRequestTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/GenerateAuthnRequestTask.java
index 358b681e..da554249 100644
--- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/GenerateAuthnRequestTask.java
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/GenerateAuthnRequestTask.java
@@ -2,66 +2,64 @@
*******************************************************************************/
package at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.tasks;
-import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
+import java.util.Map;
import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.apache.commons.lang3.BooleanUtils;
-import org.apache.velocity.Template;
-import org.apache.velocity.VelocityContext;
-import org.apache.velocity.app.VelocityEngine;
-import org.opensaml.common.xml.SAMLConstants;
-import org.opensaml.saml2.metadata.EntityDescriptor;
-import org.opensaml.saml2.metadata.SingleSignOnService;
-import org.opensaml.saml2.metadata.provider.MetadataProviderException;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
-import org.springframework.util.StringUtils;
+import org.springframework.web.util.UriComponentsBuilder;
-import com.google.common.net.MediaType;
+import com.google.common.collect.ImmutableSortedSet;
+import at.gv.egiz.eaaf.core.api.data.EAAFConstants;
+import at.gv.egiz.eaaf.core.api.gui.IGUIFormBuilder;
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration;
+import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;
+import at.gv.egiz.eaaf.core.api.storage.ITransactionStorage;
+import at.gv.egiz.eaaf.core.exceptions.EAAFConfigurationException;
+import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;
+import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask;
+import at.gv.egiz.eidas.specific.connector.gui.StaticGuiBuilderConfiguration;
import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.Constants;
-import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants;
-import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
-import at.gv.egovernment.moa.id.auth.frontend.velocity.VelocityProvider;
-import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask;
-import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException;
-import at.gv.egovernment.moa.id.commons.MOAIDAuthConstants;
-import at.gv.egovernment.moa.id.commons.api.IOAAuthParameters;
-import at.gv.egovernment.moa.id.commons.api.IRequest;
-import at.gv.egovernment.moa.id.commons.api.data.CPEPS;
-import at.gv.egovernment.moa.id.commons.api.data.StorkAttribute;
-import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException;
-import at.gv.egovernment.moa.id.process.api.ExecutionContext;
-import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils;
-import at.gv.egovernment.moa.logging.Logger;
-import at.gv.egovernment.moa.util.MiscUtil;
-import eu.eidas.auth.commons.EidasStringUtil;
+import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.exception.eIDASAuthenticationException;
+import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.service.eIDASAttributeRegistry;
+import eu.eidas.auth.commons.EidasParameterKeys;
import eu.eidas.auth.commons.attribute.AttributeDefinition;
-import eu.eidas.auth.commons.attribute.AttributeDefinition.Builder;
-import eu.eidas.auth.commons.light.impl.LightRequest;
import eu.eidas.auth.commons.attribute.ImmutableAttributeMap;
-import eu.eidas.auth.commons.protocol.IRequestMessage;
-import eu.eidas.auth.commons.protocol.eidas.LevelOfAssurance;
-import eu.eidas.auth.commons.protocol.eidas.LevelOfAssuranceComparison;
+import eu.eidas.auth.commons.light.ILightRequest;
+import eu.eidas.auth.commons.light.impl.LightRequest;
import eu.eidas.auth.commons.protocol.eidas.SpType;
-import eu.eidas.auth.commons.protocol.eidas.impl.EidasAuthenticationRequest;
+import eu.eidas.auth.commons.tx.BinaryLightToken;
+import eu.eidas.specificcommunication.BinaryLightTokenHelper;
+import eu.eidas.specificcommunication.SpecificCommunicationDefinitionBeanNames;
+import eu.eidas.specificcommunication.exception.SpecificCommunicationException;
+import eu.eidas.specificcommunication.protocol.impl.SpecificConnectorCommunicationServiceImpl;
/**
* @author tlenz
*
- */
-@Component("GenerateAuthnRequestTask")
+ */
+@Component("ConnecteIDASNodeTask")
public class GenerateAuthnRequestTask extends AbstractAuthServletTask {
-
- /* (non-Javadoc)
- * @see at.gv.egovernment.moa.id.process.springweb.MoaIdTask#execute(at.gv.egovernment.moa.id.process.api.ExecutionContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
- */
+ private static final Logger log = LoggerFactory.getLogger(GenerateAuthnRequestTask.class);
+
+ @Autowired IConfiguration basicConfig;
+ @Autowired eIDASAttributeRegistry attrRegistry;
+ @Autowired ApplicationContext context;
+ @Autowired ITransactionStorage transactionStore;
+ @Autowired IGUIFormBuilder guiBuilder;
+
@Override
public void execute(ExecutionContext executionContext,
HttpServletRequest request, HttpServletResponse response)
@@ -69,245 +67,196 @@ public class GenerateAuthnRequestTask extends AbstractAuthServletTask {
try{
//get service-provider configuration
- IOAAuthParameters oaConfig = pendingReq.getOnlineApplicationConfiguration();
+ ISPConfiguration spConfig = pendingReq.getServiceProviderConfiguration();
// get target and validate citizen countryCode
- String citizenCountryCode = (String) executionContext.get(MOAIDAuthConstants.PARAM_CCC);
+ String citizenCountryCode = (String) executionContext.get(Constants.EXECUTIONCONTEXT_SELECTED_COUNTRY);
if (StringUtils.isEmpty(citizenCountryCode)) {
// illegal state; task should not have been executed without a selected country
- throw new AuthenticationException("eIDAS.03", new Object[] { "" });
+ throw new eIDASAuthenticationException("eidas.03", new Object[] { "" });
}
- CPEPS cpeps = authConfig.getStorkConfig().getCPEPSWithFullName(citizenCountryCode);
- if(null == cpeps) {
- Logger.error("PEPS unknown for country: " + citizenCountryCode);
- throw new AuthenticationException("eIDAS.04", new Object[] {citizenCountryCode});
- }
- Logger.debug("Found eIDaS Node/C-PEPS configuration for citizen of country: " + citizenCountryCode);
-
- //TODO: load authnReq End-Point URL from configuration
- SingleSignOnService authnReqEndpoint = null;
+ //TODO: maybe add countryCode validation before request ref. impl. eIDAS node
+ log.debug("Request eIDAS auth. for citizen of country: " + citizenCountryCode);
-
+
//TODO: switch to entityID and set new status codes
-// revisionsLogger.logEvent(oaConfig, pendingReq,
-// MOAIDEventConstants.AUTHPROCESS_PEPS_SELECTED,
-// metadataUrl);
+ //revisionsLogger.logEvent(oaConfig, pendingReq, MOAIDEventConstants.AUTHPROCESS_PEPS_SELECTED, metadataUrl);
- // assemble requested attributes
- Collection<StorkAttribute> attributesFromConfig = oaConfig.getRequestedSTORKAttributes();
-
- // - prepare attribute list
-
- // - fill container
- List<AttributeDefinition<?>> reqAttrList = new ArrayList<AttributeDefinition<?>>();
- //TODO: update requested attribute builder
-// for (StorkAttribute current : attributesFromConfig) {
-// AttributeDefinition<?> newAttribute = SAMLEngineUtils.getMapOfAllAvailableAttributes().get(current.getName());
-//
-// if (newAttribute == null) {
-// Logger.warn("eIDAS attribute with friendlyName:" + current.getName() + " is not supported.");
-//
-// } else {
-// boolean globallyMandatory = false;
-// for (StorkAttribute currentGlobalAttribute : authConfig.getStorkConfig().getStorkAttributes())
-// if (current.getName().equals(currentGlobalAttribute.getName())) {
-// globallyMandatory = BooleanUtils.isTrue(currentGlobalAttribute.getMandatory());
-// break;
-// }
-//
-// Builder<?> attrBuilder = AttributeDefinition.builder(newAttribute).required(current.getMandatory() || globallyMandatory);
-// reqAttrList.add(attrBuilder.build());
-//
-// }
-// }
-
- //request
-// if (reqAttrList.isEmpty()) {
-// Logger.info("No attributes requested by OA:" + pendingReq.getOnlineApplicationConfiguration().getPublicURLPrefix()
-// + " --> Request attr:" + Constants.eIDAS_ATTR_PERSONALIDENTIFIER + " by default");
-// AttributeDefinition<?> newAttribute = SAMLEngineUtils.getMapOfAllAvailableAttributes().get(Constants.eIDAS_ATTR_PERSONALIDENTIFIER);
-// Builder<?> attrBuilder = AttributeDefinition.builder(newAttribute).required(true);
-// reqAttrList.add(attrBuilder.build());
-//
-// }
-
- //build requested attribute set
- ImmutableAttributeMap reqAttrMap = new ImmutableAttributeMap.Builder().putAll(reqAttrList).build();
//build eIDAS AuthnRequest
- LightRequest.Builder authnRequestBuilder = LightRequest.builder();
-
+ LightRequest.Builder authnRequestBuilder = LightRequest.builder();
authnRequestBuilder.id(UUID.randomUUID().toString());
- authnRequestBuilder.providerName(pendingReq.getAuthURL());
- String issur = pendingReq.getAuthURL() + Constants.eIDAS_HTTP_ENDPOINT_METADATA;
- authnRequestBuilder.issuer(issur);
- //TODO:
- //authnRequestBuilder.destination(authnReqEndpoint.getLocation());
-
- authnRequestBuilder.nameIdFormat(Constants.eIDAS_REQ_NAMEID_FORMAT);
+ String issur = basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_ENTITYID);
+ if (StringUtils.isEmpty(issur)) {
+ log.error("Found NO 'eIDAS node issuer' in configuration. Authentication NOT possible!");
+ throw new EAAFConfigurationException("Found NO 'eIDAS node issuer' in configuration. Authentication NOT possible!");
+
+ }
+ authnRequestBuilder.issuer(issur);
- //set minimum required eIDAS LoA from OA config
- String LoA = oaConfig.getQaaLevel();
- //TODO:
-// if (MiscUtil.isNotEmpty(LoA))
-// authnRequestBuilder.levelOfAssurance(LevelOfAssurance.fromString(oaConfig.getQaaLevel()));
-// else
- authnRequestBuilder.levelOfAssurance(LevelOfAssurance.HIGH.getValue());
- //TODO: check if required
- //authnRequestBuilder.levelOfAssuranceComparison(LevelOfAssuranceComparison.MINIMUM);
+ //TODO: set matching mode if eIDAS ref. impl. support this method
+
+ //TODO: update if eIDAS ref. impl. supports exact matching for non-notified LoA schemes
+ String loa = EAAFConstants.EIDAS_LOA_HIGH;
+ if (spConfig.getRequiredLoA() != null) {
+ if (spConfig.getRequiredLoA().isEmpty())
+ log.info("No eIDAS LoA requested. Use LoA HIGH as default");
+
+ else {
+ if (spConfig.getRequiredLoA().size() > 1 )
+ log.info("Currently only ONE requested LoA is supported for service provider. Use first one ... ");
+
+ loa = spConfig.getRequiredLoA().get(0);
+
+ }
+ }
+
+ log.debug("Request eIdAS node with LoA: " + loa);
+ authnRequestBuilder.levelOfAssurance(loa);
- //set correct SPType for this online application
- if (oaConfig.hasBaseIdTransferRestriction())
- authnRequestBuilder.spType(SpType.PRIVATE.getValue());
- else
+ //set correct SPType for requested target sector
+ String publicSectorTargetSelector = basicConfig.getBasicConfiguration(
+ Constants.CONIG_PROPS_EIDAS_NODE_PUBLICSECTOR_TARGETS,
+ Constants.POLICY_DEFAULT_ALLOWED_TARGETS);
+ Pattern p = Pattern.compile(publicSectorTargetSelector);
+ Matcher m = p.matcher(spConfig.getAreaSpecificTargetIdentifier());
+ if (m.matches()) {
+ log.debug("Map " + spConfig.getAreaSpecificTargetIdentifier() + " to 'PublicSector'");
authnRequestBuilder.spType(SpType.PUBLIC.getValue());
+
+ //TODO: only for eIDAS ref. node 2.0 because it need 'Providername' for any SPType
+ String providerName = pendingReq.getRawData(Constants.DATA_PROVIDERNAME, String.class);
+ if (StringUtils.isNotEmpty(providerName)
+ && basicConfig.getBasicMOAIDConfigurationBoolean(
+ Constants.CONIG_PROPS_EIDAS_NODE_WORKAROUND_ADD_ALWAYS_PROVIDERNAME,
+ false)
+ )
+ authnRequestBuilder.providerName(providerName);
+
+ } else {
+ log.debug("Map " + spConfig.getAreaSpecificTargetIdentifier() + " to 'PrivateSector'");
+ authnRequestBuilder.spType(SpType.PRIVATE.getValue());
+ //TODO: switch to RequesterId in further version
+ //set provider name for private sector applications
+ String providerName = pendingReq.getRawData(Constants.DATA_PROVIDERNAME, String.class);
+ if (StringUtils.isNotEmpty(providerName))
+ authnRequestBuilder.providerName(providerName);
- //TODO
- //set service provider (eIDAS node) countryCode
-// authnRequestBuilder.serviceProviderCountryCode(
-// authConfig.getBasicMOAIDConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_COUNTRYCODE, "AT"));
-
- //set citizen country code for foreign uses
- authnRequestBuilder.citizenCountryCode(cpeps.getCountryCode());
-
- //add requested attributes
- authnRequestBuilder.requestedAttributes(reqAttrMap);
-
+ }
- LightRequest lightAuthnReq = authnRequestBuilder.build();
+ //set nameIDFormat
+ authnRequestBuilder.nameIdFormat(Constants.eIDAS_REQ_NAMEID_FORMAT);
+ //set citizen country code for foreign uses
+ authnRequestBuilder.citizenCountryCode(citizenCountryCode);
+ //set relay state
+ authnRequestBuilder.relayState(pendingReq.getPendingRequestId());
- //IRequestMessage authnRequest = engine.generateRequestMessage(authnRequestBuilder.build(), issur);
+ //build and add requested attribute set
+ ImmutableAttributeMap reqAttrMap = translateToEidasAttributes(attrRegistry.getAttributeSetFromConfiguration());
+ authnRequestBuilder.requestedAttributes(reqAttrMap);
- //encode AuthnRequest
-// byte[] token = authnRequest.getMessageBytes();
-// String SAMLRequest = EidasStringUtil.encodeToBase64(token);
+ //build request
+ LightRequest lightAuthnReq = authnRequestBuilder.build();
+ //put request into cache
+ BinaryLightToken token = putRequestInCommunicationCache(lightAuthnReq);
+ final String tokenBase64 = BinaryLightTokenHelper.encodeBinaryLightTokenBase64(token);
+
+ //Workaround, because eIDAS node ref. impl. does not return relayState
+ if (basicConfig.getBasicMOAIDConfigurationBoolean(
+ Constants.CONIG_PROPS_EIDAS_NODE_WORKAROUND_USEREQUESTIDASTRANSACTIONIDENTIFIER,
+ false)) {
+ log.trace("Put lightRequestId into transactionstore as session-handling backup");
+ transactionStore.put(lightAuthnReq.getId(), pendingReq.getPendingRequestId(), -1);
+
+ }
-// if (SAMLConstants.SAML2_POST_BINDING_URI.equals(authnReqEndpoint.getBinding()))
-// buildPostBindingRequest(pendingReq, authnReqEndpoint, SAMLRequest, authnRequest, response);
-//
-// //TODO: redirect Binding is not completely implemented
-// //else if (SAMLConstants.SAML2_REDIRECT_BINDING_URI.equals(authnReqEndpoint.getBinding()))
-// //buildRedirecttBindingRequest(pendingReq, authnReqEndpoint, token, authnRequest, response);
-//
-// else {
-// Logger.error("eIDAS-node use an unsupported binding ("
-// + authnReqEndpoint.getBinding() + "). Request eIDAS node not possible.");
-// throw new MOAIDException("eIDAS.02", new Object[]{"eIDAS-node use an unsupported binding"});
-//
-// }
+ if (basicConfig.getBasicConfiguration(
+ Constants.CONIG_PROPS_EIDAS_NODE_FORWARD_METHOD,
+ Constants.FORWARD_METHOD_GET
+ ).equals(Constants.FORWARD_METHOD_GET)) {
+
+ log.debug("Use http-redirect for eIDAS node forwarding ... ");
+ //send redirect
+ UriComponentsBuilder redirectUrl = UriComponentsBuilder.fromHttpUrl(basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_FORWARD_URL));
+ redirectUrl.queryParam(EidasParameterKeys.TOKEN.toString(), tokenBase64);
+ response.sendRedirect(redirectUrl.build().encode().toString());
+
+ } else {
+ log.debug("Use http-post for eIDAS node forwarding ... ");
+ StaticGuiBuilderConfiguration config = new StaticGuiBuilderConfiguration(
+ basicConfig,
+ pendingReq,
+ Constants.TEMPLATE_POST_FORWARD_NAME,
+ null);
+
+ config.putCustomParameter(Constants.TEMPLATE_POST_FORWARD_ENDPOINT,
+ basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_FORWARD_URL));
+ config.putCustomParameter(Constants.TEMPLATE_POST_FORWARD_TOKEN_NAME,
+ EidasParameterKeys.TOKEN.toString());
+ config.putCustomParameter(Constants.TEMPLATE_POST_FORWARD_TOKEN_VALUE,
+ tokenBase64);
+
+ guiBuilder.build(response, config, "BKU-Selection form");
+
+ }
-
-
-// }catch (EIDASSAMLEngineException e){
-// throw new TaskExecutionException(pendingReq, "eIDAS AuthnRequest generation FAILED.",
-// new EIDASEngineException("eIDAS.00", new Object[]{e.getMessage()}, e));
- } catch (MOAIDException e) {
+
+ } catch (eIDASAuthenticationException e) {
throw new TaskExecutionException(pendingReq, "eIDAS AuthnRequest generation FAILED.", e);
} catch (Exception e) {
- Logger.error("eIDAS AuthnRequest generation FAILED.", e);
+ log.warn("eIDAS AuthnRequest generation FAILED.", e);
throw new TaskExecutionException(pendingReq, e.getMessage(), e);
}
+
}
+
+ private ImmutableAttributeMap translateToEidasAttributes(final Map<String, Boolean> requiredAttributes) {
+ ImmutableAttributeMap.Builder builder = ImmutableAttributeMap.builder();
+ for (Map.Entry<String,Boolean> attribute : requiredAttributes.entrySet()) {
+ final String name = attribute.getKey();
+ final ImmutableSortedSet<AttributeDefinition<?>> byFriendlyName = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(name);
+ if (!byFriendlyName.isEmpty()) {
+ final AttributeDefinition<?> attributeDefinition = byFriendlyName.first();
+ builder.put(AttributeDefinition.builder(attributeDefinition).required(attribute.getValue()).build());
+
+ } else
+ log.warn("Can NOT request UNKNOWN attribute: " + attribute.getKey() + " Ignore it!");
+
+ }
+
+ return builder.build();
+
+ }
- /**
- * Encode the eIDAS request with POST binding
- *
- * @param pendingReq
- * @param authnReqEndpoint
- * @param SAMLRequest
- * @param authnRequest
- * @param response
- * @throws MOAIDException
- */
- private void buildPostBindingRequest(IRequest pendingReq, SingleSignOnService authnReqEndpoint,
- String SAMLRequest, IRequestMessage authnRequest, HttpServletResponse response)
- throws MOAIDException {
- //send
+ private BinaryLightToken putRequestInCommunicationCache(ILightRequest iLightRequest) throws ServletException {
+ final BinaryLightToken binaryLightToken;
try {
- VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine();
- Template template = velocityEngine.getTemplate("/resources/templates/eidas_postbinding_template.vm");
- VelocityContext context = new VelocityContext();
-
- String actionType = "SAMLRequest";
- context.put(actionType, SAMLRequest);
- context.put("RelayState", pendingReq.getRequestID());
- context.put("action", authnReqEndpoint.getLocation());
-
- Logger.debug("Using SingleSignOnService url as action: " + authnReqEndpoint.getLocation());
- Logger.debug("Encoded " + actionType + " original: " + SAMLRequest);
+ final SpecificConnectorCommunicationServiceImpl springManagedSpecificConnectorCommunicationService =
+ (SpecificConnectorCommunicationServiceImpl) context.getBean(SpecificCommunicationDefinitionBeanNames.SPECIFIC_CONNECTOR_COMMUNICATION_SERVICE.toString());
- Logger.trace("Starting template merge");
- StringWriter writer = new StringWriter();
-
- Logger.trace("Doing template merge");
- template.merge(context, writer);
-
- Logger.trace("Template merge done");
- Logger.trace("Sending html content: " + writer.getBuffer().toString());
+ binaryLightToken = springManagedSpecificConnectorCommunicationService.putRequest(iLightRequest);
-
- byte[] content = writer.getBuffer().toString().getBytes("UTF-8");
- response.setContentType(MediaType.HTML_UTF_8.toString());
- response.setContentLength(content.length);
- response.getOutputStream().write(content);
-
- revisionsLogger.logEvent(pendingReq.getOnlineApplicationConfiguration(), pendingReq,
- MOAIDEventConstants.AUTHPROCESS_PEPS_REQUESTED,
- authnRequest.getRequest().getId());
-
- } catch (Exception e) {
- Logger.error("Velocity general error: " + e.getMessage());
- throw new MOAIDException("eIDAS.02", new Object[]{e.getMessage()}, e);
+ } catch (SpecificCommunicationException e) {
+ log.error("Unable to process specific request");
+ throw new ServletException(e);
}
-
- }
-
- /**
- * Select a SingleSignOnService endPoint from eIDAS node metadata.
- * This endPoint receives the Authn. request
- *
- * @param idpEntity
- * @return
- */
- private SingleSignOnService selectSingleSignOnServiceFromMetadata(EntityDescriptor idpEntity) {
- //select SingleSignOn Service endpoint from IDP metadata
- SingleSignOnService endpoint = null;
- if (idpEntity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS) == null) {
- return null;
-
- }
-
- for (SingleSignOnService sss :
- idpEntity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS).getSingleSignOnServices()) {
-
- // use POST binding as default if it exists
- if (sss.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI))
- endpoint = sss;
-
- //TODO: redirect Binding is not completely implemented
- // use Redirect binding as backup
-// else if ( sss.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)
-// && endpoint == null )
-// endpoint = sss;
-
- }
-
- return endpoint;
- }
-
+
+ return binaryLightToken;
+ }
+
}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/ReceiveAuthnResponseTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/ReceiveAuthnResponseTask.java
index 055c402f..f0b37ede 100644
--- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/ReceiveAuthnResponseTask.java
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/tasks/ReceiveAuthnResponseTask.java
@@ -5,84 +5,78 @@ package at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.tasks;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.opensaml.saml2.core.StatusCode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
-import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants;
-import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionStorageConstants;
-import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask;
-import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException;
-import at.gv.egovernment.moa.id.auth.modules.eidas.Constants;
-import at.gv.egovernment.moa.id.auth.modules.eidas.engine.MOAeIDASChainingMetadataProvider;
-import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASEngineException;
-import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASResponseNotSuccessException;
-import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils;
-import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException;
-import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
-import at.gv.egovernment.moa.id.process.api.ExecutionContext;
-import at.gv.egovernment.moa.id.protocols.eidas.validator.eIDASResponseValidator;
-import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants;
-import at.gv.egovernment.moa.logging.Logger;
-import at.gv.egovernment.moa.util.MiscUtil;
-import eu.eidas.auth.commons.EidasStringUtil;
-import eu.eidas.auth.commons.protocol.IAuthenticationResponse;
-import eu.eidas.auth.engine.ProtocolEngineI;
-import eu.eidas.engine.exceptions.EIDASSAMLEngineException;
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;
+import at.gv.egiz.eaaf.core.exceptions.EAAFException;
+import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;
+import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper;
+import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask;
+import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.Constants;
+import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.exception.eIDASAuthenticationException;
+import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.service.eIDASAttributeRegistry;
+import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.validator.eIDASResponseValidator;
+import eu.eidas.auth.commons.light.ILightResponse;
-@Component("ReceiveAuthnResponseTask")
+@Component("ReceiveResponseFromeIDASNodeTask")
public class ReceiveAuthnResponseTask extends AbstractAuthServletTask {
-
- @Autowired(required=true) MOAeIDASChainingMetadataProvider eIDASMetadataProvider;
+ private static final Logger log = LoggerFactory.getLogger(ReceiveAuthnResponseTask.class);
- @Override
+ @Autowired private ApplicationContext context;
+ @Autowired private IConfiguration basicConfig;
+ @Autowired private eIDASAttributeRegistry attrRegistry;
+
+ @Override
public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) throws TaskExecutionException {
-
- try{
- //get SAML Response
- String base64SamlToken = request.getParameter("SAMLResponse");
- if (MiscUtil.isEmpty(base64SamlToken)) {
- Logger.warn("No eIDAS SAMLReponse found in http request.");
- throw new MOAIDException("HTTP request includes no eIDAS SAML-Response element.", null);
+ try{
+
+// //get token from Request
+// final String tokenBase64 = request.getParameter(EidasParameterKeys.TOKEN.toString());
+// if (StringUtils.isEmpty(tokenBase64)) {
+// log.warn("NO eIDAS message token found.");
+// throw new eIDASAuthenticationException("TODO", null,
+// "NO eIDAS message token found.");
+//
+// }
+//
+// //get eIDAS response from cache
+// final SpecificConnectorCommunicationServiceImpl specificConnectorCommunicationService =
+// (SpecificConnectorCommunicationServiceImpl) context.getBean(SpecificCommunicationDefinitionBeanNames.SPECIFIC_CONNECTOR_COMMUNICATION_SERVICE.toString());
+// ILightResponse eIDASResponse = specificConnectorCommunicationService.getAndRemoveResponse(tokenBase64,
+// ImmutableSortedSet.copyOf(attrRegistry.getCoreAttributeRegistry().getAttributes()));
+
+ ILightResponse eIDASResponse = (ILightResponse) request.getAttribute(Constants.DATA_FULL_EIDAS_RESPONSE);
+ if (eIDASResponse == null) {
+ log.warn("NO eIDAS response-message found.");
+ throw new eIDASAuthenticationException("eidas.01", null);
}
- //get MOASession
- defaultTaskInitialization(request, executionContext);
+ log.debug("Receive eIDAS response with RespId:" + eIDASResponse.getId() + " for ReqId:" + eIDASResponse.getInResponseToId());
- //decode SAML response
- byte[] decSamlToken = EidasStringUtil.decodeBytesFromBase64(base64SamlToken);
-
- //get eIDAS SAML-engine
- ProtocolEngineI engine = SAMLEngineUtils.createSAMLEngine(eIDASMetadataProvider);
-
- //validate SAML token
- IAuthenticationResponse samlResp = engine.unmarshallResponseAndValidate(decSamlToken,
- request.getRemoteHost(),
- Constants.CONFIG_PROPS_SKEWTIME_BEFORE,
- Constants.CONFIG_PROPS_SKEWTIME_AFTER,
- pendingReq.getAuthURL() + Constants.eIDAS_HTTP_ENDPOINT_METADATA);
-
- if (samlResp.isEncrypted()) {
- Logger.info("Received encrypted eIDAS SAML-Response.");
- //TODO: check if additional decryption operation is required
-
- }
-
-
- //check response StatusCode
- if (!samlResp.getStatusCode().equals(StatusCode.SUCCESS_URI)) {
- Logger.info("Receice eIDAS Response with StatusCode:" + samlResp.getStatusCode()
- + " Subcode:" + samlResp.getSubStatusCode() + " Msg:" + samlResp.getStatusMessage());
- throw new EIDASResponseNotSuccessException("eIDAS.11", new Object[]{samlResp.getStatusMessage()});
+
+ //check response StatusCode
+ if (!eIDASResponse.getStatus().getStatusCode().equals(Constants.SUCCESS_URI)) {
+ log.info("Receice eIDAS Response with StatusCode:" + eIDASResponse.getStatus().getStatusCode()
+ + " Subcode:" + eIDASResponse.getStatus().getSubStatusCode() + " Msg:" + eIDASResponse.getStatus().getStatusMessage());
+ throw new eIDASAuthenticationException("eidas.02", new Object[]{eIDASResponse.getStatus().getStatusCode(), eIDASResponse.getStatus().getStatusMessage()});
}
+ // extract all Attributes from response
+
+
+
// **********************************************************
- // ******* MOA-ID specific response validation **********
+ // ******* MS-specificresponse validation **********
// **********************************************************
- String spCountry = authConfig.getBasicMOAIDConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_COUNTRYCODE, "AT");
- eIDASResponseValidator.validateResponse(pendingReq, samlResp, spCountry);
+ String spCountry = basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_COUNTRYCODE, "AT");
+ eIDASResponseValidator.validateResponse(pendingReq, eIDASResponse, spCountry, attrRegistry);
// **********************************************************
@@ -90,51 +84,24 @@ public class ReceiveAuthnResponseTask extends AbstractAuthServletTask {
// **********************************************************
//update MOA-Session data with received information
- Logger.debug("Store eIDAS response information into MOA-session.");
-
- moasession.setQAALevel(samlResp.getLevelOfAssurance());
-
- moasession.setGenericDataToSession(
- AuthenticationSessionStorageConstants.eIDAS_ATTRIBUTELIST,
- samlResp.getAttributes());
-
- moasession.setGenericDataToSession(
- AuthenticationSessionStorageConstants.eIDAS_RESPONSE,
- decSamlToken);
+ log.debug("Store eIDAS response information into pending-request.");
+ AuthProcessDataWrapper authProcessData = pendingReq.getSessionData(AuthProcessDataWrapper.class);
+ authProcessData.setQAALevel(eIDASResponse.getLevelOfAssurance());
+ authProcessData.setGenericDataToSession(Constants.DATA_FULL_EIDAS_RESPONSE, eIDASResponse);
- //set issuer nation as PVP attribute into MOASession
- moasession.setGenericDataToSession(PVPConstants.EID_ISSUING_NATION_NAME, samlResp.getCountry());
-
//store MOA-session to database
requestStoreage.storePendingRequest(pendingReq);
- revisionsLogger.logEvent(pendingReq.getOnlineApplicationConfiguration(), pendingReq,
- MOAIDEventConstants.AUTHPROCESS_PEPS_RECEIVED,
- samlResp.getId());
+ revisionsLogger.logEvent(pendingReq, -1, eIDASResponse.getId());
- } catch (MOAIDException e) {
+ } catch (EAAFException e) {
throw new TaskExecutionException(pendingReq, "eIDAS Response processing FAILED.", e);
-
- }catch (EIDASSAMLEngineException e) {
- Logger.warn("eIDAS Response validation FAILED.", e);
- Logger.debug("eIDAS response was: " + request.getParameter("SAMLResponse"));
- revisionsLogger.logEvent(pendingReq.getOnlineApplicationConfiguration(), pendingReq,
- MOAIDEventConstants.AUTHPROCESS_PEPS_RECEIVED_ERROR);
- throw new TaskExecutionException(pendingReq, "eIDAS Response processing FAILED.",
- new EIDASEngineException("eIDAS.09", new Object[]{e.getMessage()}, e));
- } catch (MOADatabaseException e) {
- revisionsLogger.logEvent(pendingReq.getOnlineApplicationConfiguration(), pendingReq,
- MOAIDEventConstants.AUTHPROCESS_PEPS_RECEIVED_ERROR);
- throw new TaskExecutionException(pendingReq, "eIDAS Response processing FAILED.",
- new MOAIDException("init.04", new Object[]{""}, e));
-
} catch (Exception e) {
- Logger.warn("eIDAS Response processing FAILED.", e);
- revisionsLogger.logEvent(pendingReq.getOnlineApplicationConfiguration(), pendingReq,
- MOAIDEventConstants.AUTHPROCESS_PEPS_RECEIVED_ERROR);
+ log.warn("eIDAS Response processing FAILED.", e);
+ revisionsLogger.logEvent(pendingReq, -1);
throw new TaskExecutionException(pendingReq, e.getMessage(),
- new MOAIDException("eIDAS.10", new Object[]{e.getMessage()}, e));
+ new eIDASAuthenticationException("eidas.05", new Object[]{e.getMessage()}, e));
}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/utils/LoggingHandler.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/utils/LoggingHandler.java
new file mode 100644
index 00000000..c58d369b
--- /dev/null
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/utils/LoggingHandler.java
@@ -0,0 +1,52 @@
+package at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.utils;
+
+import java.io.ByteArrayOutputStream;
+import java.util.Set;
+
+import javax.xml.namespace.QName;
+import javax.xml.soap.SOAPMessage;
+import javax.xml.ws.handler.MessageContext;
+import javax.xml.ws.handler.soap.SOAPHandler;
+import javax.xml.ws.handler.soap.SOAPMessageContext;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class LoggingHandler implements SOAPHandler<SOAPMessageContext> {
+
+ Logger log = LoggerFactory.getLogger(LoggingHandler.class);
+
+ public boolean handleMessage(SOAPMessageContext context) {
+ SOAPMessage msg = context.getMessage();
+ boolean request = ((Boolean) context
+ .get(SOAPMessageContext.MESSAGE_OUTBOUND_PROPERTY)).booleanValue();
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+ try {
+ if (request) {
+ msg.writeTo(bos);
+ } else { // This is the response message
+ msg.writeTo(bos);
+ }
+
+ log.trace(bos.toString());
+ log.trace(new String(bos.toByteArray()));
+
+ } catch (Exception e) {
+ log.trace(e.getMessage(), e);
+ }
+ return true;
+ }
+
+ public boolean handleFault(SOAPMessageContext context) {
+ return handleMessage(context);
+ }
+
+ public void close(MessageContext context) {
+ }
+
+ public Set<QName> getHeaders() {
+ return null;
+ }
+
+}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/utils/eIDASResponseUtils.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/utils/eIDASResponseUtils.java
new file mode 100644
index 00000000..165c35cb
--- /dev/null
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/utils/eIDASResponseUtils.java
@@ -0,0 +1,98 @@
+package at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.utils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.joda.time.DateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableList;
+
+import at.gv.egiz.eaaf.core.impl.data.Trible;
+import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.Constants;
+import eu.eidas.auth.commons.attribute.AttributeDefinition;
+import eu.eidas.auth.commons.attribute.AttributeValue;
+import eu.eidas.auth.commons.attribute.AttributeValueMarshaller;
+import eu.eidas.auth.commons.attribute.AttributeValueMarshallingException;
+import eu.eidas.auth.commons.protocol.eidas.impl.PostalAddress;
+
+public class eIDASResponseUtils {
+ private static final Logger log = LoggerFactory.getLogger(eIDASResponseUtils.class);
+
+ public static final String PERSONALIDENIFIER_VALIDATION_PATTERN = "^[A-Z,a-z]{2}/[A-Z,a-z]{2}/.*";
+
+ /**
+ * Validate a eIDAS PersonalIdentifier attribute value
+ * This validation is done according to eIDAS SAML Attribute Profile - Section 2.2.3 Unique Identifier
+ *
+ * @param uniqueID eIDAS attribute value of a unique identifier
+ * @return true if the uniqueID matches to eIDAS to Unique Identifier specification, otherwise false
+ */
+ public static boolean validateEidasPersonalIdentifier(String uniqueID) {
+ Pattern pattern = Pattern.compile(PERSONALIDENIFIER_VALIDATION_PATTERN );
+ Matcher matcher = pattern.matcher(uniqueID);
+ return matcher.matches();
+
+ }
+
+
+ /**
+ * Parse an eIDAS PersonalIdentifier attribute value into it components.
+ * This processing is done according to eIDAS SAML Attribute Profile - Section 2.2.3 Unique Identifier
+ *
+ * @param uniqueID eIDAS attribute value of a unique identifier
+ * @return {@link Trible} that contains:
+ * <br> First : citizen country
+ * <br> Second: destination country
+ * <br> Third : unique identifier
+ * <br> or null if the attribute value has a wrong format
+ */
+ public static Trible<String, String, String> parseEidasPersonalIdentifier(String uniqueID) {
+ if (!validateEidasPersonalIdentifier(uniqueID)) {
+ log.error("eIDAS attribute value for " + Constants.eIDAS_ATTR_PERSONALIDENTIFIER
+ + " looks wrong formated. Value:" + ((String)uniqueID));
+ return null;
+
+ }
+ return Trible.newInstance(uniqueID.substring(0, 2), uniqueID.substring(3, 5), uniqueID.substring(6));
+
+ }
+
+ public static List<String> translateStringListAttribute(AttributeDefinition<?> attributeDefinition, ImmutableList<? extends AttributeValue<?>> attributeValues) {
+ final List<String> stringListAttribute = new ArrayList<String>();
+ AttributeValueMarshaller<?> attributeValueMarshaller = attributeDefinition.getAttributeValueMarshaller();
+ for (AttributeValue<?> attributeValue : attributeValues) {
+ String valueString = null;
+ try {
+ valueString = attributeValueMarshaller.marshal((AttributeValue) attributeValue);
+ stringListAttribute.add(valueString);
+ } catch (AttributeValueMarshallingException e) {
+ throw new IllegalStateException(e);
+
+ }
+ }
+
+ return stringListAttribute;
+
+ }
+
+ public static DateTime translateDateAttribute(AttributeDefinition<?> attributeDefinition, ImmutableList<? extends AttributeValue<?>> attributeValues) {
+ if (attributeValues.size() != 0) {
+ final AttributeValue<?> firstAttributeValue = attributeValues.get(0);
+ return (DateTime) firstAttributeValue.getValue();
+
+ }
+
+ return null;
+ }
+
+ public static PostalAddress translateAddressAttribute(AttributeDefinition<?> attributeDefinition, ImmutableList<? extends AttributeValue<?>> attributeValues) {
+ final AttributeValue<?> firstAttributeValue = attributeValues.get(0);
+ return (PostalAddress) firstAttributeValue.getValue();
+
+ }
+
+}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/validator/eIDASResponseValidator.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/validator/eIDASResponseValidator.java
new file mode 100644
index 00000000..3791d0d7
--- /dev/null
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/gv/egiz/eidas/specific/modules/authmodule_eIDASv2/validator/eIDASResponseValidator.java
@@ -0,0 +1,135 @@
+package at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.validator;
+
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableList;
+
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.impl.data.Trible;
+import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.Constants;
+import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.exception.eIDASValidationException;
+import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.service.eIDASAttributeRegistry;
+import at.gv.egiz.eidas.specific.modules.authmodule_eIDASv2.utils.eIDASResponseUtils;
+import eu.eidas.auth.commons.attribute.AttributeDefinition;
+import eu.eidas.auth.commons.attribute.AttributeValue;
+import eu.eidas.auth.commons.light.ILightResponse;
+import eu.eidas.auth.commons.protocol.eidas.LevelOfAssurance;
+
+/**
+ * @author tlenz
+ *
+ */
+public class eIDASResponseValidator {
+ private static final Logger log = LoggerFactory.getLogger(eIDASResponseValidator.class);
+
+ public static void validateResponse(IRequest pendingReq, ILightResponse eIDASResponse, String spCountry, eIDASAttributeRegistry attrRegistry) throws eIDASValidationException {
+
+ /*-----------------------------------------------------|
+ * validate received LoA against minimum required LoA |
+ *_____________________________________________________|
+ */
+ LevelOfAssurance respLoA = LevelOfAssurance.fromString(eIDASResponse.getLevelOfAssurance());
+ List<String> allowedLoAs = pendingReq.getServiceProviderConfiguration().getRequiredLoA();
+ boolean loaValid = false;
+ for (String allowedLoaString : allowedLoAs) {
+ LevelOfAssurance allowedLoa = LevelOfAssurance.fromString(allowedLoaString);
+ if (respLoA.numericValue() >= allowedLoa.numericValue()) {
+ log.debug("Response contains valid LoA. Resume process ... ");
+ loaValid = true;
+ break;
+
+ } else
+ log.trace("Allowed LoA: " + allowedLoaString + " DOES NOT match response LoA: " + eIDASResponse.getLevelOfAssurance());
+
+ }
+
+ if (!loaValid) {
+ log.error("eIDAS Response LevelOfAssurance is lower than the required! "
+ + "(Resp-LoA:" + respLoA.getValue() + " Req-LoA:" + allowedLoAs.toArray() + ")");
+ throw new eIDASValidationException("eidas.06", new Object[]{respLoA.getValue()});
+
+ }
+
+
+
+ /*-----------------------------------------------------|
+ * validate 'PersonalIdentifier' attribute |
+ *_____________________________________________________|
+ */
+ AttributeDefinition<?> attrDefinition = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(Constants.eIDAS_ATTR_PERSONALIDENTIFIER).first();
+ final ImmutableList<? extends AttributeValue<?>> attributeValues = eIDASResponse.getAttributes().getAttributeMap().get(attrDefinition).asList();
+ List<String> personalIdObj = eIDASResponseUtils.translateStringListAttribute(attrDefinition, attributeValues);
+
+ //check if attribute exists
+ if (personalIdObj == null || personalIdObj.isEmpty()) {
+ log.warn("eIDAS Response include NO 'PersonalIdentifier' attriubte "
+ + ".... That can be a BIG problem in further processing steps");
+ throw new eIDASValidationException("eidas.05", new Object[] {"NO 'PersonalIdentifier' attriubte"});
+
+ } else if (personalIdObj.size() > 1) {
+ log.warn("eIDAS Response include MORE THAN ONE 'PersonalIdentifier' attriubtes "
+ + ".... That can be a BIG problem in further processing steps");
+ throw new eIDASValidationException("eidas.05", new Object[] {"MORE THAN ONE 'PersonalIdentifier' attriubtes"});
+
+ } else {
+ String natPersId = personalIdObj.get(0);
+ //validate attribute value format
+ Trible<String, String, String> split =
+ eIDASResponseUtils.parseEidasPersonalIdentifier(natPersId);
+ if (split == null) {
+ throw new eIDASValidationException("eidas.07",
+ new Object[]{
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER,
+ "Wrong identifier format"});
+
+ } else {
+ //validation according to eIDAS SAML Attribute Profile, Section 2.2.3
+ if (StringUtils.isEmpty(split.getSecond())) {
+ log.warn("eIDAS attribute value for " + Constants.eIDAS_ATTR_PERSONALIDENTIFIER
+ + " includes NO destination country. Value:" + natPersId);
+ throw new eIDASValidationException("eidas.07",
+ new Object[]{
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER,
+ "No or empty destination country"});
+
+ }
+ if (!split.getSecond().equalsIgnoreCase(spCountry)) {
+ log.warn("eIDAS attribute value for " + Constants.eIDAS_ATTR_PERSONALIDENTIFIER
+ + " includes wrong destination country. Value:" + natPersId
+ + " SP-Country:" + spCountry);
+ throw new eIDASValidationException("eidas.07",
+ new Object[]{
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER,
+ "Destination country does not match to SP country"});
+
+ }
+
+ if (StringUtils.isEmpty(split.getFirst())) {
+ log.warn("eIDAS attribute value for " + Constants.eIDAS_ATTR_PERSONALIDENTIFIER
+ + " includes NO citizen country. Value:" + natPersId);
+ throw new eIDASValidationException("eidas.07",
+ new Object[]{
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER,
+ "No or empty citizen country"});
+
+ }
+ if (!split.getSecond().equalsIgnoreCase(spCountry)) {
+ log.warn("eIDAS attribute value for " + Constants.eIDAS_ATTR_PERSONALIDENTIFIER
+ + " includes a relaying-party country that does not match to service-provider country. "
+ + " Value:" + natPersId
+ + " SP Country:" + spCountry);
+ throw new eIDASValidationException("eidas.07",
+ new Object[]{
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER,
+ "Citizen country does not match to eIDAS-node country that generates the response"});
+
+ }
+ }
+ }
+
+ }
+}