aboutsummaryrefslogtreecommitdiff
path: root/modules/eidas_proxy-sevice
diff options
context:
space:
mode:
authorThomas <>2022-03-08 19:06:10 +0100
committerThomas <>2022-03-08 19:06:10 +0100
commit7bf7c3c03fd3a1efeaf3f8e3dd75922e2f5f9921 (patch)
tree6e4ec82475f4f30275d3e0a0305ad3c2d340e0d3 /modules/eidas_proxy-sevice
parent300bd1b44f521a2b33c259be1f8d21eba58c1a31 (diff)
downloadNational_eIDAS_Gateway-7bf7c3c03fd3a1efeaf3f8e3dd75922e2f5f9921.tar.gz
National_eIDAS_Gateway-7bf7c3c03fd3a1efeaf3f8e3dd75922e2f5f9921.tar.bz2
National_eIDAS_Gateway-7bf7c3c03fd3a1efeaf3f8e3dd75922e2f5f9921.zip
refactor(core): move all project libs into sub-project 'modules'
Diffstat (limited to 'modules/eidas_proxy-sevice')
-rw-r--r--modules/eidas_proxy-sevice/checks/spotbugs-exclude.xml20
-rw-r--r--modules/eidas_proxy-sevice/pom.xml184
-rw-r--r--modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/EidasProxyMessageSource.java22
-rw-r--r--modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/MsProxyServiceConstants.java54
-rw-r--r--modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/MsProxyServiceSpringResourceProvider.java52
-rw-r--r--modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/exception/EidasProxyServiceException.java19
-rw-r--r--modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/EidasProxyServiceController.java443
-rw-r--r--modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServiceAuthenticationAction.java374
-rw-r--r--modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServicePendingRequest.java28
-rw-r--r--modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/utils/EidasProxyServiceUtils.java45
-rw-r--r--modules/eidas_proxy-sevice/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider1
-rw-r--r--modules/eidas_proxy-sevice/src/main/resources/messages/eidasproxy_messages.properties14
-rw-r--r--modules/eidas_proxy-sevice/src/main/resources/spring/eidas_proxy-service.beans.xml28
-rw-r--r--modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/EidasProxyMessageSourceTest.java50
-rw-r--r--modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/MsProxyServiceSpringResourceProviderTest.java56
-rw-r--r--modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/protocol/EidasProxyServiceControllerTest.java666
-rw-r--r--modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/protocol/ProxyServiceAuthenticationActionTest.java637
-rw-r--r--modules/eidas_proxy-sevice/src/test/resources/config/additional-attributes.xml39
-rw-r--r--modules/eidas_proxy-sevice/src/test/resources/config/eidas-attributes.xml376
-rw-r--r--modules/eidas_proxy-sevice/src/test/resources/config/junit_config_1.properties6
-rw-r--r--modules/eidas_proxy-sevice/src/test/resources/spring/SpringTest-context_basic_mapConfig.xml20
-rw-r--r--modules/eidas_proxy-sevice/src/test/resources/spring/SpringTest-context_basic_test.xml42
22 files changed, 3176 insertions, 0 deletions
diff --git a/modules/eidas_proxy-sevice/checks/spotbugs-exclude.xml b/modules/eidas_proxy-sevice/checks/spotbugs-exclude.xml
new file mode 100644
index 00000000..cdc9fa95
--- /dev/null
+++ b/modules/eidas_proxy-sevice/checks/spotbugs-exclude.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<FindBugsFilter>
+ <Match>
+ <!-- CSRF protection is implicit available by request token from eIDAS Node and tokens only be logged on trace level -->
+ <Class name="at.asitplus.eidas.specific.modules.msproxyservice.protocol.EidasProxyServiceController" />
+ <Method name="receiveEidasAuthnRequest" />
+ <OR>
+ <Bug pattern="SPRING_CSRF_UNRESTRICTED_REQUEST_MAPPING" />
+ <Bug pattern="CRLF_INJECTION_LOGS" />
+ </OR>
+ </Match>
+ <Match>
+ <!-- Redirect-URL is set by configuration only. Therefore it's trusted -->
+ <Class name="at.asitplus.eidas.specific.modules.msproxyservice.protocol.ProxyServiceAuthenticationAction" />
+ <Method name="forwardToEidasProxy" />
+ <OR>
+ <Bug pattern="UNVALIDATED_REDIRECT" />
+ </OR>
+ </Match>
+</FindBugsFilter>
diff --git a/modules/eidas_proxy-sevice/pom.xml b/modules/eidas_proxy-sevice/pom.xml
new file mode 100644
index 00000000..55a6974c
--- /dev/null
+++ b/modules/eidas_proxy-sevice/pom.xml
@@ -0,0 +1,184 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>at.asitplus.eidas.ms_specific</groupId>
+ <artifactId>modules</artifactId>
+ <version>1.2.4-SNAPSHOT</version>
+ </parent>
+ <groupId>at.asitplus.eidas.ms_specific.modules</groupId>
+ <artifactId>eidas_proxy-sevice</artifactId>
+ <name>eIDAS specific proxy-service</name>
+ <description>Austrian specific eIDAS Proxy-Service to handle eIDAS Proxy-Service requests from other member states</description>
+
+ <repositories>
+ <repository>
+ <id>eIDASNode-local</id>
+ <name>local</name>
+ <url>file:${basedir}/../../repository</url>
+ </repository>
+ </repositories>
+
+ <dependencies>
+ <dependency>
+ <groupId>at.gv.egiz.components</groupId>
+ <artifactId>egiz-spring-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>at.asitplus.eidas.ms_specific</groupId>
+ <artifactId>core_common_lib</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>at.asitplus.eidas.ms_specific.modules</groupId>
+ <artifactId>authmodule-eIDAS-v2</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>at.gv.egiz.eaaf</groupId>
+ <artifactId>eaaf-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>at.gv.egiz.eaaf</groupId>
+ <artifactId>eaaf_module_pvp2_sp</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>eu.eidas</groupId>
+ <artifactId>eidas-light-commons</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>eu.eidas</groupId>
+ <artifactId>eidas-specific-communication-definition</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>eu.eidas</groupId>
+ <artifactId>eidas-jcache-ignite-specific-communication</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-text</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <!-- Testing -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>2.0.7</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito2</artifactId>
+ <version>2.0.7</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>at.asitplus.eidas.ms_specific</groupId>
+ <artifactId>core_common_lib</artifactId>
+ <scope>test</scope>
+ <type>test-jar</type>
+ </dependency>
+ <dependency>
+ <groupId>at.asitplus.eidas.ms_specific.modules</groupId>
+ <artifactId>authmodule-eIDAS-v2</artifactId>
+ <scope>test</scope>
+ <type>test-jar</type>
+ </dependency>
+
+ <dependency>
+ <groupId>at.gv.egiz.eaaf</groupId>
+ <artifactId>eaaf_core_utils</artifactId>
+ <scope>test</scope>
+ <type>test-jar</type>
+ </dependency>
+ <dependency>
+ <groupId>at.gv.egiz.eaaf</groupId>
+ <artifactId>eaaf-core</artifactId>
+ <scope>test</scope>
+ <type>test-jar</type>
+ </dependency>
+
+ </dependencies>
+
+<build>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ </resource>
+ </resources>
+
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+
+ <plugin>
+ <groupId>com.github.spotbugs</groupId>
+ <artifactId>spotbugs-maven-plugin</artifactId>
+ <version>${spotbugs-maven-plugin.version}</version>
+ <configuration>
+ <excludeFilterFile>checks/spotbugs-exclude.xml</excludeFilterFile>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>post-unit-check</id>
+ <phase>test</phase>
+ <goals>
+ <goal>check</goal>
+ <goal>report</goal>
+ </goals>
+ <configuration>
+ <haltOnFailure>true</haltOnFailure>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ <!-- enable co-existence of testng and junit -->
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <threadCount>1</threadCount>
+ </configuration>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.surefire</groupId>
+ <artifactId>surefire-junit47</artifactId>
+ <version>${surefire.version}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+
+</project> \ No newline at end of file
diff --git a/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/EidasProxyMessageSource.java b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/EidasProxyMessageSource.java
new file mode 100644
index 00000000..23390da8
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/EidasProxyMessageSource.java
@@ -0,0 +1,22 @@
+package at.asitplus.eidas.specific.modules.msproxyservice;
+
+import java.util.Arrays;
+import java.util.List;
+
+import at.gv.egiz.eaaf.core.api.logging.IMessageSourceLocation;
+
+/**
+ * i18n Message-Source for eIDAS Proxy-Service messages.
+ *
+ * @author tlenz
+ *
+ */
+public class EidasProxyMessageSource implements IMessageSourceLocation {
+
+ @Override
+ public List<String> getMessageSourceLocation() {
+ return Arrays.asList("classpath:messages/eidasproxy_messages");
+
+ }
+
+}
diff --git a/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/MsProxyServiceConstants.java b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/MsProxyServiceConstants.java
new file mode 100644
index 00000000..f6a88aa3
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/MsProxyServiceConstants.java
@@ -0,0 +1,54 @@
+package at.asitplus.eidas.specific.modules.msproxyservice;
+
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.gv.egiz.eaaf.core.api.data.EaafConfigConstants;
+
+/**
+ * Constants for MS-specific eIDAS Proxy-Service.
+ *
+ * @author tlenz
+ *
+ */
+public class MsProxyServiceConstants {
+
+ // general constants
+ public static final String TEMPLATE_SP_UNIQUE_ID = "eidasProxyAuth_from_{0}_type_{1}";
+
+ // configuration constants
+ public static final String CONIG_PROPS_EIDAS_PROXY_NODE_ENTITYID = Constants.CONIG_PROPS_EIDAS_NODE
+ + ".proxy.entityId";
+ public static final String CONIG_PROPS_EIDAS_PROXY_NODE_FORWARD_URL = Constants.CONIG_PROPS_EIDAS_NODE
+ + ".proxy.forward.endpoint";
+
+ // mandate configuration
+ public static final String CONIG_PROPS_EIDAS_PROXY_MANDATES_ENABLED =
+ Constants.CONIG_PROPS_EIDAS_PREFIX + ".proxy.mandates.enabled";
+ public static final String CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_NATURAL =
+ Constants.CONIG_PROPS_EIDAS_PREFIX + ".proxy.mandates.profiles.natural.default";
+ public static final String CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_LEGAL =
+ Constants.CONIG_PROPS_EIDAS_PREFIX + ".proxy.mandates.profiles.legal.default";
+
+
+ public static final String CONIG_PROPS_EIDAS_PROXY_WORKAROUND_MANDATES_LEGAL_PERSON =
+ Constants.CONIG_PROPS_EIDAS_PREFIX + ".proxy.workaround.mandates.legalperson";
+
+ // specific eIDAS-Connector configuration
+ public static final String CONIG_PROPS_CONNECTOR_PREFIX = "connector";
+ public static final String CONIG_PROPS_CONNECTOR_UNIQUEID = EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER;
+ public static final String CONIG_PROPS_CONNECTOR_COUNTRYCODE = "countryCode";
+ public static final String CONIG_PROPS_CONNECTOR_MANDATES_ENABLED = "mandates.enabled";
+ public static final String CONIG_PROPS_CONNECTOR_MANDATES_PROFILE_NATURAL = "mandates.natural";
+ public static final String CONIG_PROPS_CONNECTOR_MANDATES_PROFILE_LEGAL = "mandates.legal";
+ public static final String CONIG_PROPS_CONNECTOR_VALIDATION_ATTR_MDS = "validation.attributes.mds";
+
+
+ //http end-points
+ public static final String EIDAS_HTTP_ENDPOINT_IDP_POST = "/eidas/light/idp/post";
+ public static final String EIDAS_HTTP_ENDPOINT_IDP_REDIRECT = "/eidas/light/idp/redirect";
+
+ private MsProxyServiceConstants() {
+ //private constructor for class with only constant values
+
+ }
+
+}
diff --git a/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/MsProxyServiceSpringResourceProvider.java b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/MsProxyServiceSpringResourceProvider.java
new file mode 100644
index 00000000..d36e4712
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/MsProxyServiceSpringResourceProvider.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2018 A-SIT Plus GmbH
+ * AT-specific eIDAS Connector has been developed in a cooperation between EGIZ,
+ * A-SIT Plus GmbH, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "License");
+ * You may not use this work except in compliance with the License.
+ * You may obtain a copy of the License at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+*/
+
+package at.asitplus.eidas.specific.modules.msproxyservice;
+
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+
+import at.gv.egiz.components.spring.api.SpringResourceProvider;
+
+public class MsProxyServiceSpringResourceProvider implements SpringResourceProvider {
+
+ @Override
+ public String getName() {
+ return "MS-specific eIDAS Proxy-Service module";
+ }
+
+ @Override
+ public String[] getPackagesToScan() {
+ return null;
+
+ }
+
+ @Override
+ public Resource[] getResourcesToLoad() {
+ final ClassPathResource eidasProxyServiceConfig =
+ new ClassPathResource("/spring/eidas_proxy-service.beans.xml", MsProxyServiceSpringResourceProvider.class);
+
+ return new Resource[] { eidasProxyServiceConfig };
+ }
+
+}
diff --git a/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/exception/EidasProxyServiceException.java b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/exception/EidasProxyServiceException.java
new file mode 100644
index 00000000..43592a28
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/exception/EidasProxyServiceException.java
@@ -0,0 +1,19 @@
+package at.asitplus.eidas.specific.modules.msproxyservice.exception;
+
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+
+public class EidasProxyServiceException extends EaafException {
+
+ private static final long serialVersionUID = 1L;
+
+ public EidasProxyServiceException(String errorId, Object[] params) {
+ super(errorId, params);
+
+ }
+
+ public EidasProxyServiceException(String errorId, Object[] params, Throwable e) {
+ super(errorId, params, e);
+
+ }
+
+}
diff --git a/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/EidasProxyServiceController.java b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/EidasProxyServiceController.java
new file mode 100644
index 00000000..e24c753e
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/EidasProxyServiceController.java
@@ -0,0 +1,443 @@
+package at.asitplus.eidas.specific.modules.msproxyservice.protocol;
+
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.opensaml.saml.saml2.core.NameIDType;
+import org.opensaml.saml.saml2.core.StatusCode;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import com.google.common.collect.ImmutableSortedSet;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.asitplus.eidas.specific.core.config.ServiceProviderConfiguration;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.EidasAttributeRegistry;
+import at.asitplus.eidas.specific.modules.msproxyservice.MsProxyServiceConstants;
+import at.asitplus.eidas.specific.modules.msproxyservice.exception.EidasProxyServiceException;
+import at.asitplus.eidas.specific.modules.msproxyservice.utils.EidasProxyServiceUtils;
+import at.gv.egiz.components.eventlog.api.EventConstants;
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.api.data.EaafConfigConstants;
+import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions.SpMandateModes;
+import at.gv.egiz.eaaf.core.api.idp.IModulInfo;
+import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.exceptions.GuiBuildException;
+import at.gv.egiz.eaaf.core.impl.idp.controller.AbstractController;
+import at.gv.egiz.eaaf.core.impl.utils.KeyValueUtils;
+import eu.eidas.auth.commons.EIDASSubStatusCode;
+import eu.eidas.auth.commons.EidasParameterKeys;
+import eu.eidas.auth.commons.light.ILightRequest;
+import eu.eidas.auth.commons.light.impl.LightResponse;
+import eu.eidas.auth.commons.light.impl.LightResponse.Builder;
+import eu.eidas.auth.commons.light.impl.ResponseStatus;
+import eu.eidas.specificcommunication.SpecificCommunicationDefinitionBeanNames;
+import eu.eidas.specificcommunication.exception.SpecificCommunicationException;
+import eu.eidas.specificcommunication.protocol.SpecificCommunicationService;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * End-point implementation for authentication requests from eIDAS Proxy-Service
+ * to MS-specific eIDAS Proxy-Service.
+ *
+ * @author tlenz
+ *
+ */
+@Slf4j
+@Controller
+public class EidasProxyServiceController extends AbstractController implements IModulInfo {
+
+ private static final String ERROR_01 = "eidas.proxyservice.01";
+ private static final String ERROR_02 = "eidas.proxyservice.02";
+ private static final String ERROR_03 = "eidas.proxyservice.03";
+ private static final String ERROR_04 = "eidas.proxyservice.04";
+ private static final String ERROR_05 = "eidas.proxyservice.05";
+ private static final String ERROR_07 = "eidas.proxyservice.07";
+ private static final String ERROR_08 = "eidas.proxyservice.08";
+ private static final String ERROR_09 = "eidas.proxyservice.09";
+ private static final String ERROR_10 = "eidas.proxyservice.10";
+ private static final String ERROR_11 = "eidas.proxyservice.11";
+
+ public static final String PROTOCOL_ID = "eidasProxy";
+
+ @Autowired EidasAttributeRegistry attrRegistry;
+ @Autowired ProxyServiceAuthenticationAction responseAction;
+
+ /**
+ * End-point that receives authentication requests from eIDAS Node.
+ *
+ * @param httpReq Http request
+ * @param httpResp Http response
+ * @throws IOException In case of general error
+ * @throws EaafException In case of a validation or processing error
+ */
+ @RequestMapping(value = {
+ MsProxyServiceConstants.EIDAS_HTTP_ENDPOINT_IDP_POST,
+ MsProxyServiceConstants.EIDAS_HTTP_ENDPOINT_IDP_REDIRECT
+ },
+ method = { RequestMethod.POST, RequestMethod.GET })
+ public void receiveEidasAuthnRequest(HttpServletRequest httpReq, HttpServletResponse httpResp)
+ throws IOException,
+ EaafException {
+ log.trace("Receive request on eidas proxy-service end-points");
+ ProxyServicePendingRequest pendingReq = null;
+ try {
+ // get token from Request
+ final String tokenBase64 = httpReq.getParameter(EidasParameterKeys.TOKEN.toString());
+ if (StringUtils.isEmpty(tokenBase64)) {
+ log.warn("NO eIDAS message token found.");
+ throw new EidasProxyServiceException(ERROR_02, null);
+
+ }
+ log.trace("Receive eIDAS-node token: {}. Searching authentication request from eIDAS Proxy-Service ...",
+ tokenBase64);
+
+ // read authentication request from shared cache
+ final SpecificCommunicationService specificProxyCommunicationService =
+ (SpecificCommunicationService) applicationContext.getBean(
+ SpecificCommunicationDefinitionBeanNames.SPECIFIC_PROXYSERVICE_COMMUNICATION_SERVICE
+ .toString());
+ final ILightRequest eidasRequest = specificProxyCommunicationService.getAndRemoveRequest(
+ tokenBase64,
+ ImmutableSortedSet.copyOf(attrRegistry.getCoreAttributeRegistry().getAttributes()));
+ if (eidasRequest == null) {
+ log.info("Find no eIDAS Authn. Request with stated token.");
+ throw new EidasProxyServiceException(ERROR_11, null);
+
+ }
+
+ log.debug("Received eIDAS auth. request from: {}, Initializing authentication environment ... ",
+ eidasRequest.getSpCountryCode() != null ? eidasRequest.getSpCountryCode() : "'missing SP-country'");
+ log.trace("Received eIDAS requst: {}", eidasRequest);
+
+ // create pendingRequest object
+ pendingReq = applicationContext.getBean(ProxyServicePendingRequest.class);
+ pendingReq.initialize(httpReq, authConfig);
+ pendingReq.setModule(getName());
+
+ // log 'transaction created' event
+ revisionsLogger.logEvent(EventConstants.TRANSACTION_CREATED,
+ pendingReq.getUniqueTransactionIdentifier());
+ revisionsLogger.logEvent(pendingReq.getUniqueSessionIdentifier(),
+ pendingReq.getUniqueTransactionIdentifier(), EventConstants.TRANSACTION_IP,
+ httpReq.getRemoteAddr());
+
+ // validate eIDAS Authn. request and set into pending-request
+ validateEidasAuthnRequest(eidasRequest);
+ pendingReq.setEidasRequest(eidasRequest);
+
+ // generate Service-Provider configuration from eIDAS request
+ final ISpConfiguration spConfig = generateSpConfigurationFromEidasRequest(eidasRequest);
+
+ // validate eIDAS Authn. request by using eIDAS Connector specifc parameters
+ validateEidasAuthnRequest(spConfig, eidasRequest);
+
+ // populate pendingRequest with parameters
+ pendingReq.setOnlineApplicationConfiguration(spConfig);
+ pendingReq.setSpEntityId(spConfig.getUniqueIdentifier());
+ pendingReq.setPassiv(false);
+ pendingReq.setForce(true);
+
+ // AuthnRequest needs authentication
+ pendingReq.setNeedAuthentication(true);
+
+ // set protocol action, which should be executed after authentication
+ pendingReq.setAction(ProxyServiceAuthenticationAction.class.getName());
+
+ // switch to session authentication
+ protAuthService.performAuthentication(httpReq, httpResp, pendingReq);
+
+ } catch (final EidasProxyServiceException e) {
+ throw e;
+
+ } catch (final SpecificCommunicationException e) {
+ log.error("Can not read eIDAS Authn request from shared cache. Reason: {}", e.getMessage());
+ throw new EidasProxyServiceException(ERROR_03, new Object[] { e.getMessage() }, e);
+
+ } catch (final Throwable e) {
+ // write revision log entries
+ if (pendingReq != null) {
+ revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR,
+ pendingReq.getUniqueTransactionIdentifier());
+ }
+
+ throw new EidasProxyServiceException(ERROR_01, new Object[] { e.getMessage() }, e);
+ }
+
+ }
+
+ @Override
+ public boolean generateErrorMessage(Throwable e, HttpServletRequest httpReq, HttpServletResponse httpResp,
+ IRequest pendingReq) throws Throwable {
+ if (pendingReq instanceof ProxyServicePendingRequest) {
+ try {
+ ILightRequest eidasReq = ((ProxyServicePendingRequest) pendingReq).getEidasRequest();
+
+ //build eIDAS response
+ Builder lightRespBuilder = LightResponse.builder();
+ lightRespBuilder.id(UUID.randomUUID().toString());
+ lightRespBuilder.inResponseToId(eidasReq.getId());
+ lightRespBuilder.relayState(eidasReq.getRelayState());
+ lightRespBuilder.issuer(authConfig.getBasicConfiguration(
+ MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_NODE_ENTITYID));
+ lightRespBuilder.subject(UUID.randomUUID().toString());
+ lightRespBuilder.subjectNameIdFormat(NameIDType.TRANSIENT);
+ lightRespBuilder.status(ResponseStatus.builder()
+ .statusCode(StatusCode.RESPONDER)
+ .subStatusCode(EIDASSubStatusCode.AUTHN_FAILED_URI.getValue())
+ .statusMessage(StringEscapeUtils.escapeXml(e.getLocalizedMessage()))
+ .build());
+
+ // forward to eIDAS Proxy-Service
+ responseAction.forwardToEidasProxy(pendingReq, httpReq, httpResp, lightRespBuilder.build());
+
+ return true;
+
+ } catch (ServletException | IOException | GuiBuildException e1) {
+ log.warn("Forward error to eIDAS Proxy-Service FAILED. Handle error localy ... ", e1);
+
+ }
+
+ } else {
+ log.error("eIDAS Proxy-Service authentication requires PendingRequest of Type: {}",
+ ProxyServicePendingRequest.class.getName());
+
+ }
+
+ return false;
+
+ }
+
+ @Override
+ public String getName() {
+ return EidasProxyServiceController.class.getName();
+
+ }
+
+ @Override
+ public String getAuthProtocolIdentifier() {
+ return PROTOCOL_ID;
+
+ }
+
+ @Override
+ public boolean validate(HttpServletRequest request, HttpServletResponse response, IRequest pending) {
+ return true;
+
+ }
+
+ /**
+ * Generic validation of incoming eIDAS request.
+ *
+ * @param eidasRequest Incoming eIDAS authentication request
+ * @throws EidasProxyServiceException In case of a validation error
+ */
+ private void validateEidasAuthnRequest(ILightRequest eidasRequest) throws EidasProxyServiceException {
+ if (StringUtils.isEmpty(eidasRequest.getIssuer())) {
+ throw new EidasProxyServiceException(ERROR_05, null);
+
+ }
+
+ // TODO: validate some other stuff
+
+ }
+
+ /**
+ * eIDAS Connector specific validation of incoming eIDAS request.
+ *
+ * @param eidasRequest Incoming eIDAS authentication request
+ * @param spConfig eIDAS Connector configuration
+ * @throws EidasProxyServiceException In case of a validation error
+ */
+ private void validateEidasAuthnRequest(ISpConfiguration spConfig, ILightRequest eidasRequest)
+ throws EidasProxyServiceException {
+ // check if natural-person and legal-person attributes requested in parallel
+ if (spConfig.isConfigurationValue(MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_VALIDATION_ATTR_MDS, true)
+ && EidasProxyServiceUtils.isLegalPersonRequested(eidasRequest)
+ && EidasProxyServiceUtils.isNaturalPersonRequested(eidasRequest)) {
+ throw new EidasProxyServiceException(ERROR_08, null);
+
+ }
+
+ // TODO: validate some other stuff
+
+ }
+
+ /**
+ * Generate a dummy Service-Provider configuration for processing.
+ *
+ * @param eidasRequest Incoming eIDAS authentication request
+ * @return Service-Provider configuration that can be used for authentication
+ * @throws EidasProxyServiceException In case of a configuration error
+ */
+ private ISpConfiguration generateSpConfigurationFromEidasRequest(ILightRequest eidasRequest)
+ throws EidasProxyServiceException {
+ try {
+
+ Map<String, String> connectorConfigMap = extractRawConnectorConfiguration(eidasRequest);
+
+ // check if country-code is available
+ String spCountry = connectorConfigMap.get(MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_COUNTRYCODE);
+ if (StringUtils.isEmpty(spCountry)) {
+ throw new EidasProxyServiceException(ERROR_07, null);
+
+ }
+
+ // build FriendyName from CountryCode and SPType
+ connectorConfigMap.put(MsEidasNodeConstants.PROP_CONFIG_SP_FRIENDLYNAME,
+ MessageFormat.format(MsProxyServiceConstants.TEMPLATE_SP_UNIQUE_ID,
+ spCountry, eidasRequest.getSpType()));
+
+ // build Service-Provider configuration object
+ final ServiceProviderConfiguration spConfig = new ServiceProviderConfiguration(connectorConfigMap, authConfig);
+
+ // build bPK target from Country-Code
+ final String ccCountry = authConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_COUNTRYCODE,
+ Constants.DEFAULT_MS_NODE_COUNTRY_CODE);
+ spConfig.setBpkTargetIdentifier(
+ EaafConstants.URN_PREFIX_EIDAS + ccCountry + "+" + spCountry);
+
+ // set required LoA from eIDAS request
+ spConfig.setRequiredLoA(
+ eidasRequest.getLevelsOfAssurance().stream().map(el -> el.getValue()).collect(Collectors.toList()));
+
+ //build mandate profiles for this specific request
+ buildMandateProfileConfiguration(spConfig, eidasRequest);
+
+ return spConfig;
+
+ } catch (EidasProxyServiceException e) {
+ throw e;
+
+ } catch (final EaafException e) {
+ throw new EidasProxyServiceException(ERROR_04, new Object[] { e.getMessage() }, e);
+
+ }
+ }
+
+
+ private Map<String, String> extractRawConnectorConfiguration(ILightRequest eidasRequest) {
+ Map<String, String> allConnectorConfigs = authConfig.getBasicConfigurationWithPrefix(
+ MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_PREFIX);
+ if (log.isTraceEnabled()) {
+ log.trace("Full-connector configuration:");
+ allConnectorConfigs.entrySet().stream().forEach(
+ el -> log.trace("Key: {} -> Value: {}", el.getKey(), el.getValue()));
+
+ }
+
+
+ Map<String, String> connectorConfig = allConnectorConfigs.entrySet().stream()
+ .filter(el -> el.getKey().endsWith(MsEidasNodeConstants.PROP_CONFIG_SP_UNIQUEIDENTIFIER)
+ && el.getValue().equals(eidasRequest.getIssuer()))
+ .findFirst()
+ .map(el -> KeyValueUtils.getSubSetWithPrefix(allConnectorConfigs,
+ KeyValueUtils.getParentKey(el.getKey()) + KeyValueUtils.KEY_DELIMITER))
+ .orElse(new HashMap<>());
+
+
+ if (connectorConfig.isEmpty()) {
+ log.debug("No specific configuration for eIDAS Connector: {} Using default configuration ... ",
+ eidasRequest.getIssuer());
+
+ // set EntityId of the requesting eIDAS Connector
+ connectorConfig.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, eidasRequest.getIssuer());
+
+ // set country-code from eIDAS request
+ connectorConfig.put(MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_COUNTRYCODE,
+ eidasRequest.getSpCountryCode());
+
+ // set default mandate configuration
+ connectorConfig.put(MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_MANDATES_ENABLED,
+ String.valueOf(authConfig.getBasicConfigurationBoolean(
+ MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_ENABLED, false)));
+ connectorConfig.put(MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_MANDATES_PROFILE_NATURAL,
+ authConfig.getBasicConfiguration(
+ MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_NATURAL));
+ connectorConfig.put(MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_MANDATES_PROFILE_LEGAL,
+ authConfig.getBasicConfiguration(
+ MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_LEGAL));
+
+ } else {
+ log.debug("Find specific configuration for eIDAS Connector: {}", eidasRequest.getIssuer());
+
+ }
+
+ return connectorConfig;
+
+ }
+
+
+ private void buildMandateProfileConfiguration(ServiceProviderConfiguration spConfig, ILightRequest eidasRequest)
+ throws EidasProxyServiceException {
+ // check if mandates are enabled
+ if (spConfig.isConfigurationValue(MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_MANDATES_ENABLED, false)) {
+ injectMandateInfosIntoSpConfig(spConfig, eidasRequest);
+
+ } else {
+ if (EidasProxyServiceUtils.isLegalPersonRequested(eidasRequest)) {
+ throw new EidasProxyServiceException(ERROR_09, null);
+
+ }
+
+ spConfig.setMandateProfiles(Collections.emptyList());
+ spConfig.setMandateMode(SpMandateModes.NONE);
+
+ }
+
+ }
+
+ private void injectMandateInfosIntoSpConfig(ServiceProviderConfiguration spConfig,
+ ILightRequest eidasRequest) throws EidasProxyServiceException {
+ log.trace("eIDAS Proxy-Service allows mandates for Connector: {}. Selecting profiles ... ",
+ spConfig.getUniqueIdentifier());
+
+ //check if legal person is requested
+ if (EidasProxyServiceUtils.isLegalPersonRequested(eidasRequest)) {
+ spConfig.setMandateProfiles(KeyValueUtils.getListOfCsvValues(
+ spConfig.getConfigurationValue(MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_MANDATES_PROFILE_LEGAL)));
+ spConfig.setMandateMode(SpMandateModes.LEGAL_FORCE);
+
+ if (spConfig.getMandateProfiles().isEmpty()) {
+ throw new EidasProxyServiceException(ERROR_10, null);
+
+ }
+
+ } else if (EidasProxyServiceUtils.isNaturalPersonRequested(eidasRequest)) {
+ spConfig.setMandateProfiles(KeyValueUtils.getListOfCsvValues(
+ spConfig.getConfigurationValue(MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_MANDATES_PROFILE_NATURAL)));
+
+ spConfig.setMandateMode(SpMandateModes.NATURAL);
+
+ }
+
+
+ if (spConfig.getMandateProfiles().isEmpty()) {
+ log.debug("No mandate-profiles for issure: {}. Set mandate-mode to 'none'",
+ spConfig.getUniqueIdentifier());
+ spConfig.setMandateMode(SpMandateModes.NONE);
+
+ } else {
+ log.debug("Set mandate-profiles: {} to request from issuer: {}",
+ spConfig.getMandateProfiles(), spConfig.getUniqueIdentifier());
+
+ }
+
+ }
+}
diff --git a/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServiceAuthenticationAction.java b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServiceAuthenticationAction.java
new file mode 100644
index 00000000..15524005
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServiceAuthenticationAction.java
@@ -0,0 +1,374 @@
+package at.asitplus.eidas.specific.modules.msproxyservice.protocol;
+
+import java.io.IOException;
+import java.util.UUID;
+
+import javax.annotation.PostConstruct;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang3.StringUtils;
+import org.opensaml.saml.saml2.core.NameIDType;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.asitplus.eidas.specific.core.gui.StaticGuiBuilderConfiguration;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.EidasAttributeRegistry;
+import at.asitplus.eidas.specific.modules.msproxyservice.MsProxyServiceConstants;
+import at.asitplus.eidas.specific.modules.msproxyservice.exception.EidasProxyServiceException;
+import at.asitplus.eidas.specific.modules.msproxyservice.utils.EidasProxyServiceUtils;
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions;
+import at.gv.egiz.eaaf.core.api.gui.ISpringMvcGuiFormBuilder;
+import at.gv.egiz.eaaf.core.api.idp.IAction;
+import at.gv.egiz.eaaf.core.api.idp.IAuthData;
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.api.idp.IEidAuthData;
+import at.gv.egiz.eaaf.core.api.idp.slo.SloInformationInterface;
+import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.exceptions.GuiBuildException;
+import at.gv.egiz.eaaf.core.impl.data.SloInformationImpl;
+import eu.eidas.auth.commons.EidasParameterKeys;
+import eu.eidas.auth.commons.attribute.AttributeDefinition;
+import eu.eidas.auth.commons.attribute.ImmutableAttributeMap;
+import eu.eidas.auth.commons.light.ILightRequest;
+import eu.eidas.auth.commons.light.ILightResponse;
+import eu.eidas.auth.commons.light.impl.LightResponse;
+import eu.eidas.auth.commons.light.impl.LightResponse.Builder;
+import eu.eidas.auth.commons.light.impl.ResponseStatus;
+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.SpecificCommunicationService;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * Result action of a successfully performed eIDAS Proxy-Service authentication.
+ *
+ * @author tlenz
+ *
+ */
+@Slf4j
+public class ProxyServiceAuthenticationAction implements IAction {
+
+ private static final String PROXYSERVICE_AUTH_ACTION_NAME = "MS-specific eIDAS-Proxy action";
+
+ @Autowired
+ ApplicationContext context;
+ @Autowired
+ IConfiguration basicConfig;
+ @Autowired
+ ResourceLoader resourceLoader;
+ @Autowired
+ ISpringMvcGuiFormBuilder guiBuilder;
+ @Autowired
+ EidasAttributeRegistry attrRegistry;
+
+ @Override
+ public SloInformationInterface processRequest(IRequest pendingReq, HttpServletRequest httpReq,
+ HttpServletResponse httpResp, IAuthData authData) throws EaafException {
+ if (pendingReq instanceof ProxyServicePendingRequest) {
+ try {
+ ILightRequest eidasReq = ((ProxyServicePendingRequest) pendingReq).getEidasRequest();
+
+ //build eIDAS response
+ Builder lightRespBuilder = LightResponse.builder();
+ lightRespBuilder.id(UUID.randomUUID().toString());
+ lightRespBuilder.inResponseToId(eidasReq.getId());
+ lightRespBuilder.relayState(eidasReq.getRelayState());
+
+ lightRespBuilder.status(ResponseStatus.builder()
+ .statusCode(Constants.SUCCESS_URI)
+ .build());
+
+ //TODO: check if we can use transient subjectNameIds
+ lightRespBuilder.subject(UUID.randomUUID().toString());
+ lightRespBuilder.subjectNameIdFormat(NameIDType.TRANSIENT);
+
+ //TODO:
+ lightRespBuilder.issuer(basicConfig.getBasicConfiguration(
+ MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_NODE_ENTITYID));
+ lightRespBuilder.levelOfAssurance(authData.getEidasQaaLevel());
+ lightRespBuilder.attributes(buildAttributesFromAuthData(authData, eidasReq));
+
+ // set SLO response object of EAAF framework
+ final SloInformationImpl sloInformation = new SloInformationImpl();
+ sloInformation.setProtocolType(pendingReq.requestedModule());
+ sloInformation
+ .setSpEntityID(pendingReq.getServiceProviderConfiguration().getUniqueIdentifier());
+
+ // forward to eIDAS Proxy-Service
+ forwardToEidasProxy(pendingReq, httpReq, httpResp, lightRespBuilder.build());
+
+ return sloInformation;
+
+ } catch (ServletException | IOException | GuiBuildException e) {
+ throw new EidasProxyServiceException("eidas.proxyservice.06", null, e);
+
+ }
+
+ } else {
+ log.error("eIDAS Proxy-Service authentication requires PendingRequest of Type: {}",
+ ProxyServicePendingRequest.class.getName());
+ throw new EaafException("eidas.proxyservice.99");
+
+ }
+ }
+
+ @Override
+ public boolean needAuthentication(IRequest req, HttpServletRequest httpReq, HttpServletResponse httpResp) {
+ return true;
+
+ }
+
+ @Override
+ public String getDefaultActionName() {
+ return PROXYSERVICE_AUTH_ACTION_NAME;
+
+ }
+
+
+ /**
+ * Forward eIDAS Light response to eIDAS node.
+ *
+ * @param pendingReq Current pending request.
+ * @param httpReq Current HTTP request
+ * @param httpResp Current HTTP response
+ * @param lightResponse eIDAS LightResponse
+ * @throws EaafConfigurationException In case of a configuration error
+ * @throws IOException In case of a general error
+ * @throws GuiBuildException In case of a GUI rendering error, if http POST binding is used
+ * @throws ServletException In case of a general error
+ */
+ public void forwardToEidasProxy(IRequest pendingReq, HttpServletRequest httpReq,
+ HttpServletResponse httpResp, LightResponse lightResponse) throws EaafConfigurationException, IOException,
+ GuiBuildException, ServletException {
+
+ // put request into shared cache
+ final BinaryLightToken token = putResponseInCommunicationCache(lightResponse);
+ final String tokenBase64 = BinaryLightTokenHelper.encodeBinaryLightTokenBase64(token);
+
+ // select forward URL regarding the selected environment
+ final String forwardUrl = basicConfig.getBasicConfiguration(
+ MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_NODE_FORWARD_URL);
+
+ if (StringUtils.isEmpty(forwardUrl)) {
+ log.warn("NO ForwardURL defined in configuration. Can NOT forward to eIDAS node! Process stops");
+ throw new EaafConfigurationException("config.08",
+ new Object[] { MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_NODE_FORWARD_URL });
+
+ }
+ log.debug("ForwardURL: " + forwardUrl + " selected to forward eIDAS request");
+
+ 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
+ final UriComponentsBuilder redirectUrl = UriComponentsBuilder.fromHttpUrl(forwardUrl);
+ redirectUrl.queryParam(EidasParameterKeys.TOKEN.toString(), tokenBase64);
+ httpResp.sendRedirect(redirectUrl.build().encode().toString());
+
+ } else {
+ log.debug("Use http-post for eIDAS node forwarding ... ");
+ final StaticGuiBuilderConfiguration config = new StaticGuiBuilderConfiguration(
+ basicConfig,
+ pendingReq,
+ Constants.TEMPLATE_POST_FORWARD_NAME,
+ null,
+ resourceLoader);
+
+ config.putCustomParameter(null, Constants.TEMPLATE_POST_FORWARD_ENDPOINT, forwardUrl);
+ config.putCustomParameter(null, Constants.TEMPLATE_POST_FORWARD_TOKEN_NAME,
+ EidasParameterKeys.TOKEN.toString());
+ config.putCustomParameter(null, Constants.TEMPLATE_POST_FORWARD_TOKEN_VALUE,
+ tokenBase64);
+
+ guiBuilder.build(httpReq, httpResp, config, "Forward to eIDASNode form");
+
+ }
+ }
+
+ @PostConstruct
+ private void checkConfiguration() {
+ //TODO: validate configuration on start-up
+
+ }
+
+
+ private ImmutableAttributeMap buildAttributesFromAuthData(IAuthData authData,
+ ILightRequest eidasReq) {
+ IEidAuthData eidAuthData = (IEidAuthData) authData;
+ if (eidAuthData.isUseMandate()) {
+ log.debug("Building eIDAS Proxy-Service response with mandate ... ");
+ final ImmutableAttributeMap.Builder attributeMap = ImmutableAttributeMap.builder();
+ injectRepesentativeInformation(attributeMap, eidAuthData);
+ injectMandatorInformation(attributeMap, eidAuthData);
+
+ // work-around that injects nat. person subject to bypass validation on eIDAS Node
+ injectJurPersonWorkaroundIfRequired(attributeMap, eidasReq, authData);
+
+ return attributeMap.build();
+
+ } else {
+ log.debug("Building eIDAS Proxy-Service response without mandates ... ");
+ return buildAttributesWithoutMandate(eidAuthData);
+
+ }
+ }
+
+ private void injectMandatorInformation(
+ ImmutableAttributeMap.Builder attributeMap, IEidAuthData eidAuthData) {
+ String natMandatorId = eidAuthData.getGenericData(
+ MsEidasNodeConstants.ATTR_EIDAS_NAT_MANDATOR_PERSONAL_IDENTIFIER, String.class);
+
+ if (StringUtils.isNotEmpty(natMandatorId)) {
+ log.debug("Injecting natural mandator informations ... ");
+ final AttributeDefinition<?> attrDefPersonalId = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER).first();
+ final AttributeDefinition<?> attrDefFamilyName = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_CURRENTFAMILYNAME).first();
+ final AttributeDefinition<?> attrDefGivenName = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_CURRENTGIVENNAME).first();
+ final AttributeDefinition<?> attrDefDateOfBirth = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_DATEOFBIRTH).first();
+
+ attributeMap.put(attrDefPersonalId, natMandatorId);
+ attributeMap.put(attrDefFamilyName, eidAuthData.getGenericData(
+ PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_NAME, String.class));
+ attributeMap.put(attrDefGivenName, eidAuthData.getGenericData(
+ PvpAttributeDefinitions.MANDATE_NAT_PER_GIVEN_NAME_NAME, String.class));
+ attributeMap.put(attrDefDateOfBirth, eidAuthData.getGenericData(
+ PvpAttributeDefinitions.MANDATE_NAT_PER_BIRTHDATE_NAME, String.class));
+
+ } else {
+ log.debug("Injecting legal mandator informations ... ");
+ final AttributeDefinition<?> commonName = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_LEGALNAME).first();
+ final AttributeDefinition<?> legalPersonId = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_LEGALPERSONIDENTIFIER).first();
+
+ attributeMap.put(commonName, eidAuthData.getGenericData(
+ PvpAttributeDefinitions.MANDATE_LEG_PER_FULL_NAME_NAME, String.class));
+ attributeMap.put(legalPersonId, eidAuthData.getGenericData(
+ MsEidasNodeConstants.ATTR_EIDAS_JUR_MANDATOR_PERSONAL_IDENTIFIER, String.class));
+
+ }
+ }
+
+ private void injectRepesentativeInformation(
+ ImmutableAttributeMap.Builder attributeMap, IEidAuthData eidAuthData) {
+ final AttributeDefinition<?> attrDefPersonalId = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_REPRESENTATIVE_PERSONALIDENTIFIER).first();
+ final AttributeDefinition<?> attrDefFamilyName = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_REPRESENTATIVE_CURRENTFAMILYNAME).first();
+ final AttributeDefinition<?> attrDefGivenName = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_REPRESENTATIVE_CURRENTGIVENNAME).first();
+ final AttributeDefinition<?> attrDefDateOfBirth = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_REPRESENTATIVE_DATEOFBIRTH).first();
+
+ attributeMap.put(attrDefPersonalId,
+ eidAuthData.getGenericData(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, String.class));
+ attributeMap.put(attrDefFamilyName, eidAuthData.getFamilyName());
+ attributeMap.put(attrDefGivenName, eidAuthData.getGivenName());
+
+ //TODO: throw an error in case of SZR Date with month or day = "00"
+ attributeMap.put(attrDefDateOfBirth, eidAuthData.getDateOfBirth());
+
+ }
+
+ /**
+ * Work-around to inject representative information as nat. person subject to bypass eIDAS Node validation.
+ *
+ * <p><b>Injection will only be done if this work-around is enabled by configuration,
+ * the mandator is a legal person, and both legal and natural person subject's is requested.</b></p>
+ *
+ * @param attributeMap Attribute set for eIDAS response
+ * @param eidasReq Incoming eIDAS request
+ * @param authData Authentication data
+ */
+ private void injectJurPersonWorkaroundIfRequired(
+ ImmutableAttributeMap.Builder attributeMap, ILightRequest eidasReq, IAuthData authData) {
+ if (isLegalPersonWorkaroundActive() && isLegalPersonMandateAvailable(authData)
+ && EidasProxyServiceUtils.isNaturalPersonRequested(eidasReq)
+ && EidasProxyServiceUtils.isLegalPersonRequested(eidasReq)) {
+ log.debug("Injecting representative information as nat. person subject to bypass eIDAS Node validation");
+ attributeMap.putAll(buildAttributesWithoutMandate(authData));
+
+ }
+ }
+
+ private ImmutableAttributeMap buildAttributesWithoutMandate(IAuthData eidAuthData) {
+ //TODO: throw an error in case of SZR Date with month or day = "00"
+ return buildAttributesWithoutMandate(
+ eidAuthData.getGenericData(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER, String.class),
+ eidAuthData.getFamilyName(),
+ eidAuthData.getGivenName(),
+ eidAuthData.getDateOfBirth());
+
+ }
+
+ private ImmutableAttributeMap buildAttributesWithoutMandate(String personalIdentifier, String familyName,
+ String givenName, String dateOfBirth) {
+ final AttributeDefinition<?> attrDefPersonalId = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER).first();
+ final AttributeDefinition<?> attrDefFamilyName = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_CURRENTFAMILYNAME).first();
+ final AttributeDefinition<?> attrDefGivenName = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_CURRENTGIVENNAME).first();
+ final AttributeDefinition<?> attrDefDateOfBirth = attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_DATEOFBIRTH).first();
+
+ final ImmutableAttributeMap.Builder attributeMap =
+ ImmutableAttributeMap.builder()
+ .put(attrDefPersonalId, personalIdentifier)
+ .put(attrDefFamilyName, familyName)
+ .put(attrDefGivenName, givenName)
+ .put(attrDefDateOfBirth, dateOfBirth);
+
+ return attributeMap.build();
+
+ }
+
+ private BinaryLightToken putResponseInCommunicationCache(ILightResponse lightResponse)
+ throws ServletException {
+ final BinaryLightToken binaryLightToken;
+ try {
+ final SpecificCommunicationService springManagedSpecificConnectorCommunicationService =
+ (SpecificCommunicationService) context.getBean(
+ SpecificCommunicationDefinitionBeanNames.SPECIFIC_PROXYSERVICE_COMMUNICATION_SERVICE
+ .toString());
+
+ binaryLightToken = springManagedSpecificConnectorCommunicationService.putResponse(lightResponse);
+
+ } catch (final SpecificCommunicationException e) {
+ log.error("Unable to process specific request");
+ throw new ServletException(e);
+
+ }
+
+ return binaryLightToken;
+ }
+
+ private boolean isLegalPersonWorkaroundActive() {
+ return basicConfig.getBasicConfigurationBoolean(
+ MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_WORKAROUND_MANDATES_LEGAL_PERSON,
+ false);
+
+ }
+
+ private boolean isLegalPersonMandateAvailable(IAuthData authData) {
+ return StringUtils.isNoneEmpty(authData.getGenericData(
+ MsEidasNodeConstants.ATTR_EIDAS_JUR_MANDATOR_PERSONAL_IDENTIFIER, String.class));
+
+ }
+
+}
diff --git a/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServicePendingRequest.java b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServicePendingRequest.java
new file mode 100644
index 00000000..a3b5007a
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServicePendingRequest.java
@@ -0,0 +1,28 @@
+package at.asitplus.eidas.specific.modules.msproxyservice.protocol;
+
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+import at.gv.egiz.eaaf.core.impl.idp.controller.protocols.RequestImpl;
+import eu.eidas.auth.commons.light.ILightRequest;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * Pending-request of an authentication process from eIDAS Proxy-Service.
+ *
+ * @author tlenz
+ *
+ */
+@Component("ProxyServicePendingRequest")
+@Scope(value = BeanDefinition.SCOPE_PROTOTYPE)
+public class ProxyServicePendingRequest extends RequestImpl {
+
+ private static final long serialVersionUID = 4227378344716277935L;
+
+ @Getter
+ @Setter
+ ILightRequest eidasRequest;
+
+}
diff --git a/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/utils/EidasProxyServiceUtils.java b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/utils/EidasProxyServiceUtils.java
new file mode 100644
index 00000000..4cd7ba6c
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/utils/EidasProxyServiceUtils.java
@@ -0,0 +1,45 @@
+package at.asitplus.eidas.specific.modules.msproxyservice.utils;
+
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import eu.eidas.auth.commons.light.ILightRequest;
+
+/**
+ * Common utils for eIDAS Proxy-Service implementation.
+ *
+ * @author tlenz
+ *
+ */
+public class EidasProxyServiceUtils {
+
+ /**
+ * Check if legal person subject is requested by eIDAS Connector.
+ *
+ * @param eidasRequest Authentication request from eIDAS Connector.
+ * @return <code>true</code> if <i>LegalPersonIdentifier</i> is requested, otherwise <code>false</code>lse
+ */
+ public static boolean isLegalPersonRequested(ILightRequest eidasRequest) {
+ return eidasRequest.getRequestedAttributes().entrySet().stream()
+ .filter(el -> el.getKey().getFriendlyName().equals(Constants.eIDAS_ATTR_LEGALPERSONIDENTIFIER))
+ .findFirst()
+ .isPresent();
+
+ }
+
+ /**
+ * Check if natural person subject is requested by eIDAS Connector.
+ *
+ * @param eidasRequest Authentication request from eIDAS Connector.
+ * @return <code>true</code> if <i>PersonIdentifier</i> is requested, otherwise <code>false</code>lse
+ */
+ public static boolean isNaturalPersonRequested(ILightRequest eidasRequest) {
+ return eidasRequest.getRequestedAttributes().entrySet().stream()
+ .filter(el -> el.getKey().getFriendlyName().equals(Constants.eIDAS_ATTR_PERSONALIDENTIFIER))
+ .findFirst()
+ .isPresent();
+
+ }
+
+ private EidasProxyServiceUtils() {
+ //hide constructor for class with static methods only
+ }
+}
diff --git a/modules/eidas_proxy-sevice/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider b/modules/eidas_proxy-sevice/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider
new file mode 100644
index 00000000..9158d2e6
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider
@@ -0,0 +1 @@
+at.asitplus.eidas.specific.modules.msproxyservice.MsProxyServiceSpringResourceProvider \ No newline at end of file
diff --git a/modules/eidas_proxy-sevice/src/main/resources/messages/eidasproxy_messages.properties b/modules/eidas_proxy-sevice/src/main/resources/messages/eidasproxy_messages.properties
new file mode 100644
index 00000000..3f92d58a
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/main/resources/messages/eidasproxy_messages.properties
@@ -0,0 +1,14 @@
+eidas.proxyservice.01=General error on request-validation from national eIDAS Proxy-Service
+eidas.proxyservice.02=Authentication request contains not communication token.
+eidas.proxyservice.03=General error during eIDAS-Node communication. Reason: {}
+eidas.proxyservice.04=Validation of eIDAS Authn request failed. Reason: {}
+eidas.proxyservice.05=No eIDAS-Connector Issuer in Authn. request. Authentication not possible
+eidas.proxyservice.06=Can not build eIDAS Proxy-Service response. Authentication FAILED.
+eidas.proxyservice.07=Can not determine eIDAS-Connector CountryCode. Authentication not possible
+eidas.proxyservice.08=Validation of eIDAS Authn request failed. Reason: Legal person and natural person can not be requested at once.
+eidas.proxyservice.09=eIDAS authentication not possible, because legal person is requested but mandates are disabled in general
+eidas.proxyservice.10=eIDAS authentication not possible, because legal person is requested but not mandate profiles are defined
+eidas.proxyservice.11=No Authentication request with stated communication token.
+
+
+eidas.proxyservice.99=Internal error during eIDAS Proxy-Service authentication \ No newline at end of file
diff --git a/modules/eidas_proxy-sevice/src/main/resources/spring/eidas_proxy-service.beans.xml b/modules/eidas_proxy-sevice/src/main/resources/spring/eidas_proxy-service.beans.xml
new file mode 100644
index 00000000..2055b5a9
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/main/resources/spring/eidas_proxy-service.beans.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:tx="http://www.springframework.org/schema/tx"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
+ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
+
+ <context:annotation-config />
+
+ <bean id="ProxyServicePendingRequest"
+ class="at.asitplus.eidas.specific.modules.msproxyservice.protocol.ProxyServicePendingRequest"
+ scope="prototype"/>
+
+ <bean id="ProxyServiceAuthenticationAction"
+ class="at.asitplus.eidas.specific.modules.msproxyservice.protocol.ProxyServiceAuthenticationAction"/>
+
+ <bean id="msSpecificProxyController"
+ class="at.asitplus.eidas.specific.modules.msproxyservice.protocol.EidasProxyServiceController"/>
+
+ <bean id="eidasProxyMessageSource"
+ class="at.asitplus.eidas.specific.modules.msproxyservice.EidasProxyMessageSource"/>
+
+
+</beans> \ No newline at end of file
diff --git a/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/EidasProxyMessageSourceTest.java b/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/EidasProxyMessageSourceTest.java
new file mode 100644
index 00000000..efe572b5
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/EidasProxyMessageSourceTest.java
@@ -0,0 +1,50 @@
+package at.asitplus.eidas.specific.modules.auth.idaustria.test;
+
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import at.asitplus.eidas.specific.modules.msproxyservice.EidasProxyMessageSource;
+import at.gv.egiz.eaaf.core.api.logging.IMessageSourceLocation;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = {
+ "/spring/SpringTest-context_basic_test.xml",
+ "/spring/SpringTest-context_basic_mapConfig.xml",
+ })
+public class EidasProxyMessageSourceTest {
+
+ @Autowired
+ private ResourceLoader loader;
+ @Autowired(required = false)
+ private List<IMessageSourceLocation> messageSources;
+
+ @Test
+ public void checkMessageSources() {
+ Assert.assertNotNull("No messageSource", messageSources);
+ Assert.assertFalse("No message source", messageSources.isEmpty());
+
+ boolean found = false;
+
+ for (final IMessageSourceLocation messageSource : messageSources) {
+ found = found ? found : messageSource instanceof EidasProxyMessageSource;
+
+ Assert.assertNotNull("No sourcePath", messageSource.getMessageSourceLocation());
+ for (final String el : messageSource.getMessageSourceLocation()) {
+ final Resource messages = loader.getResource(el + ".properties");
+ Assert.assertTrue("Source not exist", messages.exists());
+
+ }
+ }
+
+ Assert.assertTrue("Internal messagesource not found", found);
+
+ }
+}
diff --git a/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/MsProxyServiceSpringResourceProviderTest.java b/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/MsProxyServiceSpringResourceProviderTest.java
new file mode 100644
index 00000000..8c6da366
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/MsProxyServiceSpringResourceProviderTest.java
@@ -0,0 +1,56 @@
+package at.asitplus.eidas.specific.modules.auth.idaustria.test;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.BlockJUnit4ClassRunner;
+import org.springframework.core.io.Resource;
+
+import at.asitplus.eidas.specific.modules.msproxyservice.MsProxyServiceSpringResourceProvider;
+import at.gv.egiz.eaaf.core.test.TestConstants;
+
+
+
+@RunWith(BlockJUnit4ClassRunner.class)
+public class MsProxyServiceSpringResourceProviderTest {
+
+ @Test
+ public void testSpringConfig() {
+ final MsProxyServiceSpringResourceProvider test =
+ new MsProxyServiceSpringResourceProvider();
+ for (final Resource el : test.getResourcesToLoad()) {
+ try {
+ IOUtils.toByteArray(el.getInputStream());
+
+ } catch (final IOException e) {
+ Assert.fail("Ressouce: " + el.getFilename() + " not found");
+ }
+
+ }
+
+ Assert.assertNotNull("no Name", test.getName());
+ Assert.assertNull("Find package definitions", test.getPackagesToScan());
+
+ }
+
+ @Test
+ public void testSpILoaderConfig() {
+ final InputStream el = this.getClass().getResourceAsStream(TestConstants.TEST_SPI_LOADER_PATH);
+ try {
+ final String spiFile = IOUtils.toString(el, "UTF-8");
+
+ Assert.assertEquals("Wrong classpath in SPI file",
+ MsProxyServiceSpringResourceProvider.class.getName(), spiFile);
+
+
+ } catch (final IOException e) {
+ Assert.fail("Ressouce: " + TestConstants.TEST_SPI_LOADER_PATH + " not found");
+
+ }
+ }
+
+}
diff --git a/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/protocol/EidasProxyServiceControllerTest.java b/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/protocol/EidasProxyServiceControllerTest.java
new file mode 100644
index 00000000..55958d9e
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/protocol/EidasProxyServiceControllerTest.java
@@ -0,0 +1,666 @@
+package at.asitplus.eidas.specific.modules.auth.idaustria.test.protocol;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URLDecoder;
+import java.text.MessageFormat;
+import java.util.Arrays;
+import java.util.List;
+import java.util.UUID;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opensaml.saml.saml2.core.NameIDType;
+import org.opensaml.saml.saml2.core.StatusCode;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+import org.springframework.web.servlet.config.annotation.EnableWebMvc;
+
+import com.google.common.collect.ImmutableSortedSet;
+
+import at.asitplus.eidas.specific.core.config.ServiceProviderConfiguration;
+import at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummyConfigMap;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.EidasAttributeRegistry;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.CreateIdentityLinkTask;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.test.dummy.DummySpecificCommunicationService;
+import at.asitplus.eidas.specific.modules.msproxyservice.MsProxyServiceConstants;
+import at.asitplus.eidas.specific.modules.msproxyservice.exception.EidasProxyServiceException;
+import at.asitplus.eidas.specific.modules.msproxyservice.protocol.EidasProxyServiceController;
+import at.asitplus.eidas.specific.modules.msproxyservice.protocol.ProxyServicePendingRequest;
+import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions.SpMandateModes;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.exceptions.EaafStorageException;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.DummyProtocolAuthService;
+import eu.eidas.auth.commons.EidasParameterKeys;
+import eu.eidas.auth.commons.attribute.ImmutableAttributeMap;
+import eu.eidas.auth.commons.light.ILightResponse;
+import eu.eidas.auth.commons.light.impl.LightRequest;
+import eu.eidas.specificcommunication.SpecificCommunicationDefinitionBeanNames;
+import eu.eidas.specificcommunication.exception.SpecificCommunicationException;
+import eu.eidas.specificcommunication.protocol.SpecificCommunicationService;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@PrepareForTest(CreateIdentityLinkTask.class)
+@ContextConfiguration(locations = {
+ "/spring/SpringTest-context_basic_test.xml",
+ "/spring/SpringTest-context_basic_mapConfig.xml",
+ })
+@EnableWebMvc
+public class EidasProxyServiceControllerTest {
+
+ @Autowired private EidasProxyServiceController controller;
+
+ @Autowired private DummySpecificCommunicationService proxyService;
+ @Autowired private DummyProtocolAuthService authService;
+ @Autowired private EidasAttributeRegistry attrRegistry;
+ @Autowired private ApplicationContext context;
+
+ @Autowired MsConnectorDummyConfigMap config;
+
+ private MockHttpServletRequest httpReq;
+ private MockHttpServletResponse httpResp;
+
+ private SpecificCommunicationService springManagedSpecificConnectorCommunicationService;
+
+ /**
+ * jUnit test set-up.
+ */
+ @Before
+ public void setUp() throws EaafStorageException, URISyntaxException {
+ httpReq = new MockHttpServletRequest("POST", "http://localhost/ms_connector/eidas/light/idp/redirect");
+ httpResp = new MockHttpServletResponse();
+ RequestContextHolder.resetRequestAttributes();
+ RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpReq, httpResp));
+
+ proxyService.setiLightRequest(null);
+ proxyService.setError(null);
+
+ config.putConfigValue("eidas.ms.auth.eIDAS.node_v2.proxy.forward.endpoint",
+ "http://eidas.proxy/endpoint");
+
+ springManagedSpecificConnectorCommunicationService =
+ (SpecificCommunicationService) context.getBean(
+ SpecificCommunicationDefinitionBeanNames.SPECIFIC_PROXYSERVICE_COMMUNICATION_SERVICE
+ .toString());
+
+ }
+
+ @Test
+ public void generateErrorResponseWrongPendingReq() throws Throwable {
+ Assert.assertFalse("wrong statusCode", controller.generateErrorMessage(
+ new EaafException("1000"),
+ httpReq, httpResp, null));
+
+ }
+
+ @Test
+ public void generateErrorResponse() throws Throwable {
+ ProxyServicePendingRequest pendingReq = new ProxyServicePendingRequest();
+ pendingReq.initialize(httpReq, config);
+
+ LightRequest.Builder eidasRequestBuilder = LightRequest.builder()
+ .id(UUID.randomUUID().toString())
+ .issuer(RandomStringUtils.randomAlphabetic(10))
+ .citizenCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH)
+ .spCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .spType("public")
+ .requesterId(RandomStringUtils.randomAlphanumeric(10))
+ .providerName(RandomStringUtils.randomAlphanumeric(10));
+ pendingReq.setEidasRequest(eidasRequestBuilder.build());
+
+
+ // execute test
+ Assert.assertTrue("wrong statusCode", controller.generateErrorMessage(
+ new EaafException("1000"),
+ httpReq, httpResp,
+ pendingReq));
+
+ // validate state
+ assertNotNull("not redirct Header", httpResp.getHeader("Location"));
+ assertTrue("wrong redirect URL", httpResp.getHeader("Location").startsWith("http://eidas.proxy/endpoint?token="));
+ String token = httpResp.getHeader("Location").substring("http://eidas.proxy/endpoint?token=".length());
+
+ ILightResponse resp = springManagedSpecificConnectorCommunicationService.getAndRemoveResponse(URLDecoder.decode(token, "UTF-8"),
+ ImmutableSortedSet.copyOf(attrRegistry.getCoreAttributeRegistry().getAttributes()));
+
+ assertNotNull("responseId", resp.getId());
+ assertEquals("inResponseTo", pendingReq.getEidasRequest().getId(), resp.getInResponseToId());
+ assertEquals("relayState", pendingReq.getEidasRequest().getRelayState(), resp.getRelayState());
+
+ assertNotNull("subjectNameId", resp.getSubject());
+ assertEquals("subjectNameIdFormat", NameIDType.TRANSIENT, resp.getSubjectNameIdFormat());
+ assertTrue("not attributes", resp.getAttributes().isEmpty());
+
+ assertEquals("StatusCode", StatusCode.RESPONDER, resp.getStatus().getStatusCode());
+ //assertEquals("SubStatusCode", "", resp.getStatus().getSubStatusCode());
+ //assertEquals("StatusMsg", "", resp.getStatus().getStatusMessage());
+
+ }
+
+ @Test
+ public void missingEidasToken() {
+ EidasProxyServiceException exception = assertThrows(EidasProxyServiceException.class,
+ () -> controller.receiveEidasAuthnRequest(httpReq, httpResp));
+ Assert.assertEquals("wrong errorCode", "eidas.proxyservice.02", exception.getErrorId());
+
+ }
+
+ @Test
+ public void wrongEidasTokenWithNullpointerException() {
+ //initialize state
+ httpReq.addParameter(EidasParameterKeys.TOKEN.toString(), RandomStringUtils.randomAlphanumeric(10));
+
+ //validate state
+ EidasProxyServiceException exception = assertThrows(EidasProxyServiceException.class,
+ () -> controller.receiveEidasAuthnRequest(httpReq, httpResp));
+ Assert.assertEquals("wrong errorCode", "eidas.proxyservice.11", exception.getErrorId());
+
+ }
+
+ @Test
+ public void wrongEidasTokenCacheCommunicationError() {
+ //initialize state
+ httpReq.addParameter(EidasParameterKeys.TOKEN.toString(), RandomStringUtils.randomAlphanumeric(10));
+ proxyService.setError(new SpecificCommunicationException(RandomStringUtils.randomAlphanumeric(10)));
+
+ //validate state
+ EidasProxyServiceException exception = assertThrows(EidasProxyServiceException.class,
+ () -> controller.receiveEidasAuthnRequest(httpReq, httpResp));
+ Assert.assertEquals("wrong errorCode", "eidas.proxyservice.03", exception.getErrorId());
+ Assert.assertTrue("Wrong exception", (exception.getCause() instanceof SpecificCommunicationException));
+
+ }
+
+ @Test
+ public void missingServiceProviderCountry() {
+ //initialize state
+ httpReq.addParameter(EidasParameterKeys.TOKEN.toString(), RandomStringUtils.randomAlphanumeric(10));
+ LightRequest.Builder authnReqBuilder = LightRequest.builder()
+ .id(UUID.randomUUID().toString())
+ .issuer(RandomStringUtils.randomAlphabetic(10))
+ .citizenCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH);
+
+ proxyService.setiLightRequest(authnReqBuilder.build());
+
+ //validate state
+ EidasProxyServiceException exception = assertThrows(EidasProxyServiceException.class,
+ () -> controller.receiveEidasAuthnRequest(httpReq, httpResp));
+ Assert.assertEquals("wrong errorCode", "eidas.proxyservice.07", exception.getErrorId());
+
+ }
+
+ @Test
+ public void requestingLegalAndNaturalPerson() {
+ //initialize state
+ httpReq.addParameter(EidasParameterKeys.TOKEN.toString(), RandomStringUtils.randomAlphanumeric(10));
+ LightRequest.Builder authnReqBuilder = LightRequest.builder()
+ .id(UUID.randomUUID().toString())
+ .issuer(RandomStringUtils.randomAlphabetic(10))
+ .citizenCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .spCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH)
+ .requestedAttributes(ImmutableAttributeMap.builder()
+ .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER).first())
+ .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_LEGALPERSONIDENTIFIER).first())
+ .build());
+
+ proxyService.setiLightRequest(authnReqBuilder.build());
+
+ //validate state
+ EidasProxyServiceException exception = assertThrows(EidasProxyServiceException.class,
+ () -> controller.receiveEidasAuthnRequest(httpReq, httpResp));
+ Assert.assertEquals("wrong errorCode", "eidas.proxyservice.08", exception.getErrorId());
+
+ }
+
+ @Test
+ public void requestLegalPersonButNoMandates() throws IOException, EaafException {
+ //initialize state
+ httpReq.addParameter(EidasParameterKeys.TOKEN.toString(), RandomStringUtils.randomAlphanumeric(10));
+ String spCountryCode = RandomStringUtils.randomAlphabetic(2).toUpperCase();
+ LightRequest.Builder authnReqBuilder = LightRequest.builder()
+ .id(UUID.randomUUID().toString())
+ .issuer(RandomStringUtils.randomAlphabetic(10))
+ .citizenCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH)
+ .spCountryCode(spCountryCode)
+ .spType("public")
+ .requestedAttributes(ImmutableAttributeMap.builder()
+ .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_LEGALPERSONIDENTIFIER).first()).build());
+
+ proxyService.setiLightRequest(authnReqBuilder.build());
+
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_ENABLED, "false");
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_NATURAL,
+ StringUtils.join(Arrays.asList(
+ RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5)), ","));
+
+ //validate state
+ EidasProxyServiceException exception = assertThrows(EidasProxyServiceException.class,
+ () -> controller.receiveEidasAuthnRequest(httpReq, httpResp));
+ Assert.assertEquals("wrong errorCode", "eidas.proxyservice.09", exception.getErrorId());
+
+ }
+
+ @Test
+ public void validAuthnRequest() throws IOException, EaafException {
+ //initialize state
+ httpReq.addParameter(EidasParameterKeys.TOKEN.toString(), RandomStringUtils.randomAlphanumeric(10));
+ String spCountryCode = RandomStringUtils.randomAlphabetic(2).toUpperCase();
+ LightRequest.Builder authnReqBuilder = LightRequest.builder()
+ .id(UUID.randomUUID().toString())
+ .issuer(RandomStringUtils.randomAlphabetic(10))
+ .citizenCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH)
+ .spCountryCode(spCountryCode)
+ .spType("public")
+ .requestedAttributes(ImmutableAttributeMap.builder()
+ .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER).first()).build());
+
+ proxyService.setiLightRequest(authnReqBuilder.build());
+
+
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_ENABLED, "false");
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_NATURAL,
+ StringUtils.join(Arrays.asList(
+ RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5)), ","));
+
+
+ //execute
+ controller.receiveEidasAuthnRequest(httpReq, httpResp);
+
+ //validate state
+ Assert.assertNotNull("pendingRequest", authService.getPendingReq());
+ Assert.assertTrue("wrong pendingRequest", authService.getPendingReq() instanceof ProxyServicePendingRequest);
+ ProxyServicePendingRequest pendingReq = (ProxyServicePendingRequest) authService.getPendingReq();
+ Assert.assertNotNull("missing uniqueSpId", pendingReq.getSpEntityId());
+ Assert.assertNotNull("missing eidasReq", pendingReq.getEidasRequest());
+
+ Assert.assertFalse("isPassive", pendingReq.isPassiv());
+ Assert.assertTrue("isPassive", pendingReq.forceAuth());
+ Assert.assertFalse("isPassive", pendingReq.isAuthenticated());
+ Assert.assertFalse("isPassive", pendingReq.isAbortedByUser());
+ Assert.assertTrue("isPassive", pendingReq.isNeedAuthentication());
+
+ Assert.assertNotNull("missing spConfig", pendingReq.getServiceProviderConfiguration());
+ ServiceProviderConfiguration spConfig =
+ pendingReq.getServiceProviderConfiguration(ServiceProviderConfiguration.class);
+ Assert.assertNotNull("uniqueId", spConfig.getUniqueIdentifier());
+ Assert.assertEquals("uniqueId wrong pattern",
+ authnReqBuilder.build().getIssuer(),
+ spConfig.getUniqueIdentifier());
+ Assert.assertEquals("friendlyName wrong pattern",
+ MessageFormat.format(MsProxyServiceConstants.TEMPLATE_SP_UNIQUE_ID, spCountryCode, "public"),
+ spConfig.getFriendlyName());
+
+ Assert.assertEquals("uniqueId not match to pendingReq",
+ pendingReq.getSpEntityId(), spConfig.getUniqueIdentifier());
+ Assert.assertNotNull("bpkTarget", spConfig.getAreaSpecificTargetIdentifier());
+ Assert.assertEquals("wrong bPK Target",
+ EaafConstants.URN_PREFIX_EIDAS + "AT+" + spCountryCode,
+ spConfig.getAreaSpecificTargetIdentifier());
+
+ assertNotNull("mandateprofiles", spConfig.getMandateProfiles());
+ assertTrue("mandateprofiles not empty", spConfig.getMandateProfiles().isEmpty());
+ assertEquals("MandateMode", SpMandateModes.NONE, spConfig.getMandateMode());
+
+ }
+
+ @Test
+ public void validAuthnRequestWithMandatesDefaultProfilesNat() throws IOException, EaafException {
+ //initialize state
+ httpReq.addParameter(EidasParameterKeys.TOKEN.toString(), RandomStringUtils.randomAlphanumeric(10));
+ String spCountryCode = RandomStringUtils.randomAlphabetic(2).toUpperCase();
+ LightRequest.Builder authnReqBuilder = LightRequest.builder()
+ .id(UUID.randomUUID().toString())
+ .issuer(RandomStringUtils.randomAlphabetic(10))
+ .citizenCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH)
+ .spCountryCode(spCountryCode)
+ .spType("public")
+ .requestedAttributes(ImmutableAttributeMap.builder()
+ .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER).first()).build());
+
+
+ proxyService.setiLightRequest(authnReqBuilder.build());
+
+ List<String> mandateProfilesNat =
+ Arrays.asList(RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5));
+ List<String> mandateProfilesJur =
+ Arrays.asList(RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5));
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_ENABLED, "true");
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_NATURAL,
+ StringUtils.join(mandateProfilesNat, ","));
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_LEGAL,
+ StringUtils.join(mandateProfilesJur, ","));
+
+ //execute
+ controller.receiveEidasAuthnRequest(httpReq, httpResp);
+
+ //validate state
+ ServiceProviderConfiguration spConfig =
+ authService.getPendingReq().getServiceProviderConfiguration(ServiceProviderConfiguration.class);
+ assertNotNull("mandateprofiles", spConfig.getMandateProfiles());
+ assertFalse("mandateprofiles not empty", spConfig.getMandateProfiles().isEmpty());
+ assertEquals("mandateprofile size", mandateProfilesNat.size(), spConfig.getMandateProfiles().size());
+ spConfig.getMandateProfiles().stream()
+ .forEach(el -> assertTrue("missing mandateProfile: " + el, mandateProfilesNat.contains(el)));
+ assertEquals("MandateMode", SpMandateModes.NATURAL, spConfig.getMandateMode());
+
+ }
+
+ @Test
+ public void validAuthnRequestWithMandatesDefaultProfilesJur() throws IOException, EaafException {
+ //initialize state
+ httpReq.addParameter(EidasParameterKeys.TOKEN.toString(), RandomStringUtils.randomAlphanumeric(10));
+ String spCountryCode = RandomStringUtils.randomAlphabetic(2).toUpperCase();
+ LightRequest.Builder authnReqBuilder = LightRequest.builder()
+ .id(UUID.randomUUID().toString())
+ .issuer(RandomStringUtils.randomAlphabetic(10))
+ .citizenCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH)
+ .spCountryCode(spCountryCode)
+ .spType("public")
+ .requestedAttributes(ImmutableAttributeMap.builder()
+ .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_LEGALPERSONIDENTIFIER).first()).build());
+
+
+ proxyService.setiLightRequest(authnReqBuilder.build());
+
+ List<String> mandateProfilesNat =
+ Arrays.asList(RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5));
+ List<String> mandateProfilesJur =
+ Arrays.asList(RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5));
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_ENABLED, "true");
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_NATURAL,
+ StringUtils.join(mandateProfilesNat, ","));
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_LEGAL,
+ StringUtils.join(mandateProfilesJur, ","));
+
+ //execute
+ controller.receiveEidasAuthnRequest(httpReq, httpResp);
+
+ //validate state
+ ServiceProviderConfiguration spConfig =
+ authService.getPendingReq().getServiceProviderConfiguration(ServiceProviderConfiguration.class);
+ assertNotNull("mandateprofiles", spConfig.getMandateProfiles());
+ assertFalse("mandateprofiles not empty", spConfig.getMandateProfiles().isEmpty());
+ assertEquals("mandateprofile size", mandateProfilesJur.size(), spConfig.getMandateProfiles().size());
+ spConfig.getMandateProfiles().stream()
+ .forEach(el -> assertTrue("missing mandateProfile: " + el, mandateProfilesJur.contains(el)));
+ assertEquals("MandateMode", SpMandateModes.LEGAL_FORCE, spConfig.getMandateMode());
+
+ }
+
+ @Test
+ public void validAuthnRequestWithMandatesDefaultNoJurProfiles() throws IOException, EaafException {
+ //initialize state
+ httpReq.addParameter(EidasParameterKeys.TOKEN.toString(), RandomStringUtils.randomAlphanumeric(10));
+ String spCountryCode = RandomStringUtils.randomAlphabetic(2).toUpperCase();
+ LightRequest.Builder authnReqBuilder = LightRequest.builder()
+ .id(UUID.randomUUID().toString())
+ .issuer(RandomStringUtils.randomAlphabetic(10))
+ .citizenCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH)
+ .spCountryCode(spCountryCode)
+ .spType("public")
+ .requestedAttributes(ImmutableAttributeMap.builder()
+ .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_LEGALPERSONIDENTIFIER).first()).build());
+
+
+ proxyService.setiLightRequest(authnReqBuilder.build());
+
+ List<String> mandateProfilesNat =
+ Arrays.asList(RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5));
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_ENABLED, "true");
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_NATURAL,
+ StringUtils.join(mandateProfilesNat, ","));
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_LEGAL, "");
+
+ //validate state
+ EidasProxyServiceException exception = assertThrows(EidasProxyServiceException.class,
+ () -> controller.receiveEidasAuthnRequest(httpReq, httpResp));
+ Assert.assertEquals("wrong errorCode", "eidas.proxyservice.10", exception.getErrorId());
+
+ }
+
+ @Test
+ public void validAuthnRequestWithMandatesDefaultNoNatProfiles() throws IOException, EaafException {
+ //initialize state
+ httpReq.addParameter(EidasParameterKeys.TOKEN.toString(), RandomStringUtils.randomAlphanumeric(10));
+ String spCountryCode = RandomStringUtils.randomAlphabetic(2).toUpperCase();
+ LightRequest.Builder authnReqBuilder = LightRequest.builder()
+ .id(UUID.randomUUID().toString())
+ .issuer(RandomStringUtils.randomAlphabetic(10))
+ .citizenCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH)
+ .spCountryCode(spCountryCode)
+ .spType("public")
+ .requestedAttributes(ImmutableAttributeMap.builder()
+ .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER).first()).build());
+
+
+ proxyService.setiLightRequest(authnReqBuilder.build());
+
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_ENABLED, "true");
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_NATURAL, "");
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_LEGAL, "");
+
+ //execute
+ controller.receiveEidasAuthnRequest(httpReq, httpResp);
+
+ //validate state
+ ServiceProviderConfiguration spConfig =
+ authService.getPendingReq().getServiceProviderConfiguration(ServiceProviderConfiguration.class);
+ assertNotNull("mandateprofiles", spConfig.getMandateProfiles());
+ assertTrue("mandateprofiles not empty", spConfig.getMandateProfiles().isEmpty());
+ assertEquals("MandateMode", SpMandateModes.NONE, spConfig.getMandateMode());
+
+ }
+
+ @Test
+ public void validAuthnRequestIssueSpecificNoMandates() throws IOException, EaafException {
+ //initialize state
+ httpReq.addParameter(EidasParameterKeys.TOKEN.toString(), RandomStringUtils.randomAlphanumeric(10));
+
+ String issuer = RandomStringUtils.randomAlphabetic(10);
+ LightRequest.Builder authnReqBuilder = LightRequest.builder()
+ .id(UUID.randomUUID().toString())
+ .issuer(issuer)
+ .citizenCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH)
+ .spCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .spType("public")
+ .requestedAttributes(ImmutableAttributeMap.builder()
+ .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER).first()).build());
+
+ proxyService.setiLightRequest(authnReqBuilder.build());
+
+
+ // set default mandate configuration
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_ENABLED, "true");
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_NATURAL,
+ StringUtils.join(Arrays.asList(
+ RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5)), ","));
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_LEGAL,
+ StringUtils.join(Arrays.asList(
+ RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5)), ","));
+
+ // set specific mandate configuration
+ String spCountryCode = RandomStringUtils.randomAlphabetic(2).toUpperCase();
+ addConnectorConfig(0, MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_UNIQUEID, issuer);
+ addConnectorConfig(0, MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_COUNTRYCODE, spCountryCode);
+ addConnectorConfig(0, MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_MANDATES_ENABLED, "false");
+
+ List<String> mandateProfiles =
+ Arrays.asList(RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5));
+ addConnectorConfig(0, MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_MANDATES_PROFILE_NATURAL,
+ StringUtils.join(mandateProfiles, ","));
+ addConnectorConfig(0, MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_MANDATES_PROFILE_LEGAL,
+ StringUtils.join(Arrays.asList(RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5)), ","));
+
+ //execute
+ controller.receiveEidasAuthnRequest(httpReq, httpResp);
+
+ //validate state
+ ServiceProviderConfiguration spConfig =
+ authService.getPendingReq().getServiceProviderConfiguration(ServiceProviderConfiguration.class);
+ assertNotNull("mandateprofiles", spConfig.getMandateProfiles());
+ assertTrue("mandateprofiles not empty", spConfig.getMandateProfiles().isEmpty());
+ assertEquals("MandateMode", SpMandateModes.NONE, spConfig.getMandateMode());
+
+ }
+
+ @Test
+ public void validAuthnRequestIssueSpecificMandatesNat() throws IOException, EaafException {
+ //initialize state
+ httpReq.addParameter(EidasParameterKeys.TOKEN.toString(), RandomStringUtils.randomAlphanumeric(10));
+
+ String issuer = "https://apps.egiz.gv.at/EidasNode//ConnectorMetadata";
+ LightRequest.Builder authnReqBuilder = LightRequest.builder()
+ .id(UUID.randomUUID().toString())
+ .issuer(issuer)
+ .citizenCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH)
+ .spCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .spType("public")
+ .requestedAttributes(ImmutableAttributeMap.builder()
+ .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_PERSONALIDENTIFIER).first()).build());
+
+ proxyService.setiLightRequest(authnReqBuilder.build());
+
+
+ // set default mandate configuration
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_ENABLED, "false");
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_NATURAL,
+ StringUtils.join(Arrays.asList(
+ RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5)), ","));
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_LEGAL,
+ StringUtils.join(Arrays.asList(
+ RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5)), ","));
+
+ // set specific mandate configuration
+ String spCountryCode = RandomStringUtils.randomAlphabetic(2).toUpperCase();
+ addConnectorConfig(0, MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_UNIQUEID, issuer);
+ addConnectorConfig(0, MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_COUNTRYCODE, spCountryCode);
+ addConnectorConfig(0, MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_MANDATES_ENABLED, "true");
+
+ List<String> mandateProfiles =
+ Arrays.asList(RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5));
+ addConnectorConfig(0, MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_MANDATES_PROFILE_NATURAL,
+ StringUtils.join(mandateProfiles, ","));
+ addConnectorConfig(0, MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_MANDATES_PROFILE_LEGAL,
+ StringUtils.join(Arrays.asList(RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5)), ","));
+
+ //execute
+ controller.receiveEidasAuthnRequest(httpReq, httpResp);
+
+ //validate state
+ ServiceProviderConfiguration spConfig =
+ authService.getPendingReq().getServiceProviderConfiguration(ServiceProviderConfiguration.class);
+ assertNotNull("mandateprofiles", spConfig.getMandateProfiles());
+ assertFalse("mandateprofiles not empty", spConfig.getMandateProfiles().isEmpty());
+ assertEquals("mandateprofile size", mandateProfiles.size(), spConfig.getMandateProfiles().size());
+ spConfig.getMandateProfiles().stream()
+ .forEach(el -> assertTrue("missing mandateProfile: " + el, mandateProfiles.contains(el)));
+ assertEquals("MandateMode", SpMandateModes.NATURAL, spConfig.getMandateMode());
+
+ }
+
+ @Test
+ public void validAuthnRequestIssueSpecificMandatesJur() throws IOException, EaafException {
+ //initialize state
+ httpReq.addParameter(EidasParameterKeys.TOKEN.toString(), RandomStringUtils.randomAlphanumeric(10));
+
+ String issuer = RandomStringUtils.randomAlphabetic(10);
+ LightRequest.Builder authnReqBuilder = LightRequest.builder()
+ .id(UUID.randomUUID().toString())
+ .issuer(issuer)
+ .citizenCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH)
+ .spCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .spType("public")
+ .requestedAttributes(ImmutableAttributeMap.builder()
+ .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(
+ Constants.eIDAS_ATTR_LEGALPERSONIDENTIFIER).first()).build());
+
+ proxyService.setiLightRequest(authnReqBuilder.build());
+
+
+ // set default mandate configuration
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_ENABLED, "true");
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_NATURAL,
+ StringUtils.join(Arrays.asList(
+ RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5)), ","));
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_EIDAS_PROXY_MANDATES_PROFILE_DEFAULT_LEGAL,
+ StringUtils.join(Arrays.asList(
+ RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5)), ","));
+
+ // set specific mandate configuration
+ String spCountryCode = RandomStringUtils.randomAlphabetic(2).toUpperCase();
+ addConnectorConfig(0, MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_UNIQUEID, issuer);
+ addConnectorConfig(0, MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_COUNTRYCODE, spCountryCode);
+ addConnectorConfig(0, MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_MANDATES_ENABLED, "true");
+
+ List<String> mandateProfiles =
+ Arrays.asList(RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5));
+ addConnectorConfig(0, MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_MANDATES_PROFILE_LEGAL,
+ StringUtils.join(mandateProfiles, ","));
+ addConnectorConfig(0, MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_MANDATES_PROFILE_NATURAL,
+ StringUtils.join(Arrays.asList(RandomStringUtils.randomAlphabetic(5), RandomStringUtils.randomAlphabetic(5)), ","));
+
+ //execute
+ controller.receiveEidasAuthnRequest(httpReq, httpResp);
+
+ //validate state
+ ServiceProviderConfiguration spConfig =
+ authService.getPendingReq().getServiceProviderConfiguration(ServiceProviderConfiguration.class);
+ assertNotNull("mandateprofiles", spConfig.getMandateProfiles());
+ assertFalse("mandateprofiles not empty", spConfig.getMandateProfiles().isEmpty());
+ assertEquals("mandateprofile size", mandateProfiles.size(), spConfig.getMandateProfiles().size());
+ spConfig.getMandateProfiles().stream()
+ .forEach(el -> assertTrue("missing mandateProfile: " + el, mandateProfiles.contains(el)));
+ assertEquals("MandateMode", SpMandateModes.LEGAL_FORCE, spConfig.getMandateMode());
+
+ }
+
+ private void addConnectorConfig(int i, String key, String value) {
+ config.putConfigValue(MsProxyServiceConstants.CONIG_PROPS_CONNECTOR_PREFIX + String.valueOf(i) + "." + key,
+ value);
+
+ }
+
+}
+
+
diff --git a/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/protocol/ProxyServiceAuthenticationActionTest.java b/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/protocol/ProxyServiceAuthenticationActionTest.java
new file mode 100644
index 00000000..52cc01d4
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/protocol/ProxyServiceAuthenticationActionTest.java
@@ -0,0 +1,637 @@
+package at.asitplus.eidas.specific.modules.auth.idaustria.test.protocol;
+
+import static at.asitplus.eidas.specific.core.MsEidasNodeConstants.PROP_CONFIG_SP_NEW_EID_MODE;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+import java.net.URISyntaxException;
+import java.net.URLDecoder;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.joda.time.DateTime;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opensaml.saml.saml2.core.NameIDType;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import com.google.common.collect.ImmutableSortedSet;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummyConfigMap;
+import at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummySpConfiguration;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.EidasAttributeRegistry;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.CreateIdentityLinkTask;
+import at.asitplus.eidas.specific.modules.msproxyservice.protocol.ProxyServiceAuthenticationAction;
+import at.asitplus.eidas.specific.modules.msproxyservice.protocol.ProxyServicePendingRequest;
+import at.gv.egiz.eaaf.core.api.data.EaafConfigConstants;
+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.data.PvpAttributeDefinitions.EidIdentityStatusLevelValues;
+import at.gv.egiz.eaaf.core.api.idp.IAuthData;
+import at.gv.egiz.eaaf.core.api.idp.IEidAuthData;
+import at.gv.egiz.eaaf.core.api.idp.auth.data.IIdentityLink;
+import at.gv.egiz.eaaf.core.api.idp.slo.SloInformationInterface;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl;
+import eu.eidas.auth.commons.attribute.AttributeDefinition;
+import eu.eidas.auth.commons.attribute.ImmutableAttributeMap;
+import eu.eidas.auth.commons.light.ILightResponse;
+import eu.eidas.auth.commons.light.impl.LightRequest;
+import eu.eidas.auth.commons.light.impl.LightRequest.Builder;
+import eu.eidas.specificcommunication.SpecificCommunicationDefinitionBeanNames;
+import eu.eidas.specificcommunication.exception.SpecificCommunicationException;
+import eu.eidas.specificcommunication.protocol.SpecificCommunicationService;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@PrepareForTest(CreateIdentityLinkTask.class)
+@ContextConfiguration(locations = {
+ "/spring/SpringTest-context_basic_test.xml",
+ "/spring/SpringTest-context_basic_mapConfig.xml",
+ })
+public class ProxyServiceAuthenticationActionTest {
+
+ @Autowired private MsConnectorDummyConfigMap basicConfig;
+ @Autowired private ProxyServiceAuthenticationAction action;
+ @Autowired private ApplicationContext context;
+ @Autowired EidasAttributeRegistry attrRegistry;
+
+ private MockHttpServletRequest httpReq;
+ private MockHttpServletResponse httpResp;
+ private ProxyServicePendingRequest pendingReq;
+ private MsConnectorDummySpConfiguration oaParam;
+ private SpecificCommunicationService springManagedSpecificConnectorCommunicationService;
+
+
+ /**
+ * jUnit test set-up.
+ * @throws EaafException In case of an error
+ */
+ @Before
+ public void setUp() throws URISyntaxException, EaafException {
+ httpReq = new MockHttpServletRequest("POST", "https://localhost/authhandler");
+ httpResp = new MockHttpServletResponse();
+ RequestContextHolder.resetRequestAttributes();
+ RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpReq, httpResp));
+
+ basicConfig.putConfigValue("eidas.ms.auth.eIDAS.node_v2.proxy.forward.endpoint",
+ "http://eidas.proxy/endpoint");
+ basicConfig.putConfigValue("auth.eIDAS.proxy.workaround.mandates.legalperson",
+ "false");
+
+ final Map<String, String> spConfig = new HashMap<>();
+ spConfig.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, "testSp");
+ spConfig.put("target", "urn:publicid:gv.at:cdid+XX");
+ spConfig.put(PROP_CONFIG_SP_NEW_EID_MODE, "true");
+ oaParam = new MsConnectorDummySpConfiguration(spConfig, basicConfig);
+ oaParam.setLoa(Arrays.asList(EaafConstants.EIDAS_LOA_HIGH));
+
+ pendingReq = new ProxyServicePendingRequest();
+ pendingReq.initialize(httpReq, basicConfig);
+ pendingReq.setOnlineApplicationConfiguration(oaParam);
+
+ LightRequest.Builder eidasRequestBuilder = generateBasicLightRequest();
+ pendingReq.setEidasRequest(eidasRequestBuilder.build());
+
+
+ springManagedSpecificConnectorCommunicationService =
+ (SpecificCommunicationService) context.getBean(
+ SpecificCommunicationDefinitionBeanNames.SPECIFIC_PROXYSERVICE_COMMUNICATION_SERVICE
+ .toString());
+
+ }
+
+ @Test
+ public void wrongPendingRequestType() {
+ IAuthData authData = generateDummyAuthData();
+ TestRequestImpl internalPendingReq = new TestRequestImpl();
+
+ EaafException exception = assertThrows(EaafException.class,
+ () -> action.processRequest(internalPendingReq, httpReq, httpResp, authData));
+ Assert.assertEquals("wrong errorCode", "eidas.proxyservice.99", exception.getErrorId());
+
+ }
+
+ @Test
+ public void missingForwardUrl() {
+ Map<String, Object> attr = new HashMap<>();
+ attr.put(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER,
+ "AT+XX:" + RandomStringUtils.randomAlphanumeric(10));
+ IAuthData authData = generateDummyAuthData(attr , EaafConstants.EIDAS_LOA_HIGH,
+ RandomStringUtils.randomAlphanumeric(10), RandomStringUtils.randomAlphanumeric(10), "1945-04-18", false);
+ basicConfig.removeConfigValue("eidas.ms.auth.eIDAS.node_v2.proxy.forward.endpoint");
+
+ EaafException exception = assertThrows(EaafException.class,
+ () -> action.processRequest(pendingReq, httpReq, httpResp, authData));
+ Assert.assertEquals("wrong errorCode", "config.08", exception.getErrorId());
+
+ }
+
+ @Test
+ public void responseWithoutMandate() throws EaafException, SpecificCommunicationException {
+ Map<String, Object> attr = new HashMap<>();
+ attr.put(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER,
+ "AT+XX:" + RandomStringUtils.randomAlphanumeric(10));
+ IAuthData authData = generateDummyAuthData(attr , EaafConstants.EIDAS_LOA_HIGH,
+ RandomStringUtils.randomAlphanumeric(10), RandomStringUtils.randomAlphanumeric(10), "1945-04-18", false);
+
+ //perform test
+ SloInformationInterface result = action.processRequest(pendingReq, httpReq, httpResp, authData);
+
+ //validate state
+ Assert.assertNotNull("Result should be not null", result);
+
+ ImmutableAttributeMap respAttr = validateBasicEidasResponse(authData);
+ assertEquals("wrong attr. size", 4, respAttr.size());
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_PERSONALIDENTIFIER,
+ (String) attr.get(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER));
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_CURRENTFAMILYNAME, authData.getFamilyName());
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_CURRENTGIVENNAME, authData.getGivenName());
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_DATEOFBIRTH,
+ authData.getDateOfBirth());
+
+ }
+
+ @Test
+ public void responseWithNatMandate() throws EaafException, SpecificCommunicationException {
+ Map<String, Object> attr = new HashMap<>();
+ attr.put(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER,
+ "AT+XX:" + RandomStringUtils.randomAlphanumeric(10));
+
+ attr.put(MsEidasNodeConstants.ATTR_EIDAS_NAT_MANDATOR_PERSONAL_IDENTIFIER,
+ RandomStringUtils.randomAlphabetic(10));
+ attr.put(PvpAttributeDefinitions.MANDATE_NAT_PER_GIVEN_NAME_NAME,
+ RandomStringUtils.randomAlphabetic(10));
+ attr.put(PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_NAME,
+ RandomStringUtils.randomAlphabetic(10));
+ attr.put(PvpAttributeDefinitions.MANDATE_NAT_PER_BIRTHDATE_NAME,
+ "1985-11-15");
+
+
+ IAuthData authData = generateDummyAuthData(attr , EaafConstants.EIDAS_LOA_HIGH,
+ RandomStringUtils.randomAlphanumeric(10), RandomStringUtils.randomAlphanumeric(10), "1945-04-18", true);
+
+ //perform test
+ SloInformationInterface result = action.processRequest(pendingReq, httpReq, httpResp, authData);
+
+ //validate state
+ Assert.assertNotNull("Result should be not null", result);
+
+ ImmutableAttributeMap respAttr = validateBasicEidasResponse(authData);
+ assertEquals("wrong attr. size", 8, respAttr.size());
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_REPRESENTATIVE_PERSONALIDENTIFIER,
+ (String) attr.get(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER));
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_REPRESENTATIVE_CURRENTFAMILYNAME, authData.getFamilyName());
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_REPRESENTATIVE_CURRENTGIVENNAME, authData.getGivenName());
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_REPRESENTATIVE_DATEOFBIRTH, authData.getDateOfBirth());
+
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_PERSONALIDENTIFIER,
+ (String) attr.get(MsEidasNodeConstants.ATTR_EIDAS_NAT_MANDATOR_PERSONAL_IDENTIFIER));
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_CURRENTFAMILYNAME,
+ (String) attr.get(PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_NAME));
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_CURRENTGIVENNAME,
+ (String) attr.get(PvpAttributeDefinitions.MANDATE_NAT_PER_GIVEN_NAME_NAME));
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_DATEOFBIRTH,
+ (String) attr.get(PvpAttributeDefinitions.MANDATE_NAT_PER_BIRTHDATE_NAME));
+
+ }
+
+ @Test
+ public void responseWithJurMandate() throws EaafException, SpecificCommunicationException {
+ Map<String, Object> attr = new HashMap<>();
+ attr.put(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER,
+ "AT+XX:" + RandomStringUtils.randomAlphanumeric(10));
+ IAuthData authData = generateDummyAuthData(attr , EaafConstants.EIDAS_LOA_HIGH,
+ RandomStringUtils.randomAlphanumeric(10), RandomStringUtils.randomAlphanumeric(10), "1945-04-18", true);
+
+ attr.put(MsEidasNodeConstants.ATTR_EIDAS_JUR_MANDATOR_PERSONAL_IDENTIFIER,
+ RandomStringUtils.randomAlphabetic(10));
+ attr.put(PvpAttributeDefinitions.MANDATE_LEG_PER_FULL_NAME_NAME,
+ RandomStringUtils.randomAlphabetic(10));
+
+ //perform test
+ SloInformationInterface result = action.processRequest(pendingReq, httpReq, httpResp, authData);
+
+ //validate state
+ Assert.assertNotNull("Result should be not null", result);
+
+ ImmutableAttributeMap respAttr = validateBasicEidasResponse(authData);
+ assertEquals("wrong attr. size", 6, respAttr.size());
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_REPRESENTATIVE_PERSONALIDENTIFIER,
+ (String) attr.get(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER));
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_REPRESENTATIVE_CURRENTFAMILYNAME, authData.getFamilyName());
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_REPRESENTATIVE_CURRENTGIVENNAME, authData.getGivenName());
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_REPRESENTATIVE_DATEOFBIRTH, authData.getDateOfBirth());
+
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_LEGALPERSONIDENTIFIER,
+ (String) attr.get(MsEidasNodeConstants.ATTR_EIDAS_JUR_MANDATOR_PERSONAL_IDENTIFIER));
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_LEGALNAME,
+ (String) attr.get(PvpAttributeDefinitions.MANDATE_LEG_PER_FULL_NAME_NAME));
+
+ assertNull("find nat. person subject: personalId",
+ getAttrValue(respAttr, Constants.eIDAS_ATTR_PERSONALIDENTIFIER));
+ assertNull("find nat. person subject: familyName",
+ getAttrValue(respAttr, Constants.eIDAS_ATTR_CURRENTFAMILYNAME));
+ assertNull("find nat. person subject: givenName",
+ getAttrValue(respAttr, Constants.eIDAS_ATTR_CURRENTGIVENNAME));
+ assertNull("find nat. person subject: dateOfBirth",
+ getAttrValue(respAttr, Constants.eIDAS_ATTR_DATEOFBIRTH));
+
+ }
+
+ @Test
+ public void responseWithNatMandateWithWorkAround() throws EaafException, SpecificCommunicationException {
+ basicConfig.putConfigValue("auth.eIDAS.proxy.workaround.mandates.legalperson",
+ "true");
+
+ //request natural person subject only
+ LightRequest.Builder eidasRequestBuilder = generateBasicLightRequest();
+ eidasRequestBuilder.requestedAttributes(ImmutableAttributeMap.builder().put(
+ attrRegistry.getCoreAttributeRegistry().getByFriendlyName(Constants.eIDAS_ATTR_PERSONALIDENTIFIER).first()).build());
+ pendingReq.setEidasRequest(eidasRequestBuilder.build());
+
+
+ Map<String, Object> attr = new HashMap<>();
+ attr.put(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER,
+ "AT+XX:" + RandomStringUtils.randomAlphanumeric(10));
+
+ attr.put(MsEidasNodeConstants.ATTR_EIDAS_NAT_MANDATOR_PERSONAL_IDENTIFIER,
+ RandomStringUtils.randomAlphabetic(10));
+ attr.put(PvpAttributeDefinitions.MANDATE_NAT_PER_GIVEN_NAME_NAME,
+ RandomStringUtils.randomAlphabetic(10));
+ attr.put(PvpAttributeDefinitions.MANDATE_NAT_PER_FAMILY_NAME_NAME,
+ RandomStringUtils.randomAlphabetic(10));
+ attr.put(PvpAttributeDefinitions.MANDATE_NAT_PER_BIRTHDATE_NAME,
+ "1985-11-15");
+
+
+ IAuthData authData = generateDummyAuthData(attr , EaafConstants.EIDAS_LOA_HIGH,
+ RandomStringUtils.randomAlphanumeric(10), RandomStringUtils.randomAlphanumeric(10), "1945-04-18", true);
+
+ //perform test
+ SloInformationInterface result = action.processRequest(pendingReq, httpReq, httpResp, authData);
+
+ //validate state
+ Assert.assertNotNull("Result should be not null", result);
+
+ ImmutableAttributeMap respAttr = validateBasicEidasResponse(authData);
+ assertEquals("wrong attr. size", 8, respAttr.size());
+
+ }
+
+ @Test
+ public void responseWithJurMandateWithWorkAround() throws EaafException, SpecificCommunicationException {
+ basicConfig.putConfigValue("auth.eIDAS.proxy.workaround.mandates.legalperson",
+ "true");
+
+ //request natural person subject only
+ LightRequest.Builder eidasRequestBuilder = generateBasicLightRequest();
+ eidasRequestBuilder.requestedAttributes(ImmutableAttributeMap.builder()
+ .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(Constants.eIDAS_ATTR_PERSONALIDENTIFIER).first())
+ .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(Constants.eIDAS_ATTR_LEGALPERSONIDENTIFIER).first())
+ .build());
+ pendingReq.setEidasRequest(eidasRequestBuilder.build());
+
+ Map<String, Object> attr = new HashMap<>();
+ attr.put(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER,
+ "AT+XX:" + RandomStringUtils.randomAlphanumeric(10));
+ IAuthData authData = generateDummyAuthData(attr , EaafConstants.EIDAS_LOA_HIGH,
+ RandomStringUtils.randomAlphanumeric(10), RandomStringUtils.randomAlphanumeric(10), "1945-04-18", true);
+
+ attr.put(MsEidasNodeConstants.ATTR_EIDAS_JUR_MANDATOR_PERSONAL_IDENTIFIER,
+ RandomStringUtils.randomAlphabetic(10));
+ attr.put(PvpAttributeDefinitions.MANDATE_LEG_PER_FULL_NAME_NAME,
+ RandomStringUtils.randomAlphabetic(10));
+
+ //perform test
+ SloInformationInterface result = action.processRequest(pendingReq, httpReq, httpResp, authData);
+
+ //validate state
+ Assert.assertNotNull("Result should be not null", result);
+
+ ImmutableAttributeMap respAttr = validateBasicEidasResponse(authData);
+ assertEquals("wrong attr. size", 10, respAttr.size());
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_PERSONALIDENTIFIER,
+ (String) attr.get(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER));
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_CURRENTFAMILYNAME, authData.getFamilyName());
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_CURRENTGIVENNAME, authData.getGivenName());
+ checkAttrValue(respAttr, Constants.eIDAS_ATTR_DATEOFBIRTH, authData.getDateOfBirth());
+
+ }
+
+ @Test
+ public void responseWithJurMandateWithWorkAroundNoNatSubject() throws EaafException, SpecificCommunicationException {
+ basicConfig.putConfigValue("auth.eIDAS.proxy.workaround.mandates.legalperson",
+ "true");
+
+ //request natural person subject only
+ LightRequest.Builder eidasRequestBuilder = generateBasicLightRequest();
+ eidasRequestBuilder.requestedAttributes(ImmutableAttributeMap.builder()
+ .put(attrRegistry.getCoreAttributeRegistry().getByFriendlyName(Constants.eIDAS_ATTR_LEGALPERSONIDENTIFIER).first())
+ .build());
+ pendingReq.setEidasRequest(eidasRequestBuilder.build());
+
+ Map<String, Object> attr = new HashMap<>();
+ attr.put(MsEidasNodeConstants.ATTR_EIDAS_PERSONAL_IDENTIFIER,
+ "AT+XX:" + RandomStringUtils.randomAlphanumeric(10));
+ IAuthData authData = generateDummyAuthData(attr , EaafConstants.EIDAS_LOA_HIGH,
+ RandomStringUtils.randomAlphanumeric(10), RandomStringUtils.randomAlphanumeric(10), "1945-04-18", true);
+
+ attr.put(MsEidasNodeConstants.ATTR_EIDAS_JUR_MANDATOR_PERSONAL_IDENTIFIER,
+ RandomStringUtils.randomAlphabetic(10));
+ attr.put(PvpAttributeDefinitions.MANDATE_LEG_PER_FULL_NAME_NAME,
+ RandomStringUtils.randomAlphabetic(10));
+
+ //perform test
+ SloInformationInterface result = action.processRequest(pendingReq, httpReq, httpResp, authData);
+
+ //validate state
+ Assert.assertNotNull("Result should be not null", result);
+
+ ImmutableAttributeMap respAttr = validateBasicEidasResponse(authData);
+ assertEquals("wrong attr. size", 6, respAttr.size());
+ assertNull("find nat. person subject: personalId",
+ getAttrValue(respAttr, Constants.eIDAS_ATTR_PERSONALIDENTIFIER));
+ assertNull("find nat. person subject: familyName",
+ getAttrValue(respAttr, Constants.eIDAS_ATTR_CURRENTFAMILYNAME));
+ assertNull("find nat. person subject: givenName",
+ getAttrValue(respAttr, Constants.eIDAS_ATTR_CURRENTGIVENNAME));
+ assertNull("find nat. person subject: dateOfBirth",
+ getAttrValue(respAttr, Constants.eIDAS_ATTR_DATEOFBIRTH));
+
+ }
+
+ @Test
+ public void checkBasicConstrainsInAction() {
+
+ Assert.assertTrue("Wrong NeedAuthentication", action.needAuthentication(pendingReq, httpReq, httpResp));
+ Assert.assertNotNull("Missing ActionName", action.getDefaultActionName());
+
+ Assert.assertNotNull("missing ActionBean", context.getBean(ProxyServiceAuthenticationAction.class));
+
+ }
+
+ private IAuthData generateDummyAuthData() {
+ return generateDummyAuthData(Collections.emptyMap(), EaafConstants.EIDAS_LOA_LOW,
+ RandomStringUtils.randomAlphanumeric(10), RandomStringUtils.randomAlphanumeric(10), "1940-01-01", false);
+
+ }
+
+ private Object getAttrValue(ImmutableAttributeMap respAttr, String attrName) {
+ final AttributeDefinition<?> attrDef =
+ attrRegistry.getCoreAttributeRegistry().getByFriendlyName(attrName).first();
+ return respAttr.getFirstValue(attrDef);
+
+ }
+
+ private void checkAttrValue(ImmutableAttributeMap respAttr, String attrName, String expected) {
+ Object value = getAttrValue(respAttr, attrName);
+ assertNotNull("not attr value: " + attrName, value);
+
+ if (value instanceof String) {
+ assertEquals("wrong attr. value: " + attrName, expected, value);
+
+ } else if ( value instanceof DateTime) {
+ assertEquals("wrong attr. value: " + attrName, expected, ((DateTime)value).toString("yyyy-MM-dd"));
+
+ }
+ }
+
+ private ImmutableAttributeMap validateBasicEidasResponse(IAuthData authData) throws SpecificCommunicationException {
+ assertNotNull("not redirct Header", httpResp.getHeader("Location"));
+ assertTrue("wrong redirect URL", httpResp.getHeader("Location").startsWith("http://eidas.proxy/endpoint?token="));
+ String token = httpResp.getHeader("Location").substring("http://eidas.proxy/endpoint?token=".length());
+
+ ILightResponse resp = springManagedSpecificConnectorCommunicationService.getAndRemoveResponse(URLDecoder.decode(token),
+ ImmutableSortedSet.copyOf(attrRegistry.getCoreAttributeRegistry().getAttributes()));
+
+ assertNotNull("responseId", resp.getId());
+ assertEquals("inResponseTo", pendingReq.getEidasRequest().getId(), resp.getInResponseToId());
+ assertEquals("relayState", pendingReq.getEidasRequest().getRelayState(), resp.getRelayState());
+ assertEquals("LoA", authData.getEidasQaaLevel(), resp.getLevelOfAssurance());
+
+ assertNotNull("subjectNameId", resp.getSubject());
+ assertEquals("subjectNameIdFormat", NameIDType.TRANSIENT, resp.getSubjectNameIdFormat());
+
+ assertFalse("not attributes", resp.getAttributes().isEmpty());
+ return resp.getAttributes();
+
+ }
+
+ private Builder generateBasicLightRequest() {
+ return LightRequest.builder()
+ .id(UUID.randomUUID().toString())
+ .issuer(RandomStringUtils.randomAlphabetic(10))
+ .citizenCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH)
+ .spCountryCode(RandomStringUtils.randomAlphabetic(2).toUpperCase())
+ .spType("public")
+ .requesterId(RandomStringUtils.randomAlphanumeric(10))
+ .providerName(RandomStringUtils.randomAlphanumeric(10));
+
+ }
+
+ private IAuthData generateDummyAuthData(Map<String, Object> attrs, String loa, String familyName, String givenName, String dateOfBirth,
+ boolean useMandates) {
+ return new IEidAuthData() {
+
+ @Override
+ public boolean isSsoSession() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public boolean isForeigner() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public boolean isBaseIdTransferRestrication() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public Date getSsoSessionValidTo() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getSessionIndex() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getNameIdFormat() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getNameID() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public IIdentityLink getIdentityLink() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getIdentificationValue() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getIdentificationType() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getGivenName() {
+ return givenName;
+ }
+
+ @Override
+ public <T> T getGenericData(String key, Class<T> clazz) {
+ if (attrs.containsKey(key)) {
+ return (T) attrs.get(key);
+
+ } else {
+ return null;
+ }
+
+ }
+
+ @Override
+ public String getDateOfBirth() {
+ return dateOfBirth;
+ }
+
+ @Override
+ public String getFamilyName() {
+ return familyName;
+ }
+
+ @Override
+ public String getEncryptedSourceIdType() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getEncryptedSourceId() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getEidasQaaLevel() {
+ return loa;
+
+ }
+
+
+ @Override
+ public String getCiticenCountryCode() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getBpkType() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getBpk() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getAuthenticationIssuer() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getAuthenticationIssueInstantString() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Date getAuthenticationIssueInstant() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public byte[] getSignerCertificate() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public byte[] getEidToken() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public EidIdentityStatusLevelValues getEidStatus() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getVdaEndPointUrl() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public boolean isUseMandate() {
+ return useMandates;
+
+ }
+
+ @Override
+ public String getDateOfBirthFormated(String pattern) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ };
+
+ }
+}
diff --git a/modules/eidas_proxy-sevice/src/test/resources/config/additional-attributes.xml b/modules/eidas_proxy-sevice/src/test/resources/config/additional-attributes.xml
new file mode 100644
index 00000000..6510546e
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/test/resources/config/additional-attributes.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+# Copyright (c) 2017 European Commission
+# Licensed under the EUPL, Version 1.2 or – as soon they will be
+# approved by the European Commission - subsequent versions of the
+# EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+# * https://joinup.ec.europa.eu/page/eupl-text-11-12
+# *
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the Licence is distributed on an "AS IS" basis,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the Licence for the specific language governing permissions and limitations under the Licence.
+ -->
+
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+<properties>
+ <comment>Dynamic attributes</comment>
+
+ <entry key="1.NameUri">http://eidas.europa.eu/attributes/naturalperson/AdditionalAttribute</entry>
+ <entry key="1.FriendlyName">AdditionalAttribute</entry>
+ <entry key="1.PersonType">NaturalPerson</entry>
+ <entry key="1.Required">false</entry>
+ <entry key="1.XmlType.NamespaceUri">http://www.w3.org/2001/XMLSchema</entry>
+ <entry key="1.XmlType.LocalPart">string</entry>
+ <entry key="1.XmlType.NamespacePrefix">xs</entry>
+ <entry key="1.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="2.NameUri">http://eidas.europa.eu/attributes/legalperson/LegalAdditionalAttribute</entry>
+ <entry key="2.FriendlyName">LegalAdditionalAttribute</entry>
+ <entry key="2.PersonType">LegalPerson</entry>
+ <entry key="2.Required">false</entry>
+ <entry key="2.XmlType.NamespaceUri">http://www.w3.org/2001/XMLSchema</entry>
+ <entry key="2.XmlType.LocalPart">string</entry>
+ <entry key="2.XmlType.NamespacePrefix">xs</entry>
+ <entry key="2.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+</properties>
diff --git a/modules/eidas_proxy-sevice/src/test/resources/config/eidas-attributes.xml b/modules/eidas_proxy-sevice/src/test/resources/config/eidas-attributes.xml
new file mode 100644
index 00000000..cbae35db
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/test/resources/config/eidas-attributes.xml
@@ -0,0 +1,376 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+# Copyright (c) 2017 European Commission
+# Licensed under the EUPL, Version 1.2 or – as soon they will be
+# approved by the European Commission - subsequent versions of the
+# EUPL (the "Licence");
+# You may not use this work except in compliance with the Licence.
+# You may obtain a copy of the Licence at:
+# * https://joinup.ec.europa.eu/page/eupl-text-11-12
+# *
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the Licence is distributed on an "AS IS" basis,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the Licence for the specific language governing permissions and limitations under the Licence.
+ -->
+
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+<properties>
+ <comment>eIDAS attributes</comment>
+
+ <entry key="1.NameUri">http://eidas.europa.eu/attributes/naturalperson/PersonIdentifier</entry>
+ <entry key="1.FriendlyName">PersonIdentifier</entry>
+ <entry key="1.PersonType">NaturalPerson</entry>
+ <entry key="1.Required">true</entry>
+ <entry key="1.UniqueIdentifier">true</entry>
+ <entry key="1.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson</entry>
+ <entry key="1.XmlType.LocalPart">PersonIdentifierType</entry>
+ <entry key="1.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="1.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="2.NameUri">http://eidas.europa.eu/attributes/naturalperson/CurrentFamilyName</entry>
+ <entry key="2.FriendlyName">FamilyName</entry>
+ <entry key="2.PersonType">NaturalPerson</entry>
+ <entry key="2.Required">true</entry>
+ <entry key="2.TransliterationMandatory">true</entry>
+ <entry key="2.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson</entry>
+ <entry key="2.XmlType.LocalPart">CurrentFamilyNameType</entry>
+ <entry key="2.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="2.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="3.NameUri">http://eidas.europa.eu/attributes/naturalperson/CurrentGivenName</entry>
+ <entry key="3.FriendlyName">FirstName</entry>
+ <entry key="3.PersonType">NaturalPerson</entry>
+ <entry key="3.Required">true</entry>
+ <entry key="3.TransliterationMandatory">true</entry>
+ <entry key="3.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson</entry>
+ <entry key="3.XmlType.LocalPart">CurrentGivenNameType</entry>
+ <entry key="3.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="3.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="4.NameUri">http://eidas.europa.eu/attributes/naturalperson/DateOfBirth</entry>
+ <entry key="4.FriendlyName">DateOfBirth</entry>
+ <entry key="4.PersonType">NaturalPerson</entry>
+ <entry key="4.Required">true</entry>
+ <entry key="4.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson</entry>
+ <entry key="4.XmlType.LocalPart">DateOfBirthType</entry>
+ <entry key="4.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="4.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.DateTimeAttributeValueMarshaller</entry>
+
+ <entry key="5.NameUri">http://eidas.europa.eu/attributes/naturalperson/BirthName</entry>
+ <entry key="5.FriendlyName">BirthName</entry>
+ <entry key="5.PersonType">NaturalPerson</entry>
+ <entry key="5.Required">false</entry>
+ <entry key="5.TransliterationMandatory">true</entry>
+ <entry key="5.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson</entry>
+ <entry key="5.XmlType.LocalPart">BirthNameType</entry>
+ <entry key="5.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="5.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="6.NameUri">http://eidas.europa.eu/attributes/naturalperson/PlaceOfBirth</entry>
+ <entry key="6.FriendlyName">PlaceOfBirth</entry>
+ <entry key="6.PersonType">NaturalPerson</entry>
+ <entry key="6.Required">false</entry>
+ <entry key="6.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson</entry>
+ <entry key="6.XmlType.LocalPart">PlaceOfBirthType</entry>
+ <entry key="6.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="6.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="7.NameUri">http://eidas.europa.eu/attributes/naturalperson/CurrentAddress</entry>
+ <entry key="7.FriendlyName">CurrentAddress</entry>
+ <entry key="7.PersonType">NaturalPerson</entry>
+ <entry key="7.Required">false</entry>
+ <entry key="7.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson</entry>
+ <entry key="7.XmlType.LocalPart">CurrentAddressType</entry>
+ <entry key="7.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="7.AttributeValueMarshaller">eu.eidas.auth.commons.protocol.eidas.impl.CurrentAddressAttributeValueMarshaller</entry>
+
+ <entry key="8.NameUri">http://eidas.europa.eu/attributes/naturalperson/Gender</entry>
+ <entry key="8.FriendlyName">Gender</entry>
+ <entry key="8.PersonType">NaturalPerson</entry>
+ <entry key="8.Required">false</entry>
+ <entry key="8.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson</entry>
+ <entry key="8.XmlType.LocalPart">GenderType</entry>
+ <entry key="8.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="8.AttributeValueMarshaller">eu.eidas.auth.commons.protocol.eidas.impl.GenderAttributeValueMarshaller</entry>
+
+ <entry key="9.NameUri">http://eidas.europa.eu/attributes/legalperson/LegalPersonIdentifier</entry>
+ <entry key="9.FriendlyName">LegalPersonIdentifier</entry>
+ <entry key="9.PersonType">LegalPerson</entry>
+ <entry key="9.Required">true</entry>
+ <entry key="9.UniqueIdentifier">true</entry>
+ <entry key="9.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="9.XmlType.LocalPart">LegalPersonIdentifierType</entry>
+ <entry key="9.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="9.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="10.NameUri">http://eidas.europa.eu/attributes/legalperson/LegalName</entry>
+ <entry key="10.FriendlyName">LegalName</entry>
+ <entry key="10.PersonType">LegalPerson</entry>
+ <entry key="10.Required">true</entry>
+ <entry key="10.TransliterationMandatory">true</entry>
+ <entry key="10.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="10.XmlType.LocalPart">LegalNameType</entry>
+ <entry key="10.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="10.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="11.NameUri">http://eidas.europa.eu/attributes/legalperson/LegalPersonAddress</entry>
+ <entry key="11.FriendlyName">LegalAddress</entry>
+ <entry key="11.PersonType">LegalPerson</entry>
+ <entry key="11.Required">false</entry>
+ <entry key="11.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="11.XmlType.LocalPart">LegalPersonAddressType</entry>
+ <entry key="11.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="11.AttributeValueMarshaller">eu.eidas.auth.commons.protocol.eidas.impl.LegalAddressAttributeValueMarshaller</entry>
+
+ <entry key="12.NameUri">http://eidas.europa.eu/attributes/legalperson/VATRegistrationNumber</entry>
+ <entry key="12.FriendlyName">VATRegistration</entry>
+ <entry key="12.PersonType">LegalPerson</entry>
+ <entry key="12.Required">false</entry>
+ <entry key="12.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="12.XmlType.LocalPart">VATRegistrationNumberType</entry>
+ <entry key="12.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="12.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="13.NameUri">http://eidas.europa.eu/attributes/legalperson/TaxReference</entry>
+ <entry key="13.FriendlyName">TaxReference</entry>
+ <entry key="13.PersonType">LegalPerson</entry>
+ <entry key="13.Required">false</entry>
+ <entry key="13.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="13.XmlType.LocalPart">TaxReferenceType</entry>
+ <entry key="13.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="13.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="14.NameUri">http://eidas.europa.eu/attributes/legalperson/D-2012-17-EUIdentifier</entry>
+ <entry key="14.FriendlyName">D-2012-17-EUIdentifier</entry>
+ <entry key="14.PersonType">LegalPerson</entry>
+ <entry key="14.Required">false</entry>
+ <entry key="14.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="14.XmlType.LocalPart">D-2012-17-EUIdentifierType</entry>
+ <entry key="14.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="14.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="15.NameUri">http://eidas.europa.eu/attributes/legalperson/LEI</entry>
+ <entry key="15.FriendlyName">LEI</entry>
+ <entry key="15.PersonType">LegalPerson</entry>
+ <entry key="15.Required">false</entry>
+ <entry key="15.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="15.XmlType.LocalPart">LEIType</entry>
+ <entry key="15.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="15.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="16.NameUri">http://eidas.europa.eu/attributes/legalperson/EORI</entry>
+ <entry key="16.FriendlyName">EORI</entry>
+ <entry key="16.PersonType">LegalPerson</entry>
+ <entry key="16.Required">false</entry>
+ <entry key="16.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="16.XmlType.LocalPart">EORIType</entry>
+ <entry key="16.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="16.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="17.NameUri">http://eidas.europa.eu/attributes/legalperson/SEED</entry>
+ <entry key="17.FriendlyName">SEED</entry>
+ <entry key="17.PersonType">LegalPerson</entry>
+ <entry key="17.Required">false</entry>
+ <entry key="17.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="17.XmlType.LocalPart">SEEDType</entry>
+ <entry key="17.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="17.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="18.NameUri">http://eidas.europa.eu/attributes/legalperson/SIC</entry>
+ <entry key="18.FriendlyName">SIC</entry>
+ <entry key="18.PersonType">LegalPerson</entry>
+ <entry key="18.Required">false</entry>
+ <entry key="18.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson</entry>
+ <entry key="18.XmlType.LocalPart">SICType</entry>
+ <entry key="18.XmlType.NamespacePrefix">eidas-legal</entry>
+ <entry key="18.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="19.NameUri">http://eidas.europa.eu/attributes/naturalperson/representative/PersonIdentifier</entry>
+ <entry key="19.FriendlyName">RepresentativePersonIdentifier</entry>
+ <entry key="19.PersonType">RepresentativeNaturalPerson</entry>
+ <entry key="19.Required">false</entry>
+ <entry key="19.UniqueIdentifier">true</entry>
+ <entry key="19.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson/representative</entry>
+ <entry key="19.XmlType.LocalPart">PersonIdentifierType</entry>
+ <entry key="19.XmlType.NamespacePrefix">eidas-natural</entry>
+ <entry key="19.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="20.NameUri">http://eidas.europa.eu/attributes/naturalperson/representative/CurrentFamilyName</entry>
+ <entry key="20.FriendlyName">RepresentativeFamilyName</entry>
+ <entry key="20.PersonType">RepresentativeNaturalPerson</entry>
+ <entry key="20.Required">false</entry>
+ <entry key="20.TransliterationMandatory">true</entry>
+ <entry key="20.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson/representative</entry>
+ <entry key="20.XmlType.LocalPart">CurrentFamilyNameType</entry>
+ <entry key="20.XmlType.NamespacePrefix">eidas-reprentative-natural</entry>
+ <entry key="20.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="21.NameUri">http://eidas.europa.eu/attributes/naturalperson/representative/CurrentGivenName</entry>
+ <entry key="21.FriendlyName">RepresentativeFirstName</entry>
+ <entry key="21.PersonType">RepresentativeNaturalPerson</entry>
+ <entry key="21.Required">false</entry>
+ <entry key="21.TransliterationMandatory">true</entry>
+ <entry key="21.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson/representative</entry>
+ <entry key="21.XmlType.LocalPart">CurrentGivenNameType</entry>
+ <entry key="21.XmlType.NamespacePrefix">eidas-reprentative-natural</entry>
+ <entry key="21.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="22.NameUri">http://eidas.europa.eu/attributes/naturalperson/representative/DateOfBirth</entry>
+ <entry key="22.FriendlyName">RepresentativeDateOfBirth</entry>
+ <entry key="22.PersonType">RepresentativeNaturalPerson</entry>
+ <entry key="22.Required">false</entry>
+ <entry key="22.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson/representative</entry>
+ <entry key="22.XmlType.LocalPart">DateOfBirthType</entry>
+ <entry key="22.XmlType.NamespacePrefix">eidas-reprentative-natural</entry>
+ <entry key="22.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.DateTimeAttributeValueMarshaller</entry>
+
+ <entry key="23.NameUri">http://eidas.europa.eu/attributes/naturalperson/representative/BirthName</entry>
+ <entry key="23.FriendlyName">RepresentativeBirthName</entry>
+ <entry key="23.PersonType">RepresentativeNaturalPerson</entry>
+ <entry key="23.Required">false</entry>
+ <entry key="23.TransliterationMandatory">true</entry>
+ <entry key="23.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson/representative</entry>
+ <entry key="23.XmlType.LocalPart">BirthNameType</entry>
+ <entry key="23.XmlType.NamespacePrefix">eidas-reprentative-natural</entry>
+ <entry key="23.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="24.NameUri">http://eidas.europa.eu/attributes/naturalperson/representative/PlaceOfBirth</entry>
+ <entry key="24.FriendlyName">RepresentativePlaceOfBirth</entry>
+ <entry key="24.PersonType">RepresentativeNaturalPerson</entry>
+ <entry key="24.Required">false</entry>
+ <entry key="24.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson/representative</entry>
+ <entry key="24.XmlType.LocalPart">PlaceOfBirthType</entry>
+ <entry key="24.XmlType.NamespacePrefix">eidas-reprentative-natural</entry>
+ <entry key="24.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="25.NameUri">http://eidas.europa.eu/attributes/naturalperson/representative/CurrentAddress</entry>
+ <entry key="25.FriendlyName">RepresentativeCurrentAddress</entry>
+ <entry key="25.PersonType">RepresentativeNaturalPerson</entry>
+ <entry key="25.Required">false</entry>
+ <entry key="25.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson/representative</entry>
+ <entry key="25.XmlType.LocalPart">CurrentAddressType</entry>
+ <entry key="25.XmlType.NamespacePrefix">eidas-reprentative-natural</entry>
+ <entry key="25.AttributeValueMarshaller">eu.eidas.auth.commons.protocol.eidas.impl.RepvCurrentAddressAttributeValueMarshaller</entry>
+
+ <entry key="26.NameUri">http://eidas.europa.eu/attributes/naturalperson/representative/Gender</entry>
+ <entry key="26.FriendlyName">RepresentativeGender</entry>
+ <entry key="26.PersonType">RepresentativeNaturalPerson</entry>
+ <entry key="26.Required">false</entry>
+ <entry key="26.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/naturalperson/representative</entry>
+ <entry key="26.XmlType.LocalPart">GenderType</entry>
+ <entry key="26.XmlType.NamespacePrefix">eidas-reprentative-natural</entry>
+ <entry key="26.AttributeValueMarshaller">eu.eidas.auth.commons.protocol.eidas.impl.GenderAttributeValueMarshaller</entry>
+
+ <entry key="27.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/LegalPersonIdentifier</entry>
+ <entry key="27.FriendlyName">RepresentativeLegalPersonIdentifier</entry>
+ <entry key="27.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="27.Required">false</entry>
+ <entry key="27.UniqueIdentifier">true</entry>
+ <entry key="27.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="27.XmlType.LocalPart">LegalPersonIdentifierType</entry>
+ <entry key="27.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="27.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="28.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/LegalName</entry>
+ <entry key="28.FriendlyName">RepresentativeLegalName</entry>
+ <entry key="28.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="28.Required">false</entry>
+ <entry key="28.TransliterationMandatory">true</entry>
+ <entry key="28.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="28.XmlType.LocalPart">LegalNameType</entry>
+ <entry key="28.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="28.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="29.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/LegalPersonAddress</entry>
+ <entry key="29.FriendlyName">RepresentativeLegalAddress</entry>
+ <entry key="29.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="29.Required">false</entry>
+ <entry key="29.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="29.XmlType.LocalPart">LegalPersonAddressType</entry>
+ <entry key="29.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="29.AttributeValueMarshaller">eu.eidas.auth.commons.protocol.eidas.impl.RepvLegalAddressAttributeValueMarshaller</entry>
+
+ <entry key="30.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/VATRegistrationNumber</entry>
+ <entry key="30.FriendlyName">RepresentativeVATRegistration</entry>
+ <entry key="30.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="30.Required">false</entry>
+ <entry key="30.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="30.XmlType.LocalPart">VATRegistrationNumberType</entry>
+ <entry key="30.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="30.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="31.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/TaxReference</entry>
+ <entry key="31.FriendlyName">RepresentativeTaxReference</entry>
+ <entry key="31.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="31.Required">false</entry>
+ <entry key="31.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="31.XmlType.LocalPart">TaxReferenceType</entry>
+ <entry key="31.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="31.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="32.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/D-2012-17-EUIdentifier</entry>
+ <entry key="32.FriendlyName">RepresentativeD-2012-17-EUIdentifier</entry>
+ <entry key="32.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="32.Required">false</entry>
+ <entry key="32.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="32.XmlType.LocalPart">D-2012-17-EUIdentifierType</entry>
+ <entry key="32.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="32.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="33.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/LEI</entry>
+ <entry key="33.FriendlyName">RepresentativeLEI</entry>
+ <entry key="33.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="33.Required">false</entry>
+ <entry key="33.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="33.XmlType.LocalPart">LEIType</entry>
+ <entry key="33.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="33.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="34.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/EORI</entry>
+ <entry key="34.FriendlyName">RepresentativeEORI</entry>
+ <entry key="34.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="34.Required">false</entry>
+ <entry key="34.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="34.XmlType.LocalPart">EORIType</entry>
+ <entry key="34.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="34.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="35.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/SEED</entry>
+ <entry key="35.FriendlyName">RepresentativeSEED</entry>
+ <entry key="35.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="35.Required">false</entry>
+ <entry key="35.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="35.XmlType.LocalPart">SEEDType</entry>
+ <entry key="35.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="35.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="36.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/SIC</entry>
+ <entry key="36.FriendlyName">RepresentativeSIC</entry>
+ <entry key="36.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="36.Required">false</entry>
+ <entry key="36.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="36.XmlType.LocalPart">SICType</entry>
+ <entry key="36.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="36.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+ <entry key="39.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/LegalPersonAddress</entry>
+ <entry key="39.FriendlyName">RepresentativeLegalAddress</entry>
+ <entry key="39.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="39.Required">false</entry>
+ <entry key="39.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="39.XmlType.LocalPart">LegalPersonAddressType</entry>
+ <entry key="39.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="39.AttributeValueMarshaller">eu.eidas.auth.commons.protocol.eidas.impl.RepvLegalAddressAttributeValueMarshaller</entry>
+
+ <entry key="40.NameUri">http://eidas.europa.eu/attributes/legalperson/representative/VATRegistrationNumber</entry>
+ <entry key="40.FriendlyName">RepresentativeVATRegistration</entry>
+ <entry key="40.PersonType">RepresentativeLegalPerson</entry>
+ <entry key="40.Required">false</entry>
+ <entry key="40.XmlType.NamespaceUri">http://eidas.europa.eu/attributes/legalperson/representative</entry>
+ <entry key="40.XmlType.LocalPart">VATRegistrationNumberType</entry>
+ <entry key="40.XmlType.NamespacePrefix">eidas-reprentative-legal</entry>
+ <entry key="40.AttributeValueMarshaller">eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller</entry>
+
+
+</properties>
diff --git a/modules/eidas_proxy-sevice/src/test/resources/config/junit_config_1.properties b/modules/eidas_proxy-sevice/src/test/resources/config/junit_config_1.properties
new file mode 100644
index 00000000..4f3b82b5
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/test/resources/config/junit_config_1.properties
@@ -0,0 +1,6 @@
+## Basic service configuration
+eidas.ms.context.url.prefix=http://localhost
+eidas.ms.context.url.request.validation=false
+
+eidas.ms.auth.eIDAS.node_v2.proxy.entityId=ownSpecificProxy
+eidas.ms.auth.eIDAS.node_v2.proxy.forward.endpoint=http://eidas.proxy/endpoint \ No newline at end of file
diff --git a/modules/eidas_proxy-sevice/src/test/resources/spring/SpringTest-context_basic_mapConfig.xml b/modules/eidas_proxy-sevice/src/test/resources/spring/SpringTest-context_basic_mapConfig.xml
new file mode 100644
index 00000000..fe9ff441
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/test/resources/spring/SpringTest-context_basic_mapConfig.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:tx="http://www.springframework.org/schema/tx"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
+ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
+
+ <context:annotation-config />
+
+ <bean id="dummyMapBasedConfiguration"
+ class="at.asitplus.eidas.specific.core.test.config.dummy.MsConnectorDummyConfigMap">
+ <constructor-arg value="/config/junit_config_1.properties" />
+ <property name="configRootDirSufix" value="src/test/resources/config" />
+ </bean>
+
+</beans> \ No newline at end of file
diff --git a/modules/eidas_proxy-sevice/src/test/resources/spring/SpringTest-context_basic_test.xml b/modules/eidas_proxy-sevice/src/test/resources/spring/SpringTest-context_basic_test.xml
new file mode 100644
index 00000000..9870d22a
--- /dev/null
+++ b/modules/eidas_proxy-sevice/src/test/resources/spring/SpringTest-context_basic_test.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:tx="http://www.springframework.org/schema/tx"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
+ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
+
+
+ <import resource="classpath:/SpringTest-context_authManager.xml" />
+ <import resource="classpath:/spring/eidas_proxy-service.beans.xml"/>
+
+ <bean id="springManagedSpecificProxyserviceCommunicationService"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.test.dummy.DummySpecificCommunicationService" />
+
+ <bean id="mvcGUIBuilderImpl"
+ class="at.gv.egiz.eaaf.core.impl.gui.builder.SpringMvcGuiFormBuilderImpl" />
+
+ <bean id="specificConnectorAttributesFileWithPath"
+ class="java.lang.String">
+ <constructor-arg
+ value="src/test/resources/config/eidas-attributes.xml" />
+ </bean>
+
+ <bean id="specificConnectorAdditionalAttributesFileWithPath"
+ class="java.lang.String">
+ <constructor-arg
+ value="src/test/resources/config/additional-attributes.xml" />
+ </bean>
+
+ <bean id="attributeRegistry"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.service.EidasAttributeRegistry">
+ <property name="eidasAttributesFile"
+ ref="specificConnectorAttributesFileWithPath" />
+ <property name="additionalAttributesFile"
+ ref="specificConnectorAdditionalAttributesFileWithPath" />
+ </bean>
+
+</beans> \ No newline at end of file