aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--.gitlab-ci.yml1
-rw-r--r--connector/src/main/resources/properties/status_messages_en.properties3
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/Constants.java4
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/ErnbEidData.java2
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/MergedRegisterSearchResult.java75
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/RegisterResult.java88
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/SimpleEidasData.java81
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/ernp/DummyErnpClient.java66
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/ernp/IErnpClient.java43
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/ManualFixNecessaryException.java38
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/WorkflowException.java33
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/AbstractEidProcessor.java136
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/CountrySpecificDetailSearchProcessor.java61
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/DeSpecificDetailSearchProcessor.java65
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/ItSpecificDetailSearchProcessor.java58
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/InitialSearchTask.java303
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveAuthnResponseTask.java2
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/utils/EidasResponseUtils.java209
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/zmr/DummyZmrClient.java65
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/zmr/IZmrClient.java43
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/resources/eIDAS.Authentication.process.xml4
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/resources/eidas_v2_auth.beans.xml18
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/EidasRequestPreProcessingSecondTest.java2
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/InitialSearchTaskFirstTest.java460
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/test/resources/SpringTest-context_tasks_test.xml17
26 files changed, 1740 insertions, 138 deletions
diff --git a/.gitignore b/.gitignore
index 9be35422..8090a34b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,3 +12,4 @@ target
.metadata
*.iml
notCommit
+.idea
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 81a4a4dd..5b324d5f 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -12,7 +12,6 @@ variables:
include:
- template: Dependency-Scanning.gitlab-ci.yml
- - template: Security/SAST.gitlab-ci.yml
- template: Secret-Detection.gitlab-ci.yml
stages:
diff --git a/connector/src/main/resources/properties/status_messages_en.properties b/connector/src/main/resources/properties/status_messages_en.properties
index 80228a47..c430fc90 100644
--- a/connector/src/main/resources/properties/status_messages_en.properties
+++ b/connector/src/main/resources/properties/status_messages_en.properties
@@ -6,6 +6,9 @@ eidas.04=Request contains no sessionToken. Authentication process stops
eidas.05=Received eIDAS response-message is not valid. Reason: {0}
eidas.06=LoA from eIDAS response-message {0} does not match to requested LoA
eidas.07=eIDAS Response attribute-validation FAILED. Attribute:{0} Reason: {1}
+eidas.08=An unexpected error occurred.
+eidas.09=An error occurred while loading your data from official registers. Please contact the support.
+
config.01=No configuration-file parameter found. Maybe Java SystemD parameter is missing
config.03=Can not load configuration from path {0} (See logs for more details)
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/Constants.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/Constants.java
index 83a2afa6..54f7f8fa 100644
--- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/Constants.java
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/Constants.java
@@ -32,6 +32,7 @@ public class Constants {
public static final String DATA_REQUESTED_LOA_LIST = "req_requestedLoA";
public static final String DATA_REQUESTED_LOA_COMPERISON = "req_requestedLoAComperision";
public static final String DATA_FULL_EIDAS_RESPONSE = "resp_fulleIDASResponse";
+ public static final String DATA_RESULT_MATCHING_BPK = "matching-result-bpk";
// templates for post-binding forwarding
public static final String TEMPLATE_POST_FORWARD_NAME = "eidas_node_forward.html";
@@ -137,6 +138,7 @@ public class Constants {
public static final String eIDAS_ATTR_PLACEOFBIRTH = "PlaceOfBirth";
public static final String eIDAS_ATTR_BIRTHNAME = "BirthName";
public static final String eIDAS_ATTR_CURRENTADDRESS = "CurrentAddress";
+ public static final String eIDAS_ATTR_TAXREFERENCE = "TaxReference";
public static final String eIDAS_ATTR_LEGALPERSONIDENTIFIER = "LegalPersonIdentifier";
public static final String eIDAS_ATTR_LEGALNAME = "LegalName";
@@ -169,4 +171,6 @@ public class Constants {
"AJZyj/+sdCMDRq9RkvbFcgSTVn/OfS8EUE81ddwP8MNuJ1kd1SWBUJPaQX2JLJHrL54mkOhrkhH2M/zcuOTu8nW9TOEg"
+ "XGjrRB/0HpiYKpV+VDJViyyc/GacNLxN4Anw4pima6gHYaJIw9hQkL/nuO2hyh8PGJd7rxeFXJmbLy+X";
+ public static final String COUNTRY_CODE_DE = "DE";
+ public static final String COUNTRY_CODE_IT = "IT";
}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/ErnbEidData.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/ErnbEidData.java
index 6c7eeb6b..b780d3e8 100644
--- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/ErnbEidData.java
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/ErnbEidData.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2018 A-SIT Plus GmbH
+ * Copyright 2020 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.
*
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/MergedRegisterSearchResult.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/MergedRegisterSearchResult.java
new file mode 100644
index 00000000..e147b8aa
--- /dev/null
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/MergedRegisterSearchResult.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2020 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.auth.eidas.v2.dao;
+
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.WorkflowException;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class MergedRegisterSearchResult {
+
+ final List<RegisterResult> resultsZmr;
+ final List<RegisterResult> resultsErnp;
+
+ public MergedRegisterSearchResult(List<RegisterResult> resultsZmr, List<RegisterResult> resultsErnp) {
+ this.resultsZmr = resultsZmr;
+ this.resultsErnp = resultsErnp;
+ }
+
+ public int getResultCount() {
+ return resultsZmr.size() + resultsErnp.size();
+ }
+
+ /**
+ * Verifies that there is only one match and returns the bpk.
+ *
+ * @return bpk bpk of the match
+ * @throws WorkflowException if multiple results have been found
+ */
+ public String getBpk() throws WorkflowException {
+ if (getResultCount() != 1) {
+ throw new WorkflowException("getResultCount() != 1");
+ }
+ return getResult().getBpk();
+ }
+
+ /**
+ * Returns the results, if there is exactly one, throws exception otherwise.
+ *
+ * @return The result
+ * @throws WorkflowException Results does not contain exactly one result
+ */
+ public RegisterResult getResult() throws WorkflowException {
+ if (getResultCount() != 1) {
+ throw new WorkflowException("getResultCount() != 1");
+ }
+ if (resultsZmr.size() == 1) {
+ return resultsZmr.get(0);
+ } else {
+ return resultsErnp.get(0);
+ }
+ }
+}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/RegisterResult.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/RegisterResult.java
new file mode 100644
index 00000000..1cc36fe9
--- /dev/null
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/RegisterResult.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2020 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.auth.eidas.v2.dao;
+
+import at.gv.e_government.reference.namespace.persondata._20020228.PostalAddressType;
+import lombok.Data;
+
+@Data
+public class RegisterResult {
+
+ // MDS
+ private String pseudonym;
+ private String givenName;
+ private String familyName;
+ private String dateOfBirth;
+
+ // additional attributes
+ private String placeOfBirth;
+ private String birthName;
+ private String taxNumber;
+ private PostalAddressType address;
+
+ private String bpk;
+
+ /**
+ * Register search result.
+ *
+ * @param bpk The bpk
+ * @param pseudonym The pseudonym
+ * @param givenName The givenName
+ * @param familyName The familyName
+ * @param dateOfBirth The dateOfBirth
+ */
+ public RegisterResult(String bpk, String pseudonym, String givenName, String familyName, String dateOfBirth) {
+ this.bpk = bpk;
+ this.pseudonym = pseudonym;
+ this.givenName = givenName;
+ this.familyName = familyName;
+ this.dateOfBirth = dateOfBirth;
+ }
+
+ /**
+ * Register search result.
+ *
+ * @param bpk The bpk
+ * @param pseudonym The pseudonym
+ * @param givenName The givenName
+ * @param familyName The familyName
+ * @param dateOfBirth The dateOfBirth
+ * @param placeOfBirth The placeOfBirth
+ * @param birthName The birthName
+ * @param taxNumber The taxNumber
+ * @param address The address
+ */
+ public RegisterResult(String bpk, String pseudonym, String givenName, String familyName, String dateOfBirth,
+ String placeOfBirth, String birthName, String taxNumber, PostalAddressType address) {
+ this.bpk = bpk;
+ this.pseudonym = pseudonym;
+ this.givenName = givenName;
+ this.familyName = familyName;
+ this.dateOfBirth = dateOfBirth;
+ this.placeOfBirth = placeOfBirth;
+ this.birthName = birthName;
+ this.taxNumber = taxNumber;
+ this.address = address;
+ }
+}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/SimpleEidasData.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/SimpleEidasData.java
new file mode 100644
index 00000000..57597122
--- /dev/null
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/SimpleEidasData.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2020 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.auth.eidas.v2.dao;
+
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.WorkflowException;
+import at.gv.e_government.reference.namespace.persondata._20020228.PostalAddressType;
+import lombok.Data;
+
+@Data
+public class SimpleEidasData {
+
+ private String citizenCountryCode;
+
+ // MDS
+ private String pseudonym;
+ private String givenName;
+ private String familyName;
+ private String dateOfBirth;
+
+ // additional attributes
+ private String placeOfBirth;
+ private String birthName;
+ private PostalAddressType address;
+ private String taxNumber;
+
+ /**
+ * Compares the register result with the eidas data.
+ * @param result The register data to use for comparison
+ * @return true or false depending of the data matches
+ * @throws WorkflowException if multiple results have been found
+ */
+ public boolean equalsRegisterData(MergedRegisterSearchResult result) throws WorkflowException {
+ return equalsRegisterData(result.getResult());
+ }
+
+ private boolean equalsRegisterData(RegisterResult result) {
+ if (!result.getPseudonym().equals(pseudonym)) {
+ return false;
+ }
+ if (!result.getGivenName().equals(givenName)) {
+ return false;
+ }
+ if (!result.getFamilyName().equals(familyName)) {
+ return false;
+ }
+ if (!result.getDateOfBirth().equals(dateOfBirth)) {
+ return false;
+ }
+ if (!result.getPlaceOfBirth().equals(placeOfBirth)) {
+ return false;
+ }
+ if (!result.getBirthName().equals(birthName)) {
+ return false;
+ }
+ if (!result.getTaxNumber().equals(taxNumber)) {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/ernp/DummyErnpClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/ernp/DummyErnpClient.java
new file mode 100644
index 00000000..e514c808
--- /dev/null
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/ernp/DummyErnpClient.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2020 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.auth.eidas.v2.ernp;
+
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.RegisterResult;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData;
+import org.springframework.stereotype.Service;
+
+import java.util.Collections;
+import java.util.List;
+
+@Service("ErnbClientForeIDAS")
+public class DummyErnpClient implements IErnpClient {
+
+ @Override
+ public List<RegisterResult> searchWithPersonIdentifier(String personIdentifier) {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public List<RegisterResult> searchWithMds(String givenName, String familyName, String dateOfBirth) {
+ //TODO will I only receive matches where all three values match perfectly?
+ return Collections.emptyList();
+ }
+
+ @Override
+ public List<RegisterResult> searchDeSpecific(String givenName, String familyName, String dateOfBirth,
+ String birthPlace, String birthName) {
+ //TODO
+ return Collections.emptyList();
+ }
+
+ @Override
+ public List<RegisterResult> searchItSpecific(String taxNumber) {
+ //TODO
+ return Collections.emptyList();
+ }
+
+ @Override
+ public void update(RegisterResult registerResult, SimpleEidasData eidData) {
+ //TODO
+ }
+
+
+}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/ernp/IErnpClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/ernp/IErnpClient.java
new file mode 100644
index 00000000..b9641c5c
--- /dev/null
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/ernp/IErnpClient.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2020 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.auth.eidas.v2.ernp;
+
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.RegisterResult;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData;
+
+import java.util.List;
+
+public interface IErnpClient {
+
+ List<RegisterResult> searchWithPersonIdentifier(String personIdentifier);
+
+ List<RegisterResult> searchWithMds(String givenName, String familyName, String dateOfBirth);
+
+ List<RegisterResult> searchDeSpecific(String givenName, String familyName, String dateOfBirth,
+ String birthPlace, String birthName);
+
+ List<RegisterResult> searchItSpecific(String taxNumber);
+
+ void update(RegisterResult registerResult, SimpleEidasData eidData);
+}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/ManualFixNecessaryException.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/ManualFixNecessaryException.java
new file mode 100644
index 00000000..2fecaa6b
--- /dev/null
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/ManualFixNecessaryException.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2020 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.auth.eidas.v2.exception;
+
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData;
+
+public class ManualFixNecessaryException extends EidasSAuthenticationException {
+ private static final long serialVersionUID = 1L;
+
+ public ManualFixNecessaryException(String personIdentifier) {
+ super("eidas.09", new Object[] { personIdentifier });
+ }
+
+ public ManualFixNecessaryException(SimpleEidasData eidData) {
+ super("eidas.09", new Object[] { eidData.getPseudonym() });//TODO what info to pass???
+ }
+}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/WorkflowException.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/WorkflowException.java
new file mode 100644
index 00000000..b6f3309b
--- /dev/null
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/WorkflowException.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2020 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.auth.eidas.v2.exception;
+
+public class WorkflowException extends EidasSAuthenticationException {
+ private static final long serialVersionUID = 1L;
+
+ public WorkflowException(String data) {
+ super("eidas.08", new Object[]{data});
+ }
+
+}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/AbstractEidProcessor.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/AbstractEidProcessor.java
index fe839c37..e3c1e00f 100644
--- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/AbstractEidProcessor.java
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/AbstractEidProcessor.java
@@ -23,18 +23,6 @@
package at.asitplus.eidas.specific.modules.auth.eidas.v2.handler;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.apache.commons.lang3.StringUtils;
-import org.joda.time.DateTime;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-
-import com.google.common.collect.ImmutableSortedSet;
-
import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ErnbEidData;
import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidPostProcessingException;
@@ -46,12 +34,21 @@ import at.gv.egiz.eaaf.core.api.IRequest;
import at.gv.egiz.eaaf.core.api.idp.IConfigurationWithSP;
import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration;
import at.gv.egiz.eaaf.core.impl.data.Triple;
+import com.google.common.collect.ImmutableSortedSet;
import edu.umd.cs.findbugs.annotations.NonNull;
import eu.eidas.auth.commons.attribute.AttributeDefinition;
import eu.eidas.auth.commons.attribute.ImmutableAttributeMap;
import eu.eidas.auth.commons.light.impl.LightRequest.Builder;
import eu.eidas.auth.commons.protocol.eidas.SpType;
-import eu.eidas.auth.commons.protocol.eidas.impl.PostalAddress;
+import org.apache.commons.lang3.StringUtils;
+import org.joda.time.DateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
public abstract class AbstractEidProcessor implements INationalEidProcessor {
private static final Logger log = LoggerFactory.getLogger(AbstractEidProcessor.class);
@@ -66,7 +63,6 @@ public abstract class AbstractEidProcessor implements INationalEidProcessor {
buildProviderNameAttribute(pendingReq, authnRequestBuilder);
buildRequestedAttributes(authnRequestBuilder);
-
}
@Override
@@ -91,13 +87,12 @@ public abstract class AbstractEidProcessor implements INationalEidProcessor {
result.setAddress(processAddress(eidasAttrMap.get(Constants.eIDAS_ATTR_CURRENTADDRESS)));
return result;
-
}
-
+
/**
* Get a Map of country-specific requested attributes.
- *
+ *
* @return
*/
@NonNull
@@ -105,7 +100,7 @@ public abstract class AbstractEidProcessor implements INationalEidProcessor {
/**
* Post-Process the eIDAS CurrentAddress attribute.
- *
+ *
* @param currentAddressObj eIDAS current address information
* @return current address or null if no attribute is available
* @throws EidPostProcessingException if post-processing fails
@@ -113,34 +108,12 @@ public abstract class AbstractEidProcessor implements INationalEidProcessor {
*/
protected PostalAddressType processAddress(Object currentAddressObj) throws EidPostProcessingException,
EidasAttributeException {
-
- if (currentAddressObj != null) {
- if (currentAddressObj instanceof PostalAddress) {
- final PostalAddressType result = new PostalAddressType();
- result.setPostalCode(((PostalAddress) currentAddressObj).getPostCode());
- result.setMunicipality(((PostalAddress) currentAddressObj).getPostName());
-
- // TODO: add more mappings
-
- return result;
-
- } else {
- log.warn("eIDAS attr: " + Constants.eIDAS_ATTR_CURRENTADDRESS + " is of WRONG type");
- throw new EidasAttributeException(Constants.eIDAS_ATTR_CURRENTADDRESS);
-
- }
-
- } else {
- log.debug("NO '" + Constants.eIDAS_ATTR_CURRENTADDRESS + "' attribute. Post-Processing skipped ... ");
- }
-
- return null;
-
+ return EidasResponseUtils.processAddress(currentAddressObj);
}
/**
* Post-Process the eIDAS BirthName attribute.
- *
+ *
* @param birthNameObj eIDAS birthname information
* @return birthName or null if no attribute is available
* @throws EidPostProcessingException if post-processing fails
@@ -148,27 +121,12 @@ public abstract class AbstractEidProcessor implements INationalEidProcessor {
*/
protected String processBirthName(Object birthNameObj) throws EidPostProcessingException,
EidasAttributeException {
- if (birthNameObj != null) {
- if (birthNameObj instanceof String) {
- return (String) birthNameObj;
-
- } else {
- log.warn("eIDAS attr: " + Constants.eIDAS_ATTR_BIRTHNAME + " is of WRONG type");
- throw new EidasAttributeException(Constants.eIDAS_ATTR_BIRTHNAME);
-
- }
-
- } else {
- log.debug("NO '" + Constants.eIDAS_ATTR_BIRTHNAME + "' attribute. Post-Processing skipped ... ");
- }
-
- return null;
-
+ return EidasResponseUtils.processBirthName(birthNameObj);
}
/**
* Post-Process the eIDAS PlaceOfBirth attribute.
- *
+ *
* @param placeOfBirthObj eIDAS Place-of-Birth information
* @return place of Birth or null if no attribute is available
* @throws EidPostProcessingException if post-processing fails
@@ -176,27 +134,12 @@ public abstract class AbstractEidProcessor implements INationalEidProcessor {
*/
protected String processPlaceOfBirth(Object placeOfBirthObj) throws EidPostProcessingException,
EidasAttributeException {
- if (placeOfBirthObj != null) {
- if (placeOfBirthObj instanceof String) {
- return (String) placeOfBirthObj;
-
- } else {
- log.warn("eIDAS attr: " + Constants.eIDAS_ATTR_PLACEOFBIRTH + " is of WRONG type");
- throw new EidasAttributeException(Constants.eIDAS_ATTR_PLACEOFBIRTH);
-
- }
-
- } else {
- log.debug("NO '" + Constants.eIDAS_ATTR_PLACEOFBIRTH + "' attribute. Post-Processing skipped ... ");
- }
-
- return null;
-
+ return EidasResponseUtils.processPlaceOfBirth(placeOfBirthObj);
}
/**
* Post-Process the eIDAS DateOfBirth attribute.
- *
+ *
* @param dateOfBirthObj eIDAS date-of-birth attribute information
* @return formated user's date-of-birth
* @throws EidasAttributeException if NO attribute is available
@@ -204,17 +147,12 @@ public abstract class AbstractEidProcessor implements INationalEidProcessor {
*/
protected DateTime processDateOfBirth(Object dateOfBirthObj) throws EidPostProcessingException,
EidasAttributeException {
- if (dateOfBirthObj == null || !(dateOfBirthObj instanceof DateTime)) {
- throw new EidasAttributeException(Constants.eIDAS_ATTR_DATEOFBIRTH);
- }
-
- return (DateTime) dateOfBirthObj;
-
+ return EidasResponseUtils.processDateOfBirth(dateOfBirthObj);
}
/**
* Post-Process the eIDAS GivenName attribute.
- *
+ *
* @param givenNameObj eIDAS givenName attribute information
* @return formated user's givenname
* @throws EidasAttributeException if NO attribute is available
@@ -222,17 +160,12 @@ public abstract class AbstractEidProcessor implements INationalEidProcessor {
*/
protected String processGivenName(Object givenNameObj) throws EidPostProcessingException,
EidasAttributeException {
- if (givenNameObj == null || !(givenNameObj instanceof String)) {
- throw new EidasAttributeException(Constants.eIDAS_ATTR_CURRENTGIVENNAME);
- }
-
- return (String) givenNameObj;
-
+ return EidasResponseUtils.processGivenName(givenNameObj);
}
/**
* Post-Process the eIDAS FamilyName attribute.
- *
+ *
* @param familyNameObj eIDAS familyName attribute information
* @return formated user's familyname
* @throws EidasAttributeException if NO attribute is available
@@ -240,17 +173,12 @@ public abstract class AbstractEidProcessor implements INationalEidProcessor {
*/
protected String processFamilyName(Object familyNameObj) throws EidPostProcessingException,
EidasAttributeException {
- if (familyNameObj == null || !(familyNameObj instanceof String)) {
- throw new EidasAttributeException(Constants.eIDAS_ATTR_CURRENTFAMILYNAME);
- }
-
- return (String) familyNameObj;
-
+ return EidasResponseUtils.processFamilyName(familyNameObj);
}
/**
* Post-Process the eIDAS pseudonym to ERnB unique identifier.
- *
+ *
* @param personalIdObj eIDAS PersonalIdentifierAttribute
* @return Unique personal identifier without country-code information
* @throws EidasAttributeException if NO attribute is available
@@ -258,15 +186,7 @@ public abstract class AbstractEidProcessor implements INationalEidProcessor {
*/
protected String processPseudonym(Object personalIdObj) throws EidPostProcessingException,
EidasAttributeException {
- if (personalIdObj == null || !(personalIdObj instanceof String)) {
- throw new EidasAttributeException(Constants.eIDAS_ATTR_PERSONALIDENTIFIER);
- }
-
- final Triple<String, String, String> eIdentifier =
- EidasResponseUtils.parseEidasPersonalIdentifier((String) personalIdObj);
-
- return eIdentifier.getThird();
-
+ return EidasResponseUtils.processPseudonym(personalIdObj);
}
private void buildRequestedAttributes(Builder authnRequestBuilder) {
@@ -332,8 +252,8 @@ public abstract class AbstractEidProcessor implements INationalEidProcessor {
final String providerName = pendingReq.getRawData(Constants.DATA_PROVIDERNAME, String.class);
if (StringUtils.isNotEmpty(providerName)
&& basicConfig.getBasicConfigurationBoolean(
- Constants.CONIG_PROPS_EIDAS_NODE_WORKAROUND_ADD_ALWAYS_PROVIDERNAME,
- false)) {
+ Constants.CONIG_PROPS_EIDAS_NODE_WORKAROUND_ADD_ALWAYS_PROVIDERNAME,
+ false)) {
authnRequestBuilder.providerName(providerName);
}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/CountrySpecificDetailSearchProcessor.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/CountrySpecificDetailSearchProcessor.java
new file mode 100644
index 00000000..c5b3b231
--- /dev/null
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/CountrySpecificDetailSearchProcessor.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2020 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.auth.eidas.v2.handler;
+
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.MergedRegisterSearchResult;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.ernp.IErnpClient;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.zmr.IZmrClient;
+
+public abstract class CountrySpecificDetailSearchProcessor {
+
+ protected IErnpClient ernbClient;
+ protected IZmrClient zmrClient;
+
+ public CountrySpecificDetailSearchProcessor(IErnpClient ernbClient, IZmrClient zmrClient) {
+ this.ernbClient = ernbClient;
+ this.zmrClient = zmrClient;
+ }
+
+ /**
+ * Get a friendlyName of this post-processor implementation.
+ *
+ * @return
+ */
+ public String getName() {
+ return this.getClass().getName();
+ }
+
+ /**
+ * Check if this postProcessor is sensitive for a specific country.
+ *
+ * @param countryCode of the eID data that should be processed
+ * @param eidData eID data
+ * @return true if this implementation can handle the country, otherwise false
+ */
+ public abstract boolean canHandle(String countryCode, SimpleEidasData eidData);
+
+ public abstract MergedRegisterSearchResult search(SimpleEidasData eidData);
+
+}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/DeSpecificDetailSearchProcessor.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/DeSpecificDetailSearchProcessor.java
new file mode 100644
index 00000000..544d5b0c
--- /dev/null
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/DeSpecificDetailSearchProcessor.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2020 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.auth.eidas.v2.handler;
+
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.MergedRegisterSearchResult;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.RegisterResult;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.ernp.IErnpClient;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.zmr.IZmrClient;
+
+import java.util.List;
+
+public class DeSpecificDetailSearchProcessor extends CountrySpecificDetailSearchProcessor {
+
+ public DeSpecificDetailSearchProcessor(IErnpClient ernbClient, IZmrClient zmrClient) {
+ super(ernbClient, zmrClient);
+ }
+
+ @Override
+ public boolean canHandle(String countryCode, SimpleEidasData eidData) {
+ if (!countryCode.equalsIgnoreCase(Constants.COUNTRY_CODE_DE)) {
+ return false;
+ }
+ if (eidData.getBirthName() == null || eidData.getBirthName().isEmpty()) {
+ return false;
+ }
+ if (eidData.getPlaceOfBirth() == null || eidData.getPlaceOfBirth().isEmpty()) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public MergedRegisterSearchResult search(SimpleEidasData eidData) {
+ List<RegisterResult> resultsZmr =
+ zmrClient.searchDeSpecific(eidData.getGivenName(), eidData.getFamilyName(), eidData.getDateOfBirth(),
+ eidData.getPlaceOfBirth(), eidData.getBirthName());
+ List<RegisterResult> resultsErnb =
+ ernbClient.searchDeSpecific(eidData.getGivenName(), eidData.getFamilyName(), eidData.getDateOfBirth(),
+ eidData.getPlaceOfBirth(), eidData.getBirthName());
+ return new MergedRegisterSearchResult(resultsZmr, resultsErnb);
+ }
+}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/ItSpecificDetailSearchProcessor.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/ItSpecificDetailSearchProcessor.java
new file mode 100644
index 00000000..370a111c
--- /dev/null
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/ItSpecificDetailSearchProcessor.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2020 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.auth.eidas.v2.handler;
+
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.MergedRegisterSearchResult;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.RegisterResult;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.ernp.IErnpClient;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.zmr.IZmrClient;
+
+import java.util.List;
+
+public class ItSpecificDetailSearchProcessor extends CountrySpecificDetailSearchProcessor {
+
+ public ItSpecificDetailSearchProcessor(IErnpClient ernbClient, IZmrClient zmrClient) {
+ super(ernbClient, zmrClient);
+ }
+
+ @Override
+ public boolean canHandle(String countryCode, SimpleEidasData eidData) {
+ if (!countryCode.equalsIgnoreCase(Constants.COUNTRY_CODE_IT)) {
+ return false;
+ }
+ if (eidData.getTaxNumber() == null || eidData.getTaxNumber().isEmpty()) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public MergedRegisterSearchResult search(SimpleEidasData eidData) {
+ List<RegisterResult> resultsZmr = zmrClient.searchItSpecific(eidData.getTaxNumber());
+ List<RegisterResult> resultsErnb = ernbClient.searchItSpecific(eidData.getTaxNumber());
+ return new MergedRegisterSearchResult(resultsZmr, resultsErnb);
+ }
+}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/InitialSearchTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/InitialSearchTask.java
new file mode 100644
index 00000000..fd9e93e0
--- /dev/null
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/InitialSearchTask.java
@@ -0,0 +1,303 @@
+/*
+ * Copyright 2020 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.auth.eidas.v2.tasks;
+
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.MergedRegisterSearchResult;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.RegisterResult;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.ernp.IErnpClient;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasAttributeException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.ManualFixNecessaryException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.WorkflowException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.handler.CountrySpecificDetailSearchProcessor;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.EidasResponseUtils;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.zmr.IZmrClient;
+import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;
+import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;
+import at.gv.egiz.eaaf.core.impl.data.Triple;
+import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper;
+import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import eu.eidas.auth.commons.attribute.AttributeDefinition;
+import eu.eidas.auth.commons.attribute.AttributeValue;
+import eu.eidas.auth.commons.light.ILightResponse;
+import eu.eidas.auth.commons.protocol.eidas.impl.PostalAddress;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.joda.time.DateTime;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Task that searches ErnP and ZMR before adding person to SZR.
+ *
+ * @author amarsalek
+ */
+@Slf4j
+@Component("InitialSearchTask")
+public class InitialSearchTask extends AbstractAuthServletTask {
+
+ private final List<CountrySpecificDetailSearchProcessor> handlers;
+ private final IErnpClient ernpClient;
+ private final IZmrClient zmrClient;
+
+ /**
+ * Constructor.
+ * @param handlers List of countrySpecificSearchProcessors
+ * @param ernpClient Ernp client
+ * @param zmrClient ZMR client
+ */
+ public InitialSearchTask(List<CountrySpecificDetailSearchProcessor> handlers, IErnpClient ernpClient,
+ IZmrClient zmrClient) {
+ this.ernpClient = ernpClient;
+ this.zmrClient = zmrClient;
+ this.handlers = handlers;
+ log.info("# " + handlers.size() + " country specific detail search services are registered");
+ }
+
+ @Override
+ public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response)
+ throws TaskExecutionException {
+ try {
+ final AuthProcessDataWrapper authProcessData = pendingReq.getSessionData(AuthProcessDataWrapper.class);
+ final ILightResponse eidasResponse = authProcessData
+ .getGenericDataFromSession(Constants.DATA_FULL_EIDAS_RESPONSE, ILightResponse.class);
+
+ final SimpleEidasData eidData = convertSimpleMapToSimpleData(convertEidasAttrToSimpleMap(
+ eidasResponse.getAttributes().getAttributeMap()));
+
+ String bpK = step2RegisterSearchWithPersonidentifier(eidData);
+ authProcessData.setGenericDataToSession(Constants.DATA_RESULT_MATCHING_BPK, bpK);
+ } catch (final Exception e) {
+ log.error("Initial search FAILED.", e);
+ throw new TaskExecutionException(pendingReq, "Initial search FAILED.", e);
+ }
+ }
+
+ private String step2RegisterSearchWithPersonidentifier(SimpleEidasData eidData) throws TaskExecutionException {
+ log.trace("Starting step2RegisterSearchWithPersonidentifier");
+ String personIdentifier = eidData.getPseudonym();
+ MergedRegisterSearchResult result = searchInZmrAndErnp(personIdentifier);
+ if (result.getResultCount() == 0) {
+ return step5CheckAndPerformCountrySpecificSearchIfPossible(result, eidData);
+ } else if (result.getResultCount() == 1) {
+ return step3CheckRegisterUpdateNecessary(result, eidData);
+ }
+ throw new TaskExecutionException(pendingReq, "Initial search - Kitt Process necessary.",
+ new ManualFixNecessaryException(personIdentifier));
+ }
+
+ private String step3CheckRegisterUpdateNecessary(MergedRegisterSearchResult result, SimpleEidasData eidData)
+ throws TaskExecutionException {
+ log.trace("Starting step3CheckRegisterUpdateNecessary");
+ try {
+ if (eidData.equalsRegisterData(result)) {
+ //No update necessary, just return bpk
+ return result.getBpk();
+ } else {
+ return step4UpdateRegisterData(result, eidData);
+ }
+ } catch (WorkflowException e) {
+ throw new TaskExecutionException(pendingReq, "Initial search - Kitt Process necessary.", e);
+ }
+ }
+
+ private String step4UpdateRegisterData(MergedRegisterSearchResult result,
+ SimpleEidasData eidData) throws WorkflowException {
+ log.trace("Starting step4UpdateRegisterData");
+ log.debug("Update " + result + " with " + eidData);
+ //TODO wann rechtlich möglich?
+
+ return result.getBpk();
+ }
+
+ private String step5CheckAndPerformCountrySpecificSearchIfPossible(
+ MergedRegisterSearchResult result, SimpleEidasData eidData) throws TaskExecutionException {
+ log.trace("Starting step5CheckAndPerformCountrySpecificSearchIfPossible");
+ String citizenCountry = eidData.getCitizenCountryCode();
+ CountrySpecificDetailSearchProcessor foundHandler = null;
+ for (final CountrySpecificDetailSearchProcessor el : handlers) {
+ if (el.canHandle(citizenCountry, eidData)) {
+ log.debug("Found suitable country specific search handler for " + citizenCountry
+ + " by using: " + el.getName());
+ foundHandler = el;
+ break;
+ }
+ }
+ if (foundHandler == null) {
+ return step8RegisterSearchWithMds(result, eidData);
+ } else {
+ return step6CountrySpecificSearch(foundHandler, result, eidData);
+ }
+ }
+
+ private String step6CountrySpecificSearch(CountrySpecificDetailSearchProcessor countrySpecificDetailSearchProcessor,
+ MergedRegisterSearchResult initialSearchResult, SimpleEidasData eidData)
+ throws TaskExecutionException {
+ log.trace("Starting step6CountrySpecificSearch");
+ MergedRegisterSearchResult countrySpecificDetailSearchResult =
+ countrySpecificDetailSearchProcessor.search(eidData);
+
+ switch (countrySpecificDetailSearchResult.getResultCount()) {
+ case 0:
+ return step8RegisterSearchWithMds(initialSearchResult, eidData);
+ case 1:
+ return step7aKittProcess(initialSearchResult, countrySpecificDetailSearchResult, eidData);
+ default:
+ throw new TaskExecutionException(pendingReq, "Detail search - Kitt Process necessary.",
+ new ManualFixNecessaryException(eidData));
+ }
+ }
+
+ private String step7aKittProcess(MergedRegisterSearchResult initialSearchResult,
+ MergedRegisterSearchResult countrySpecificDetailSearchResult,
+ SimpleEidasData eidData) throws TaskExecutionException {
+ log.trace("Starting step7aKittProcess");
+ try {
+ if (initialSearchResult.getResultCount() != 0) {
+ throw new WorkflowException("initialSearchResult.getResultCount() != 0");
+ }
+ if (countrySpecificDetailSearchResult.getResultCount() != 1) {
+ throw new WorkflowException("countrySpecificDetailSearchResult.getResultCount() != 1");
+ }
+ if (countrySpecificDetailSearchResult.getResultsZmr().size() == 1) {
+ zmrClient.update(countrySpecificDetailSearchResult.getResultsZmr().get(0), eidData);
+ }
+ if (countrySpecificDetailSearchResult.getResultsErnp().size() == 1) {
+ ernpClient.update(countrySpecificDetailSearchResult.getResultsErnp().get(0), eidData);
+ }
+ String bpK = countrySpecificDetailSearchResult.getBpk();
+ return bpK;
+ } catch (WorkflowException e) {
+ throw new TaskExecutionException(pendingReq, "Step7a failed.", e);
+ }
+ }
+
+ private String step8RegisterSearchWithMds(MergedRegisterSearchResult initialSearchResult,
+ SimpleEidasData eidData) {
+ log.trace("Starting step8RegisterSearchWithMds");
+ List<RegisterResult> resultsZmr =
+ zmrClient.searchWithMds(eidData.getGivenName(), eidData.getFamilyName(), eidData.getDateOfBirth());
+ List<RegisterResult> resultsErnp =
+ ernpClient.searchWithMds(eidData.getGivenName(), eidData.getFamilyName(), eidData.getDateOfBirth());
+ MergedRegisterSearchResult mdsSearchResult = new MergedRegisterSearchResult(resultsZmr, resultsErnp);
+ log.debug("Automerge " + initialSearchResult + " with " + eidData + " " + mdsSearchResult);
+ //TODO implement next phase and return correct value
+ return "TODO-Temporary-Endnode-105";
+ }
+
+ private MergedRegisterSearchResult searchInZmrAndErnp(String personIdentifier) {
+ List<RegisterResult> resultsZmr = zmrClient.searchWithPersonIdentifier(personIdentifier);
+ List<RegisterResult> resultsErnp = ernpClient.searchWithPersonIdentifier(personIdentifier);
+ return new MergedRegisterSearchResult(resultsZmr, resultsErnp);
+ }
+
+ private SimpleEidasData convertSimpleMapToSimpleData(Map<String, Object> eidasAttrMap)
+ throws EidasAttributeException {
+ SimpleEidasData simpleEidasData = new SimpleEidasData();
+
+ final Object eIdentifierObj = eidasAttrMap.get(Constants.eIDAS_ATTR_PERSONALIDENTIFIER);
+ final Triple<String, String, String> eIdentifier =
+ EidasResponseUtils.parseEidasPersonalIdentifier((String) eIdentifierObj);
+ if (eIdentifier == null) {
+ throw new EidasAttributeException("Error processing eIdentifier");
+ }
+ simpleEidasData.setCitizenCountryCode(eIdentifier.getFirst());
+
+ // MDS attributes
+ simpleEidasData.setPseudonym(EidasResponseUtils.processPseudonym(
+ eidasAttrMap.get(Constants.eIDAS_ATTR_PERSONALIDENTIFIER)));
+ simpleEidasData.setFamilyName(EidasResponseUtils.processFamilyName(
+ eidasAttrMap.get(Constants.eIDAS_ATTR_CURRENTFAMILYNAME)));
+ simpleEidasData.setGivenName(EidasResponseUtils.processGivenName(
+ eidasAttrMap.get(Constants.eIDAS_ATTR_CURRENTGIVENNAME)));
+ simpleEidasData.setDateOfBirth(EidasResponseUtils.processDateOfBirthToString(
+ eidasAttrMap.get(Constants.eIDAS_ATTR_DATEOFBIRTH)));
+
+ // additional attributes
+ simpleEidasData.setPlaceOfBirth(EidasResponseUtils.processPlaceOfBirth(
+ eidasAttrMap.get(Constants.eIDAS_ATTR_PLACEOFBIRTH)));
+ simpleEidasData.setBirthName(EidasResponseUtils.processBirthName(
+ eidasAttrMap.get(Constants.eIDAS_ATTR_BIRTHNAME)));
+ simpleEidasData.setAddress(EidasResponseUtils.processAddress(
+ eidasAttrMap.get(Constants.eIDAS_ATTR_CURRENTADDRESS)));
+
+ if (eidasAttrMap.containsKey(Constants.eIDAS_ATTR_TAXREFERENCE)) {
+ simpleEidasData.setTaxNumber(EidasResponseUtils.processTaxReference(
+ eidasAttrMap.get(Constants.eIDAS_ATTR_TAXREFERENCE)));
+ }
+
+ //TODO other additional attributes
+ return simpleEidasData;
+ }
+
+ private Map<String, Object> convertEidasAttrToSimpleMap(
+ ImmutableMap<AttributeDefinition<?>, ImmutableSet<? extends AttributeValue<?>>> attributeMap) {
+ final Map<String, Object> result = new HashMap<>();
+
+ for (final AttributeDefinition<?> el : attributeMap.keySet()) {
+
+ final Class<?> parameterizedType = el.getParameterizedType();
+ if (DateTime.class.equals(parameterizedType)) {
+ final DateTime attribute = EidasResponseUtils.translateDateAttribute(el, attributeMap.get(el).asList());
+ if (attribute != null) {
+ result.put(el.getFriendlyName(), attribute);
+ log.trace("Find attr '" + el.getFriendlyName() + "' with value: " + attribute.toString());
+
+ } else {
+ log.info("Ignore empty 'DateTime' attribute");
+ }
+ } else if (PostalAddress.class.equals(parameterizedType)) {
+ final PostalAddress addressAttribute = EidasResponseUtils
+ .translateAddressAttribute(el, attributeMap.get(el).asList());
+ if (addressAttribute != null) {
+ result.put(el.getFriendlyName(), addressAttribute);
+ log.trace("Find attr '" + el.getFriendlyName() + "' with value: " + addressAttribute.toString());
+
+ } else {
+ log.info("Ignore empty 'PostalAddress' attribute");
+ }
+ } else {
+ final List<String> natPersonIdObj = EidasResponseUtils
+ .translateStringListAttribute(el, attributeMap.get(el).asList());
+ final String stringAttr = natPersonIdObj.get(0);
+ if (StringUtils.isNotEmpty(stringAttr)) {
+ result.put(el.getFriendlyName(), stringAttr);
+ log.trace("Find attr '" + el.getFriendlyName() + "' with value: " + stringAttr);
+ } else {
+ log.info("Ignore empty 'String' attribute");
+ }
+ }
+ }
+ log.debug("Receive #" + result.size() + " attributes with names: " + result.keySet().toString());
+ return result;
+ }
+}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveAuthnResponseTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveAuthnResponseTask.java
index 684546f7..0f733e8d 100644
--- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveAuthnResponseTask.java
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveAuthnResponseTask.java
@@ -94,7 +94,7 @@ public class ReceiveAuthnResponseTask extends AbstractAuthServletTask {
attrRegistry);
// **********************************************************
- // ******* Store resonse infos into session object **********
+ // ******* Store response infos into session object **********
// **********************************************************
// update MOA-Session data with received information
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/utils/EidasResponseUtils.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/utils/EidasResponseUtils.java
index ebd2ae78..aafcd8b9 100644
--- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/utils/EidasResponseUtils.java
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/utils/EidasResponseUtils.java
@@ -23,28 +23,28 @@
package at.asitplus.eidas.specific.modules.auth.eidas.v2.utils;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.annotation.Nullable;
-
-import org.apache.commons.lang3.StringUtils;
-import org.joda.time.DateTime;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.ImmutableList;
-
import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasAttributeException;
+import at.gv.e_government.reference.namespace.persondata._20020228.PostalAddressType;
import at.gv.egiz.eaaf.core.impl.data.Triple;
+import com.google.common.collect.ImmutableList;
import eu.eidas.auth.commons.attribute.AttributeDefinition;
import eu.eidas.auth.commons.attribute.AttributeValue;
import eu.eidas.auth.commons.attribute.AttributeValueMarshaller;
import eu.eidas.auth.commons.attribute.AttributeValueMarshallingException;
import eu.eidas.auth.commons.attribute.AttributeValueTransliterator;
import eu.eidas.auth.commons.protocol.eidas.impl.PostalAddress;
+import org.apache.commons.lang3.StringUtils;
+import org.joda.time.DateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nullable;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
public class EidasResponseUtils {
private static final Logger log = LoggerFactory.getLogger(EidasResponseUtils.class);
@@ -54,7 +54,7 @@ public class EidasResponseUtils {
/**
* Validate a eIDAS PersonalIdentifier attribute value This validation is done
* according to eIDAS SAML Attribute Profile - Section 2.2.3 Unique Identifier
- *
+ *
* @param uniqueID eIDAS attribute value of a unique identifier
* @return true if the uniqueID matches to eIDAS to Unique Identifier
* specification, otherwise false
@@ -70,9 +70,9 @@ public class EidasResponseUtils {
* Parse an eIDAS PersonalIdentifier attribute value into it components. This
* processing is done according to eIDAS SAML Attribute Profile - Section 2.2.3
* Unique Identifier
- *
+ *
* @param uniqueID eIDAS attribute value of a unique identifier
- * @return {@link Trible} that contains: <br>
+ * @return {@link Triple} that contains: <br>
* First : citizen country <br>
* Second: destination country <br>
* Third : unique identifier <br>
@@ -80,7 +80,7 @@ public class EidasResponseUtils {
*/
public static Triple<String, String, String> parseEidasPersonalIdentifier(String uniqueID) {
if (!validateEidasPersonalIdentifier(uniqueID)) {
- log.error("eIDAS attribute value for {} looks wrong formated. Value: {}",
+ log.error("eIDAS attribute value for {} looks wrong formated. Value: {}",
Constants.eIDAS_ATTR_PERSONALIDENTIFIER, uniqueID);
return null;
@@ -90,11 +90,11 @@ public class EidasResponseUtils {
}
/**
- * Get eIDAS attribute-values from eIDAS Node attributes.
- *
+ * Get eIDAS attribute-values from eIDAS Node attributes.
+ *
* @param attributeDefinition eIDAS attribute definition
* @param attributeValues Attributes from eIDAS response
- * @return Set of attribute values. If more then one value than the first value contains the 'Latin' value.
+ * @return Set of attribute values. If more then one value than the first value contains the 'Latin' value.
*/
// TODO: check possible problem with nonLatinCharacters
public static List<String> translateStringListAttribute(AttributeDefinition<?> attributeDefinition,
@@ -109,7 +109,7 @@ public class EidasResponseUtils {
log.trace("Find attr: {} with value: {} nonLatinFlag: {} needTransliteration: {}",
attributeDefinition.getFriendlyName(), attributeValue.toString(),
- attributeValue.isNonLatinScriptAlternateVersion(),
+ attributeValue.isNonLatinScriptAlternateVersion(),
AttributeValueTransliterator.needsTransliteration(valueString));
// if (attributeValue.isNonLatinScriptAlternateVersion()) {
@@ -128,7 +128,7 @@ public class EidasResponseUtils {
}
}
- log.trace("Extract values: {} for attr: {}",
+ log.trace("Extract values: {} for attr: {}",
StringUtils.join(stringListAttribute, ","), attributeDefinition.getFriendlyName());
return stringListAttribute;
@@ -136,8 +136,8 @@ public class EidasResponseUtils {
}
/**
- * Convert eIDAS DateTime attribute to Java Object.
- *
+ * Convert eIDAS DateTime attribute to Java Object.
+ *
* @param attributeDefinition eIDAS attribute definition.
* @param attributeValues eIDAS attribute value
* @return
@@ -156,7 +156,7 @@ public class EidasResponseUtils {
/**
* Concert eIDAS Address attribute to Java object.
- *
+ *
* @param attributeDefinition eIDAS attribute definition
* @param attributeValues eIDAS attribute value
* @return
@@ -166,7 +166,164 @@ public class EidasResponseUtils {
ImmutableList<? extends AttributeValue<?>> attributeValues) {
final AttributeValue<?> firstAttributeValue = attributeValues.get(0);
return (PostalAddress) firstAttributeValue.getValue();
+ }
+
+ /**
+ * Post-Process the eIDAS CurrentAddress attribute.
+ *
+ * @param currentAddressObj eIDAS current address information
+ * @return current address or null if no attribute is available
+ * @throws EidasAttributeException if eIDAS attribute is of a wrong type
+ */
+ public static PostalAddressType processAddress(Object currentAddressObj) throws EidasAttributeException {
+ if (currentAddressObj != null) {
+ if (currentAddressObj instanceof PostalAddress) {
+ final PostalAddressType result = new PostalAddressType();
+ result.setPostalCode(((PostalAddress) currentAddressObj).getPostCode());
+ result.setMunicipality(((PostalAddress) currentAddressObj).getPostName());
+ // TODO: add more mappings
+ return result;
+ } else {
+ log.warn("eIDAS attr: " + Constants.eIDAS_ATTR_CURRENTADDRESS + " is of WRONG type");
+ throw new EidasAttributeException(Constants.eIDAS_ATTR_CURRENTADDRESS);
+ }
+ } else {
+ log.debug("NO '" + Constants.eIDAS_ATTR_CURRENTADDRESS + "' attribute. Post-Processing skipped ... ");
+ }
+ return null;
+ }
+
+ /**
+ * Post-Process the eIDAS BirthName attribute.
+ *
+ * @param birthNameObj eIDAS birthname information
+ * @return birthName or null if no attribute is available
+ * @throws EidasAttributeException if eIDAS attribute is of a wrong type
+ */
+ public static String processBirthName(Object birthNameObj) throws EidasAttributeException {
+ if (birthNameObj != null) {
+ if (birthNameObj instanceof String) {
+ return (String) birthNameObj;
+ } else {
+ log.warn("eIDAS attr: " + Constants.eIDAS_ATTR_BIRTHNAME + " is of WRONG type");
+ throw new EidasAttributeException(Constants.eIDAS_ATTR_BIRTHNAME);
+ }
+ } else {
+ log.debug("NO '" + Constants.eIDAS_ATTR_BIRTHNAME + "' attribute. Post-Processing skipped ... ");
+ }
+ return null;
+ }
+
+ /**
+ * Post-Process the eIDAS PlaceOfBirth attribute.
+ *
+ * @param placeOfBirthObj eIDAS Place-of-Birth information
+ * @return place of Birth or null if no attribute is available
+ * @throws EidasAttributeException if eIDAS attribute is of a wrong type
+ */
+ public static String processPlaceOfBirth(Object placeOfBirthObj) throws EidasAttributeException {
+ if (placeOfBirthObj != null) {
+ if (placeOfBirthObj instanceof String) {
+ return (String) placeOfBirthObj;
+
+ } else {
+ log.warn("eIDAS attr: " + Constants.eIDAS_ATTR_PLACEOFBIRTH + " is of WRONG type");
+ throw new EidasAttributeException(Constants.eIDAS_ATTR_PLACEOFBIRTH);
+
+ }
+
+ } else {
+ log.debug("NO '" + Constants.eIDAS_ATTR_PLACEOFBIRTH + "' attribute. Post-Processing skipped ... ");
+ }
+ return null;
+ }
+
+ /**
+ * Post-Process the eIDAS DateOfBirth attribute.
+ *
+ * @param dateOfBirthObj eIDAS date-of-birth attribute information
+ * @return formated user's date-of-birth
+ * @throws EidasAttributeException if NO attribute is available
+ */
+ public static DateTime processDateOfBirth(Object dateOfBirthObj) throws EidasAttributeException {
+ if (!(dateOfBirthObj instanceof DateTime)) {
+ throw new EidasAttributeException(Constants.eIDAS_ATTR_DATEOFBIRTH);
+ }
+ return (DateTime) dateOfBirthObj;
+ }
+ /**
+ * Post-Process the eIDAS DateOfBirth attribute to a string.
+ *
+ * @param dateOfBirthObj eIDAS date-of-birth attribute information
+ * @return formated user's date-of-birth as string
+ * @throws EidasAttributeException if NO attribute is available
+ */
+ public static String processDateOfBirthToString(Object dateOfBirthObj) throws EidasAttributeException {
+ if (!(dateOfBirthObj instanceof DateTime)) {
+ throw new EidasAttributeException(Constants.eIDAS_ATTR_DATEOFBIRTH);
+ }
+ return new SimpleDateFormat("yyyy-MM-dd").format(((DateTime) dateOfBirthObj).toDate());
}
+ /**
+ * Post-Process the eIDAS GivenName attribute.
+ *
+ * @param givenNameObj eIDAS givenName attribute information
+ * @return formated user's givenname
+ * @throws EidasAttributeException if NO attribute is available
+ */
+ public static String processGivenName(Object givenNameObj) throws EidasAttributeException {
+ if (!(givenNameObj instanceof String)) {
+ throw new EidasAttributeException(Constants.eIDAS_ATTR_CURRENTGIVENNAME);
+ }
+ return (String) givenNameObj;
+ }
+
+ /**
+ * Post-Process the eIDAS FamilyName attribute.
+ *
+ * @param familyNameObj eIDAS familyName attribute information
+ * @return formated user's familyname
+ * @throws EidasAttributeException if NO attribute is available
+ */
+ public static String processFamilyName(Object familyNameObj) throws EidasAttributeException {
+ if (!(familyNameObj instanceof String)) {
+ throw new EidasAttributeException(Constants.eIDAS_ATTR_CURRENTFAMILYNAME);
+ }
+ return (String) familyNameObj;
+ }
+
+ /**
+ * Post-Process the eIDAS pseudonym to ERnB unique identifier.
+ *
+ * @param personalIdObj eIDAS PersonalIdentifierAttribute
+ * @return Unique personal identifier without country-code information
+ * @throws EidasAttributeException if NO attribute is available
+ */
+ public static String processPseudonym(Object personalIdObj) throws EidasAttributeException {
+ if (!(personalIdObj instanceof String)) {
+ throw new EidasAttributeException(Constants.eIDAS_ATTR_PERSONALIDENTIFIER);
+ }
+ final Triple<String, String, String> eIdentifier =
+ EidasResponseUtils.parseEidasPersonalIdentifier((String) personalIdObj);
+ if (eIdentifier == null || eIdentifier.getThird() == null) {
+ throw new EidasAttributeException("Error processing eIdentifier");
+ }
+ return eIdentifier.getThird();
+ }
+
+ /**
+ * Post-Process the eIDAS TaxReference attribute.
+ *
+ * @param taxReferenceObj eIDAS TaxReference attribute information
+ * @return formated user's TaxReference
+ * @throws EidasAttributeException if NO attribute is available
+ */
+ public static String processTaxReference(Object taxReferenceObj) throws EidasAttributeException {
+ if (!(taxReferenceObj instanceof String)) {
+ throw new EidasAttributeException(Constants.eIDAS_ATTR_CURRENTGIVENNAME);
+ }
+ return (String) taxReferenceObj;
+ }
}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/zmr/DummyZmrClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/zmr/DummyZmrClient.java
new file mode 100644
index 00000000..b12c1bcb
--- /dev/null
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/zmr/DummyZmrClient.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2020 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.auth.eidas.v2.zmr;
+
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.RegisterResult;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData;
+import org.springframework.stereotype.Service;
+
+import java.util.Collections;
+import java.util.List;
+
+@Service("ZmrClientForeIDAS")
+public class DummyZmrClient implements IZmrClient {
+
+ @Override
+ public List<RegisterResult> searchWithPersonIdentifier(String personIdentifier) {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public List<RegisterResult> searchWithMds(String givenName, String familyName, String dateOfBirth) {
+ //TODO will I only receive matches where all three values match perfectly?
+ return Collections.emptyList();
+ }
+
+ @Override
+ public List<RegisterResult> searchDeSpecific(String givenName, String familyName, String dateOfBirth,
+ String birthPlace, String birthName) {
+ //TODO
+ return Collections.emptyList();
+ }
+
+ @Override
+ public List<RegisterResult> searchItSpecific(String taxNumber) {
+ //TODO
+ return Collections.emptyList();
+ }
+
+ @Override
+ public void update(RegisterResult registerResult, SimpleEidasData eidData) {
+ //TODO
+ }
+
+}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/zmr/IZmrClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/zmr/IZmrClient.java
new file mode 100644
index 00000000..5175cd7b
--- /dev/null
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/zmr/IZmrClient.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2020 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.auth.eidas.v2.zmr;
+
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.RegisterResult;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData;
+
+import java.util.List;
+
+public interface IZmrClient {
+
+ List<RegisterResult> searchWithPersonIdentifier(String personIdentifier);
+
+ List<RegisterResult> searchWithMds(String givenName, String familyName, String dateOfBirth);
+
+ List<RegisterResult> searchDeSpecific(String givenName, String familyName, String dateOfBirth,
+ String birthPlace, String birthName);
+
+ List<RegisterResult> searchItSpecific(String taxNumber);
+
+ void update(RegisterResult registerResult, SimpleEidasData eidData);
+}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/resources/eIDAS.Authentication.process.xml b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/eIDAS.Authentication.process.xml
index 55bb1ace..e199d379 100644
--- a/eidas_modules/authmodule-eIDAS-v2/src/main/resources/eIDAS.Authentication.process.xml
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/eIDAS.Authentication.process.xml
@@ -10,6 +10,8 @@
class="FinalizeAuthenticationTask" />
<pd:Task id="generateIdentityLink"
class="CreateIdentityLinkTask" />
+ <pd:Task id="initialRegisterSearch"
+ class="InitialSearchTask" />
<pd:StartEvent id="start" />
@@ -18,6 +20,8 @@
<pd:Transition from="createAuthnRequest"
to="receiveAuthnResponse" />
<pd:Transition from="receiveAuthnResponse"
+ to="initialRegisterSearch" />
+ <pd:Transition from="initialRegisterSearch"
to="generateIdentityLink" />
<pd:Transition from="generateIdentityLink"
to="finalizeAuthentication" />
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/resources/eidas_v2_auth.beans.xml b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/eidas_v2_auth.beans.xml
index 6cc704ab..52404bab 100644
--- a/eidas_modules/authmodule-eIDAS-v2/src/main/resources/eidas_v2_auth.beans.xml
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/eidas_v2_auth.beans.xml
@@ -17,6 +17,12 @@
<bean id="SZRClientForeIDAS"
class="at.asitplus.eidas.specific.modules.auth.eidas.v2.szr.SzrClient" />
+ <bean id="ErnbClientForeIDAS"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.ernp.DummyErnpClient" />
+
+ <bean id="ZmrClientForeIDAS"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.zmr.DummyZmrClient" />
+
<bean id="specificConnectorAttributesFile"
class="java.lang.String">
<constructor-arg value="eidas-attributes.xml" />
@@ -74,6 +80,14 @@
<property name="priority" value="0" />
</bean>
+ <bean id="DE-Specific-Search"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.handler.DeSpecificDetailSearchProcessor">
+ </bean>
+
+ <bean id="IT-Specific-Search"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.handler.ItSpecificDetailSearchProcessor">
+ </bean>
+
<!-- Authentication Process Tasks -->
<bean id="ConnecteIDASNodeTask"
class="at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.GenerateAuthnRequestTask"
@@ -87,4 +101,8 @@
class="at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.CreateIdentityLinkTask"
scope="prototype" />
+ <bean id="InitialSearchTask"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.InitialSearchTask"
+ scope="prototype" />
+
</beans> \ No newline at end of file
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/EidasRequestPreProcessingSecondTest.java b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/EidasRequestPreProcessingSecondTest.java
index da7e3d85..e7bacded 100644
--- a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/EidasRequestPreProcessingSecondTest.java
+++ b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/EidasRequestPreProcessingSecondTest.java
@@ -107,7 +107,7 @@ public class EidasRequestPreProcessingSecondTest {
final LightRequest lightReq = authnRequestBuilder.build();
- Assert.assertEquals("ProviderName is not Static", "myNode", lightReq.getProviderName());
+ Assert.assertEquals("ProviderName is not Static", "myNode", lightReq.getProviderName());//Fixme "myNode"
Assert.assertEquals("no PublicSP", "public", lightReq.getSpType());
Assert.assertEquals("Requested attribute size not match", 8, lightReq.getRequestedAttributes().size());
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/InitialSearchTaskFirstTest.java b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/InitialSearchTaskFirstTest.java
new file mode 100644
index 00000000..9f58ba71
--- /dev/null
+++ b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/InitialSearchTaskFirstTest.java
@@ -0,0 +1,460 @@
+/*
+ * Copyright 2020 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.auth.eidas.v2.test.tasks;
+
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.RegisterResult;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.ernp.IErnpClient;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.ManualFixNecessaryException;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.handler.DeSpecificDetailSearchProcessor;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.handler.ItSpecificDetailSearchProcessor;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.InitialSearchTask;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.zmr.IZmrClient;
+import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;
+import at.gv.egiz.eaaf.core.exceptions.EaafStorageException;
+import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;
+import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl;
+import at.gv.egiz.eaaf.core.impl.idp.process.ExecutionContextImpl;
+import eu.eidas.auth.commons.attribute.AttributeDefinition;
+import eu.eidas.auth.commons.attribute.ImmutableAttributeMap;
+import eu.eidas.auth.commons.attribute.PersonType;
+import eu.eidas.auth.commons.protocol.impl.AuthenticationResponse;
+import lombok.val;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.jetbrains.annotations.NotNull;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.annotation.DirtiesContext.ClassMode;
+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 javax.xml.namespace.QName;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Random;
+
+import static org.junit.Assert.assertThrows;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration("/SpringTest-context_tasks_test.xml")
+@DirtiesContext(classMode = ClassMode.BEFORE_CLASS)
+public class InitialSearchTaskFirstTest {
+
+ private static final String DE_ST = "de/st/";
+ private static final String IT_ST = "it/st/";
+
+ private InitialSearchTask task;
+ @Mock
+ private IZmrClient zmrClient;
+ @Mock
+ private IErnpClient ernpClient;
+
+ final ExecutionContext executionContext = new ExecutionContextImpl();
+ private TestRequestImpl pendingReq;
+ private final String randomBpk = RandomStringUtils.randomNumeric(6);
+ private final String randomIdentifier = RandomStringUtils.randomNumeric(10);
+ private final String randomPseudonym = DE_ST + randomIdentifier;
+ private final String randomFamilyName = RandomStringUtils.randomAlphabetic(10);
+ private final String randomGivenName = RandomStringUtils.randomAlphabetic(10);
+ private final String randomPlaceOfBirth = RandomStringUtils.randomAlphabetic(10);
+ private final String randomBirthName = RandomStringUtils.randomAlphabetic(10);
+ private final String randomDate = "2011-01-" + (10 + new Random().nextInt(18));
+
+ /**
+ * jUnit class initializer.
+ *
+ * @throws IOException In case of an error
+ */
+ @BeforeClass
+ public static void classInitializer() throws IOException {
+ final String current = new java.io.File(".").toURI().toString();
+ System.setProperty("eidas.ms.configuration", current
+ + "src/test/resources/config/junit_config_1.properties");
+ }
+
+ /**
+ * jUnit test set-up.
+ */
+ @Before
+ public void setUp() throws URISyntaxException, EaafStorageException {
+ MockitoAnnotations.initMocks(this);
+ task = new InitialSearchTask(new ArrayList<>(), ernpClient, zmrClient);
+
+ MockHttpServletRequest httpReq = new MockHttpServletRequest("POST", "https://localhost/authhandler");
+ MockHttpServletResponse httpResp = new MockHttpServletResponse();
+ RequestContextHolder.resetRequestAttributes();
+ RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpReq, httpResp));
+
+ final AuthenticationResponse response = buildDummyAuthResponseRandomPerson();
+ pendingReq = new TestRequestImpl();
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(Constants.DATA_FULL_EIDAS_RESPONSE, response);
+ }
+
+ /**
+ * One match, but register update needed
+ */
+ @Test
+ @DirtiesContext
+ public void testNode100_UserIdentifiedUpdateNecessary_a() throws Exception {
+ String newFirstName = RandomStringUtils.randomAlphabetic(10);
+ Mockito.when(zmrClient.searchWithPersonIdentifier(randomIdentifier)).thenReturn(Collections.singletonList(
+ new RegisterResult(randomBpk, randomPseudonym, newFirstName, randomFamilyName, randomDate)));
+ Mockito.when(ernpClient.searchWithPersonIdentifier(randomIdentifier)).thenReturn(Collections.emptyList());
+
+ task.execute(pendingReq, executionContext);
+ String bPk = (String)
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .getGenericDataFromSession(Constants.DATA_RESULT_MATCHING_BPK);
+
+ Assert.assertEquals("Wrong bpk", bPk, randomBpk);
+ }
+
+ /**
+ * One match, but register update needed
+ */
+ @Test
+ @DirtiesContext
+ public void testNode100_UserIdentifiedUpdateNecessary_b() throws TaskExecutionException {
+ Mockito.when(zmrClient.searchWithPersonIdentifier(randomIdentifier)).thenReturn(Collections.emptyList());
+ String newRandomGivenName = RandomStringUtils.randomAlphabetic(10);
+ Mockito.when(ernpClient.searchWithPersonIdentifier(randomIdentifier)).thenReturn(Collections.singletonList(
+ new RegisterResult(randomBpk, randomPseudonym, newRandomGivenName, randomFamilyName, randomDate)));
+
+ task.execute(pendingReq, executionContext);
+ String bPk = (String)
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .getGenericDataFromSession(Constants.DATA_RESULT_MATCHING_BPK);
+
+ Assert.assertEquals("Wrong bpk", bPk, randomBpk);
+ }
+
+ /**
+ * Two matches found in ZMR
+ */
+ @Test
+ @DirtiesContext
+ public void testNode101_ManualFixNecessary_a() {
+ ArrayList<RegisterResult> zmrResult = new ArrayList<>();
+ zmrResult.add(new RegisterResult(randomBpk, randomPseudonym, randomGivenName, randomFamilyName, randomDate));
+ String newRandomGivenName = randomGivenName + RandomStringUtils.randomAlphabetic(2);
+ zmrResult.add(new RegisterResult(randomBpk, randomPseudonym, newRandomGivenName, randomFamilyName, randomDate));
+ Mockito.when(zmrClient.searchWithPersonIdentifier(randomIdentifier)).thenReturn(zmrResult);
+ Mockito.when(ernpClient.searchWithPersonIdentifier(randomIdentifier)).thenReturn(Collections.emptyList());
+
+ TaskExecutionException exception = assertThrows(TaskExecutionException.class,
+ () -> task.execute(pendingReq, executionContext));
+
+ Throwable origE = exception.getOriginalException();
+ Assert.assertTrue("Wrong exception", (origE.getCause() instanceof ManualFixNecessaryException));
+ }
+
+
+ /**
+ * Two matches found in ErnP
+ */
+ @Test
+ @DirtiesContext
+ public void testNode101_ManualFixNecessary_b() {
+ Mockito.when(zmrClient.searchWithPersonIdentifier(randomIdentifier)).thenReturn(Collections.emptyList());
+ ArrayList<RegisterResult> ernpResult = new ArrayList<>();
+ ernpResult.add(new RegisterResult(randomBpk, randomPseudonym, randomGivenName, randomFamilyName, randomDate));
+ String newRandomGivenName = randomGivenName + RandomStringUtils.randomAlphabetic(2);
+ ernpResult.add(
+ new RegisterResult(randomBpk, randomPseudonym, newRandomGivenName, randomFamilyName, randomDate));
+ Mockito.when(ernpClient.searchWithPersonIdentifier(randomIdentifier)).thenReturn(ernpResult);
+
+ TaskExecutionException exception = assertThrows(TaskExecutionException.class,
+ () -> task.execute(pendingReq, executionContext));
+
+ Throwable origE = exception.getOriginalException();
+ Assert.assertTrue("Wrong exception", (origE.getCause() instanceof ManualFixNecessaryException));
+ }
+
+ /**
+ * One match, no register update needed
+ */
+ @Test
+ @DirtiesContext
+ public void testNode102_UserIdentified_a() throws Exception {
+ Mockito.when(zmrClient.searchWithPersonIdentifier(randomIdentifier)).thenReturn(Collections.emptyList());
+ Mockito.when(ernpClient.searchWithPersonIdentifier(randomIdentifier)).thenReturn(Collections.singletonList(
+ new RegisterResult(randomBpk, randomPseudonym, randomGivenName, randomFamilyName, randomDate)));
+
+ task.execute(pendingReq, executionContext);
+ String bPk = (String)
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .getGenericDataFromSession(Constants.DATA_RESULT_MATCHING_BPK);
+ Assert.assertEquals("Wrong bpk", bPk, randomBpk);
+ }
+
+ /**
+ * One match, no register update needed
+ */
+ @Test
+ @DirtiesContext
+ public void testNode102_UserIdentified_b() throws Exception {
+ Mockito.when(zmrClient.searchWithPersonIdentifier(randomIdentifier)).thenReturn(Collections.singletonList(
+ new RegisterResult(randomBpk, randomPseudonym, randomGivenName, randomFamilyName, randomDate)));
+ Mockito.when(ernpClient.searchWithPersonIdentifier(randomIdentifier)).thenReturn(Collections.emptyList());
+
+ task.execute(pendingReq, executionContext);
+
+ String bPk = (String)
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .getGenericDataFromSession(Constants.DATA_RESULT_MATCHING_BPK);
+ Assert.assertEquals("Wrong bpk", bPk, randomBpk);
+ }
+
+ /**
+ * One match found in ZMR and ErnP with detail search
+ */
+ @Test
+ @DirtiesContext
+ public void testNode103_UserIdentified_IT() throws Exception {
+ String taxNumber = RandomStringUtils.randomNumeric(14);
+ final AuthenticationResponse response = buildDummyAuthResponseRandomPersonIT_Tax(taxNumber);
+ TestRequestImpl pendingReq1 = new TestRequestImpl();
+ pendingReq1.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(Constants.DATA_FULL_EIDAS_RESPONSE, response);
+ Mockito.when(zmrClient.searchWithPersonIdentifier(randomIdentifier)).thenReturn(Collections.emptyList());
+ String newRandomPseudonym = IT_ST + randomIdentifier + RandomStringUtils.randomNumeric(2);
+ Mockito.when(zmrClient.searchItSpecific(taxNumber)).thenReturn(Collections.singletonList(
+ new RegisterResult(randomBpk, newRandomPseudonym, randomGivenName, randomFamilyName,
+ randomDate, null, null, taxNumber, null)));
+ Mockito.when(ernpClient.searchWithPersonIdentifier(randomIdentifier)).thenReturn(Collections.emptyList());
+ task = new InitialSearchTask(
+ Collections.singletonList(new ItSpecificDetailSearchProcessor(ernpClient, zmrClient)),
+ ernpClient, zmrClient);
+
+ task.execute(pendingReq1, executionContext);
+
+ String bPk = (String)
+ pendingReq1.getSessionData(AuthProcessDataWrapper.class)
+ .getGenericDataFromSession(Constants.DATA_RESULT_MATCHING_BPK);
+ Assert.assertEquals("Wrong bpk", bPk, randomBpk);
+ }
+
+ /**
+ * Multiple matches found in ZMR and ErnP with detail search
+ */
+ @Test
+ @DirtiesContext
+ public void testNode103_UserIdentified_DE() throws Exception {
+ final AuthenticationResponse response = buildDummyAuthResponseDE(randomGivenName, randomFamilyName,
+ randomPseudonym,
+ randomDate, randomPlaceOfBirth, randomBirthName);
+ TestRequestImpl pendingReq1 = new TestRequestImpl();
+ pendingReq1.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(Constants.DATA_FULL_EIDAS_RESPONSE, response);
+ Mockito.when(zmrClient.searchWithPersonIdentifier(randomIdentifier)).thenReturn(Collections.emptyList());
+ Mockito.when(zmrClient.searchDeSpecific(randomGivenName, randomFamilyName, randomDate, randomPlaceOfBirth,
+ randomBirthName))
+ .thenReturn(Collections.singletonList(new RegisterResult(randomBpk, randomPseudonym, randomGivenName,
+ randomFamilyName, randomDate, randomPlaceOfBirth, randomBirthName, null, null)));
+ Mockito.when(ernpClient.searchWithPersonIdentifier(randomIdentifier)).thenReturn(Collections.emptyList());
+ task = new InitialSearchTask(
+ Collections.singletonList(new DeSpecificDetailSearchProcessor(ernpClient, zmrClient)),
+ ernpClient, zmrClient);
+
+ task.execute(pendingReq1, executionContext);
+
+ String resultBpk = (String)
+ pendingReq1.getSessionData(AuthProcessDataWrapper.class)
+ .getGenericDataFromSession(Constants.DATA_RESULT_MATCHING_BPK);
+ Assert.assertEquals("Wrong bpk", resultBpk, randomBpk);
+ }
+
+ /**
+ * Multiple matches found in ZMR and ErnP with detail search
+ */
+ @Test
+ @DirtiesContext
+ public void testNode104_ManualFixNecessary_DE() throws Exception {
+ String newRandomPseudonym = randomPseudonym + RandomStringUtils.randomNumeric(2);
+ String newRandomBpk = randomBpk + RandomStringUtils.randomNumeric(6);
+ final AuthenticationResponse response = buildDummyAuthResponseDE(randomGivenName, randomFamilyName,
+ randomPseudonym,
+ randomDate, randomPlaceOfBirth, randomBirthName);
+ TestRequestImpl pendingReq1 = new TestRequestImpl();
+ pendingReq1.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(Constants.DATA_FULL_EIDAS_RESPONSE, response);
+ Mockito.when(zmrClient.searchWithPersonIdentifier(randomIdentifier)).thenReturn(Collections.emptyList());
+ ArrayList<RegisterResult> zmrResultSpecific = new ArrayList<>();
+ zmrResultSpecific.add(
+ new RegisterResult(randomBpk, randomPseudonym, randomGivenName, randomFamilyName, randomDate,
+ randomPlaceOfBirth, randomBirthName, null, null));
+ zmrResultSpecific.add(new RegisterResult(newRandomBpk, newRandomPseudonym, randomGivenName, randomFamilyName, randomDate,
+ randomPlaceOfBirth, randomBirthName, null, null));
+ Mockito.when(zmrClient.searchDeSpecific(randomGivenName, randomFamilyName, randomDate, randomPlaceOfBirth,
+ randomBirthName)).thenReturn(zmrResultSpecific);
+ Mockito.when(ernpClient.searchWithPersonIdentifier(randomIdentifier)).thenReturn(Collections.emptyList());
+ task = new InitialSearchTask(
+ Collections.singletonList(new DeSpecificDetailSearchProcessor(ernpClient, zmrClient)),
+ ernpClient, zmrClient);
+
+ TaskExecutionException exception = assertThrows(TaskExecutionException.class,
+ () -> task.execute(pendingReq1, executionContext));
+
+ Throwable origE = exception.getOriginalException();
+ Assert.assertTrue("Wrong exception", (origE.getCause() instanceof ManualFixNecessaryException));
+ }
+
+ /**
+ * Multiple matches found in ZMR and ErnP with detail search
+ */
+ @Test
+ @DirtiesContext
+ public void testNode104_ManualFixNecessary_IT() throws Exception {
+ String randomTaxNumber = RandomStringUtils.randomNumeric(14);
+ final AuthenticationResponse response = buildDummyAuthResponseRandomPersonIT_Tax(randomTaxNumber);
+ TestRequestImpl pendingReq1 = new TestRequestImpl();
+ pendingReq1.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(Constants.DATA_FULL_EIDAS_RESPONSE, response);
+ Mockito.when(zmrClient.searchWithPersonIdentifier(randomIdentifier)).thenReturn(Collections.emptyList());
+ ArrayList<RegisterResult> zmrResultSpecific = new ArrayList<>();
+ String randomPseudonym = IT_ST + randomIdentifier + "4";
+ zmrResultSpecific.add(new RegisterResult(randomBpk, randomPseudonym, randomGivenName,
+ randomFamilyName, randomDate, null, null, randomTaxNumber, null));
+ String newRandomPseudonym = IT_ST + randomIdentifier + "5";
+ String newRandomBpk = RandomStringUtils.randomNumeric(6);
+ zmrResultSpecific.add(new RegisterResult(newRandomBpk, newRandomPseudonym, randomGivenName,
+ randomFamilyName, randomDate, null, null, randomTaxNumber, null));
+ Mockito.when(zmrClient.searchItSpecific(randomTaxNumber)).thenReturn(zmrResultSpecific);
+ Mockito.when(ernpClient.searchWithPersonIdentifier(randomIdentifier)).thenReturn(Collections.emptyList());
+ task = new InitialSearchTask(
+ Collections.singletonList(new ItSpecificDetailSearchProcessor(ernpClient, zmrClient)),
+ ernpClient, zmrClient);
+
+ TaskExecutionException exception = assertThrows(TaskExecutionException.class,
+ () -> task.execute(pendingReq1, executionContext));
+
+ Throwable origE = exception.getOriginalException();
+ Assert.assertTrue("Wrong exception", (origE.getCause() instanceof ManualFixNecessaryException));
+ }
+
+ /**
+ * NO match found in ZMR and ErnP with Initial search
+ */
+ @Test
+ @DirtiesContext
+ public void testNode105_TemporaryEnd() throws TaskExecutionException {
+ Mockito.when(zmrClient.searchWithPersonIdentifier(randomIdentifier)).thenReturn(Collections.emptyList());
+ Mockito.when(ernpClient.searchWithPersonIdentifier(randomIdentifier)).thenReturn(Collections.emptyList());
+
+ task.execute(pendingReq, executionContext);
+
+ String bPk = (String)
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .getGenericDataFromSession(Constants.DATA_RESULT_MATCHING_BPK);
+ Assert.assertEquals("Wrong bpk", "TODO-Temporary-Endnode-105", bPk);
+ }
+
+
+ @NotNull
+ private AuthenticationResponse buildDummyAuthResponseRandomPerson() throws URISyntaxException {
+ return buildDummyAuthResponse(randomGivenName, randomFamilyName, DE_ST + randomIdentifier, randomDate);
+ }
+
+ private AuthenticationResponse buildDummyAuthResponseRandomPersonIT_Tax(String taxNumber)
+ throws URISyntaxException {
+ return buildDummyAuthResponse(randomGivenName, randomFamilyName, IT_ST + randomIdentifier, randomDate,
+ taxNumber, null, null);
+ }
+
+ @NotNull
+ private AuthenticationResponse buildDummyAuthResponse(String givenName, String familyName, String identifier,
+ String dateOfBirth) throws URISyntaxException {
+ return buildDummyAuthResponse(givenName, familyName, identifier, dateOfBirth, null, null, null);
+ }
+
+ @NotNull
+ private AuthenticationResponse buildDummyAuthResponseDE(String givenName, String familyName, String identifier,
+ String dateOfBirth, String placeOfBirth,
+ String birthName) throws URISyntaxException {
+ return buildDummyAuthResponse(givenName, familyName, identifier, dateOfBirth, null, placeOfBirth, birthName);
+ }
+
+ @NotNull
+ private AuthenticationResponse buildDummyAuthResponse(String givenName, String familyName, String identifier,
+ String dateOfBirth, String taxNumber, String placeOfBirth,
+ String birthName) throws URISyntaxException {
+ ImmutableAttributeMap.Builder builder = ImmutableAttributeMap.builder()
+ .put(generateStringAttribute(Constants.eIDAS_ATTR_PERSONALIDENTIFIER, "ff", "af"), identifier)
+ .put(generateStringAttribute(Constants.eIDAS_ATTR_CURRENTFAMILYNAME, "fff", "aff"), familyName)
+ .put(generateStringAttribute(Constants.eIDAS_ATTR_CURRENTGIVENNAME, "ffff", "afff"), givenName)
+ .put(generateDateTimeAttribute(Constants.eIDAS_ATTR_DATEOFBIRTH, "fffff", "affff"), dateOfBirth);
+ if (taxNumber != null) {
+ builder.put(generateStringAttribute(Constants.eIDAS_ATTR_TAXREFERENCE, "ffffff", "afffff"), taxNumber);
+ }
+ if (birthName != null) {
+ builder.put(generateStringAttribute(Constants.eIDAS_ATTR_BIRTHNAME, "fffffff", "affffff"), birthName);
+ }
+ if (placeOfBirth != null) {
+ builder.put(generateStringAttribute(Constants.eIDAS_ATTR_PLACEOFBIRTH, "ffffffff", "afffffff"),
+ placeOfBirth);
+ }
+ final ImmutableAttributeMap attributeMap = builder.build();
+
+ val b = new AuthenticationResponse.Builder();
+ return b.id("aasdf").issuer("asd").subject("asf").statusCode("200").inResponseTo("asdf").subjectNameIdFormat(
+ "afaf").attributes(attributeMap).build();
+ }
+
+ private AttributeDefinition<Object> generateStringAttribute(String friendlyName, String fragment, String prefix)
+ throws URISyntaxException {
+ return generateAttribute(friendlyName, fragment, prefix, "eu.eidas.auth.commons.attribute.impl" +
+ ".LiteralStringAttributeValueMarshaller");
+ }
+
+ private AttributeDefinition<Object> generateDateTimeAttribute(String friendlyName, String fragment, String prefix)
+ throws URISyntaxException {
+ return generateAttribute(friendlyName, fragment, prefix, "eu.eidas.auth.commons.attribute.impl" +
+ ".DateTimeAttributeValueMarshaller");
+ }
+
+ private AttributeDefinition<Object> generateAttribute(String friendlyName, String fragment, String prefix,
+ String marshaller) throws URISyntaxException {
+ return AttributeDefinition.builder()
+ .friendlyName(friendlyName).nameUri(new URI("ad", "sd", fragment))
+ .personType(PersonType.LEGAL_PERSON).xmlType(new QName("http://saf", "as", prefix))
+ .attributeValueMarshaller(marshaller).build();
+ }
+
+}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/SpringTest-context_tasks_test.xml b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/SpringTest-context_tasks_test.xml
index 7d5a4c53..1f3a984b 100644
--- a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/SpringTest-context_tasks_test.xml
+++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/SpringTest-context_tasks_test.xml
@@ -61,4 +61,21 @@
class="at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.CreateIdentityLinkTask"
scope="prototype" />
+ <bean id="InitialSearchTask"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.InitialSearchTask"
+ scope="prototype" />
+
+ <bean id="ErnbClientForeIDAS"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.ernp.DummyErnpClient" />
+
+ <bean id="ZmrClientForeIDAS"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.zmr.DummyZmrClient" />
+
+ <bean id="DE-Specific-Search"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.handler.DeSpecificDetailSearchProcessor">
+ </bean>
+
+ <bean id="IT-Specific-Search"
+ class="at.asitplus.eidas.specific.modules.auth.eidas.v2.handler.ItSpecificDetailSearchProcessor">
+ </bean>
</beans> \ No newline at end of file