aboutsummaryrefslogtreecommitdiff
path: root/eidas_modules/authmodule-eIDAS-v2/src/main
diff options
context:
space:
mode:
authorThomas <>2022-02-08 14:50:03 +0100
committerThomas <>2022-02-08 14:50:03 +0100
commit33404685b1d8de14229f61ea5dfa1fbee6229916 (patch)
treee412aa017ce83773c3ad9d50d71ad099d4a84917 /eidas_modules/authmodule-eIDAS-v2/src/main
parenta2baf085fcd3a1940585beb3f4a8acb2e4e5a461 (diff)
downloadNational_eIDAS_Gateway-33404685b1d8de14229f61ea5dfa1fbee6229916.tar.gz
National_eIDAS_Gateway-33404685b1d8de14229f61ea5dfa1fbee6229916.tar.bz2
National_eIDAS_Gateway-33404685b1d8de14229f61ea5dfa1fbee6229916.zip
feature(matching): finalize matching by residence search
Add ZMR communication and state validation for match-by-residence operation
Diffstat (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main')
-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/clients/zmr/IZmrClient.java21
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/zmr/ZmrSoapClient.java96
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/controller/AdresssucheController.java11
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/RegisterSearchService.java28
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveAustrianResidenceGuiResponseTask.java175
-rw-r--r--eidas_modules/authmodule-eIDAS-v2/src/main/resources/messages/eidas_connector_message.properties4
7 files changed, 234 insertions, 105 deletions
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 6da30299..40bcd27a 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
@@ -314,10 +314,12 @@ public class Constants {
// UI options
public static final String HTML_FORM_ADVANCED_MATCHING_FAILED = "advancedMatchingFailed";
-
+
// ProcessEngine context
public static final String CONTEXT_FLAG_ADVANCED_MATCHING_FAILED = HTML_FORM_ADVANCED_MATCHING_FAILED;
+ public static final String CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON =
+ HTML_FORM_ADVANCED_MATCHING_FAILED + "Reason";
/**
* {@link at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.CreateNewErnpEntryTask}.
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/zmr/IZmrClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/zmr/IZmrClient.java
index c4e8ece0..f3c32c96 100644
--- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/zmr/IZmrClient.java
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/zmr/IZmrClient.java
@@ -29,6 +29,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.zmr.ZmrSoapClient.ZmrRegisterResult;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.controller.AdresssucheController.AdresssucheOutput;
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.exception.EidasSAuthenticationException;
@@ -80,6 +81,23 @@ public interface IZmrClient {
throws EidasSAuthenticationException;
/**
+ * Search person based on MDS information and Austrian residence.
+ *
+ * @param zmrProzessId zmrProzessId zmrProzessId ProcessId from ZMR or <code>null</code> if no processId exists
+ * @param givenName eIDAS given name
+ * @param familyName eIDAS principle name
+ * @param dateOfBirth eIDAS date-of-birth
+ * @param citizenCountryCode citizenCountryCode CountryCode of the eIDAS proxy-service
+ * @param address Address information for searching
+ * @return Search result but never <code>null</code>
+ * @throws EidasSAuthenticationException In case of a communication error
+ */
+ @Nonnull
+ ZmrRegisterResult searchWithResidenceData(@Nullable BigInteger zmrProzessId, @Nonnull String givenName,
+ @Nonnull String familyName, @Nonnull String dateOfBirth, @Nonnull String citizenCountryCode,
+ @Nonnull AdresssucheOutput address) throws EidasSAuthenticationException;
+
+ /**
* Update ZMR entry to KITT existing ZMR identity with this eIDAS authentication.
*
* @param zmrProzessId zmrProzessId ProcessId from ZMR or <code>null</code> if no processId exists
@@ -92,7 +110,4 @@ public interface IZmrClient {
ZmrRegisterResult update(@Nullable BigInteger zmrProzessId, RegisterResult registerResult, SimpleEidasData eidData)
throws EidasSAuthenticationException;
- ZmrRegisterResult searchWithResidenceData(@Nullable BigInteger zmrProzessId, String givenName, String familyName,
- String dateOfBirth, String zipcode, String city, String street);
-
}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/zmr/ZmrSoapClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/zmr/ZmrSoapClient.java
index 18a80c33..0f2f94cc 100644
--- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/zmr/ZmrSoapClient.java
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/zmr/ZmrSoapClient.java
@@ -24,6 +24,7 @@ import org.springframework.lang.Nullable;
import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.AbstractSoapClient;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.controller.AdresssucheController.AdresssucheOutput;
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.exception.EidasSAuthenticationException;
@@ -56,6 +57,8 @@ import at.gv.bmi.namespace.zmr_su.zmr._20040201.SuchkriterienType;
import at.gv.e_government.reference.namespace.persondata.de._20040201.IdentificationType;
import at.gv.e_government.reference.namespace.persondata.de._20040201.NatuerlichePersonTyp;
import at.gv.e_government.reference.namespace.persondata.de._20040201.PersonenNameTyp;
+import at.gv.e_government.reference.namespace.persondata.de._20040201.PostAdresseTyp;
+import at.gv.e_government.reference.namespace.persondata.de._20040201.ZustelladresseTyp;
import at.gv.egiz.eaaf.core.api.data.EaafConstants;
import at.gv.egiz.eaaf.core.exceptions.EaafAuthenticationException;
import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException;
@@ -95,6 +98,7 @@ public class ZmrSoapClient extends AbstractSoapClient implements IZmrClient {
"Searching " + Constants.eIDAS_ATTR_PERSONALIDENTIFIER;
private static final String PROCESS_SEARCH_MDS_ONLY = "Searching with MDS only";
private static final String PROCESS_SEARCH_COUNTRY_SPECIFIC = "Searching {0} specific";
+ private static final String PROCESS_SEARCH_BY_RESIDENCE = "Searching by residence";
private static final String PROCESS_KITT_GENERAL = "KITT general-processing";
private static final String PROCESS_KITT_IDENITIES_GET = "KITT get-latest-version";
@@ -173,15 +177,7 @@ public class ZmrSoapClient extends AbstractSoapClient implements IZmrClient {
// set eIDAS person information
final PersonSuchenRequest searchPersonReq = new PersonSuchenRequest();
req.setPersonSuchenRequest(searchPersonReq);
-
- final NatuerlichePersonTyp searchNatPerson = new NatuerlichePersonTyp();
- searchPersonReq.setNatuerlichePerson(searchNatPerson);
- final PersonenNameTyp searchNatPersonName = new PersonenNameTyp();
- searchNatPerson.setPersonenName(searchNatPersonName);
-
- searchNatPersonName.setFamilienname(familyName);
- searchNatPersonName.setVorname(givenName);
- searchNatPerson.setGeburtsdatum(dateOfBirth);
+ searchPersonReq.setNatuerlichePerson(buildSearchNatPerson(givenName, familyName, dateOfBirth));
// set work-flow client information
req.setWorkflowInfoClient(generateWorkFlowInfos(PROCESS_TASK_SEARCH, zmrProzessId));
@@ -296,12 +292,49 @@ public class ZmrSoapClient extends AbstractSoapClient implements IZmrClient {
}
}
-
+
@Override
public ZmrRegisterResult searchWithResidenceData(BigInteger zmrProzessId, String givenName, String familyName,
- String dateOfBirth, String zipcode, String city, String street) {
- // TODO Auto-generated method stub
- return null;
+ String dateOfBirth, String citizenCountryCode, AdresssucheOutput address)
+ throws EidasSAuthenticationException {
+ try {
+ // build search request
+ final RequestType req = new RequestType();
+
+ // set person information
+ final PersonSuchenRequest searchPersonReq = new PersonSuchenRequest();
+ req.setPersonSuchenRequest(searchPersonReq);
+ searchPersonReq.setNatuerlichePerson(buildSearchNatPerson(givenName, familyName, dateOfBirth));
+ searchPersonReq.setPostAdresse(buildSearchAddress(address));
+
+ // set work-flow client information
+ req.setWorkflowInfoClient(generateWorkFlowInfos(PROCESS_SEARCH_BY_RESIDENCE, zmrProzessId));
+ req.setClientInfo(generateClientInfos());
+
+ // set additionl search parameters
+ searchPersonReq.setPersonensucheInfo(generateSearchCriteria(
+ PROCESS_SEARCH_BY_RESIDENCE, false, true, false));
+
+ // request ZMR
+ log.trace("Requesting ZMR for '{}' operation", PROCESS_SEARCH_BY_RESIDENCE);
+ final ResponseType resp = zmrClient.service(req, null);
+
+ // parse ZMR response
+ return processZmrResponse(resp, citizenCountryCode, false, PROCESS_SEARCH_BY_RESIDENCE);
+
+ } catch (final ServiceFault e) {
+ final String errorMsg = extractReasonFromError(e);
+ log.warn(LOGMSG_ZMR_ERROR, PROCESS_SEARCH_BY_RESIDENCE, errorMsg);
+ throw new ZmrCommunicationException(ERROR_MATCHING_01, new Object[] { errorMsg }, e);
+
+ } catch (EidasSAuthenticationException e) {
+ throw e;
+
+ } catch (final Exception e) {
+ log.warn(LOGMSG_ZMR_RESP_PROCESS, PROCESS_SEARCH_BY_RESIDENCE, e.getMessage());
+ throw new EidasSAuthenticationException(ERROR_MATCHING_99, new Object[] { e.getMessage() }, e);
+
+ }
}
@PostConstruct
@@ -685,6 +718,43 @@ public class ZmrSoapClient extends AbstractSoapClient implements IZmrClient {
}
}
+ private NatuerlichePersonTyp buildSearchNatPerson(String givenName, String familyName, String dateOfBirth) {
+ final NatuerlichePersonTyp searchNatPerson = new NatuerlichePersonTyp();
+ final PersonenNameTyp searchNatPersonName = new PersonenNameTyp();
+ searchNatPerson.setPersonenName(searchNatPersonName);
+ searchNatPersonName.setFamilienname(familyName);
+ searchNatPersonName.setVorname(givenName);
+ searchNatPerson.setGeburtsdatum(dateOfBirth);
+ return searchNatPerson;
+
+ }
+
+ private PostAdresseTyp buildSearchAddress(AdresssucheOutput address) {
+ PostAdresseTyp postAdresse = new PostAdresseTyp();
+ if (StringUtils.isNotBlank(address.getPostleitzahl())){
+ postAdresse.setPostleitzahl(address.getPostleitzahl());
+ }
+ if (StringUtils.isNotBlank(address.getMunicipality())) {
+ postAdresse.setGemeinde(address.getMunicipality());
+ }
+ if (StringUtils.isNotBlank(address.getVillage())) {
+ postAdresse.setOrtschaft(address.getVillage());
+ }
+ if (StringUtils.isNotBlank(address.getStreet()) || StringUtils.isNotBlank(address.getNumber())) {
+ ZustelladresseTyp zustelladresse = new ZustelladresseTyp();
+ if (StringUtils.isNotBlank(address.getStreet())) {
+ zustelladresse.setStrassenname(address.getStreet());
+ }
+ if (StringUtils.isNotBlank(address.getNumber())) {
+ zustelladresse.setOrientierungsnummer(address.getNumber());
+ }
+ postAdresse.setZustelladresse(zustelladresse);
+ }
+
+ return postAdresse;
+
+ }
+
private Collection<? extends EidasIdentitaetAnlageType> selectEidasDocumentsToAdd(
PersonErgebnisType zmrPersonToKitt, SimpleEidasData eidData) {
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/controller/AdresssucheController.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/controller/AdresssucheController.java
index 8505f5d5..6dcd4879 100644
--- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/controller/AdresssucheController.java
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/controller/AdresssucheController.java
@@ -58,6 +58,7 @@ import at.gv.egiz.eaaf.core.exceptions.EaafException;
import at.gv.egiz.eaaf.core.exceptions.GuiBuildException;
import at.gv.egiz.eaaf.core.exceptions.PendingReqIdValidationException;
import lombok.AllArgsConstructor;
+import lombok.Builder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
@@ -166,18 +167,23 @@ public class AdresssucheController {
number.replaceAll("[\r\n]", ""));
try {
pendingReqGeneration.validateAndGetPendingRequestId(pendingId);
+
} catch (PendingReqIdValidationException e) {
log.warn("Search with pendingId '{}' is not valid", pendingId.replaceAll("[\r\n]", ""));
return ResponseEntity.badRequest().build();
+
}
+
try {
Adressdaten searchInput = buildSearchInput(postleitzahl, municipality, village, street, number);
ZmrAddressSoapClient.AddressInfo searchOutput = client.searchAddress(searchInput);
AdresssucheResult output = buildResponse(searchOutput);
return ResponseEntity.ok(output);
+
} catch (EidasSAuthenticationException e) {
log.warn("Search failed", e);
return ResponseEntity.badRequest().build();
+
}
}
@@ -185,7 +191,9 @@ public class AdresssucheController {
if (searchOutput.getPersonResult().isEmpty()) {
log.warn("No result from ZMR");
return new AdresssucheResult(Collections.emptyList(), 0);
+
}
+
log.info("Result level is {}", searchOutput.getLevel());
Set<AdresssucheOutput> result = searchOutput.getPersonResult().stream()
.map(Adressdaten::getPostAdresse)
@@ -195,6 +203,7 @@ public class AdresssucheController {
// TODO Add configuration option for the limit of 30
List<AdresssucheOutput> sorted = result.stream().sorted().limit(30).collect(Collectors.toList());
return new AdresssucheResult(sorted, result.size());
+
}
private Adressdaten buildSearchInput(String postleitzahl,
@@ -225,6 +234,7 @@ public class AdresssucheController {
Adressdaten searchInput = new Adressdaten();
searchInput.setPostAdresse(postAdresse);
return searchInput;
+
}
@Data
@@ -236,6 +246,7 @@ public class AdresssucheController {
@Data
@AllArgsConstructor
+ @Builder
public static class AdresssucheOutput implements Comparable<AdresssucheOutput> {
private final String postleitzahl;
private final String municipality;
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/RegisterSearchService.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/RegisterSearchService.java
index 85ea942c..d95aadda 100644
--- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/RegisterSearchService.java
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/RegisterSearchService.java
@@ -16,6 +16,7 @@ import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.ernp.ErnpRestCli
import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.ernp.IErnpClient;
import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.zmr.IZmrClient;
import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.zmr.ZmrSoapClient.ZmrRegisterResult;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.controller.AdresssucheController.AdresssucheOutput;
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.exception.EidasSAuthenticationException;
@@ -165,18 +166,27 @@ public class RegisterSearchService {
* Search with residence infos.
*
* @param operationStatus Current register-operation status that contains processing informations
- * @param zipcode Provided Zipcode
- * @param city Provided City
- * @param street Provided street
+ * @param eidasData Receive eIDAS eID information
+ * @param address Address information provided by user
* @return Results from ZMR or ERnP search
+ * @throws WorkflowException In case of a register interaction error
*/
- public RegisterStatusResults searchWithResidence(RegisterOperationStatus operationStatus, SimpleEidasData eidasData,
- String zipcode, String city, String street) {
- final ZmrRegisterResult resultsZmr = zmrClient.searchWithResidenceData(
- operationStatus.getZmrProcessId(), eidasData.getGivenName(), eidasData.getFamilyName(),
- eidasData.getDateOfBirth(), zipcode, city, street);
- return RegisterStatusResults.fromZmr(resultsZmr);
+ public RegisterStatusResults searchWithResidence(RegisterOperationStatus operationStatus, SimpleEidasData eidasData,
+ AdresssucheOutput address) throws WorkflowException {
+ try {
+ final ZmrRegisterResult resultsZmr = zmrClient.searchWithResidenceData(
+ operationStatus.getZmrProcessId(), eidasData.getGivenName(), eidasData.getFamilyName(),
+ eidasData.getDateOfBirth(), eidasData.getCitizenCountryCode(), address);
+
+ // ERnP search is not used here, because we only search for people with Austrian residence and they are in ZMR only
+
+ return RegisterStatusResults.fromZmr(resultsZmr);
+
+ } catch (final EidasSAuthenticationException e) {
+ throw new WorkflowException("searchWithResidenceInformation", e.getMessage(),
+ !(e instanceof ZmrCommunicationException), e);
+ }
}
/**
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveAustrianResidenceGuiResponseTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveAustrianResidenceGuiResponseTask.java
index acf469d3..67addf94 100644
--- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveAustrianResidenceGuiResponseTask.java
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveAustrianResidenceGuiResponseTask.java
@@ -23,16 +23,24 @@
package at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks;
+import static at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED;
+import static at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON;
+import static at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants.TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK;
+
import java.util.Enumeration;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;
import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.controller.AdresssucheController;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.controller.AdresssucheController.AdresssucheOutput;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.controller.AdresssucheController.AdresssucheOutput.AdresssucheOutputBuilder;
import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.MatchedPersonResult;
import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData;
import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.ManualFixNecessaryException;
@@ -43,15 +51,9 @@ import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.MatchingTaskUtils;
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.modules.AbstractAuthServletTask;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
+import at.gv.egiz.eaaf.core.impl.idp.controller.tasks.AbstractLocaleAuthServletTask;
import lombok.extern.slf4j.Slf4j;
-import static at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED;
-import static at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants.TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK;
-
/**
* Task receives the response of {@link GenerateAustrianResidenceGuiTask} and handles it.
@@ -67,7 +69,7 @@ import static at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants.TRANSIT
* </ul>
* Transitions:
* <ul>
- * <li>{@link CreateNewErnpEntryTask} if no results from search with residency data in registers</li>
+ * <li>{@link GenerateOtherLoginMethodGuiTask} if no results from search with residency data in registers</li>
* <li>{@link CreateIdentityLinkTask} if one exact match between initial register search (with MDS) and results
* from search with residency data in registers exists</li>
* <li>{@link GenerateOtherLoginMethodGuiTask} if a user input error has happened</li>
@@ -79,71 +81,77 @@ import static at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants.TRANSIT
*/
@Slf4j
@Component("ReceiveAustrianResidenceGuiResponseTask")
-public class ReceiveAustrianResidenceGuiResponseTask extends AbstractAuthServletTask {
+public class ReceiveAustrianResidenceGuiResponseTask extends AbstractLocaleAuthServletTask {
- public static final String PARAM_FORMER_RESIDENCE_AVAILABLE = "formerResidenceAvailable";
- public static final String PARAM_STREET = "street";
- public static final String PARAM_CITY = "city";
- public static final String PARAM_ZIPCODE = "zipcode";
+ private static final String MSG_PROP_20 = "module.eidasauth.matching.20";
+ private static final String MSG_PROP_21 = "module.eidasauth.matching.21";
+ private static final String MSG_PROP_22 = "module.eidasauth.matching.22";
+
+ public static final String HTTP_PARAM_NO_RESIDENCE = "noResidence";
private final RegisterSearchService registerSearchService;
public ReceiveAustrianResidenceGuiResponseTask(RegisterSearchService registerSearchService) {
this.registerSearchService = registerSearchService;
+
}
-
- @Data
- @AllArgsConstructor
- @NoArgsConstructor
- public static class UserInput {
- private boolean formerResidenceAvailable;
- private String zipcode;
- private String city;
- private String street;
- }
-
+
@Override
- public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response)
- throws TaskExecutionException {
+ protected void executeWithLocale(ExecutionContext executionContext, HttpServletRequest request,
+ HttpServletResponse response) throws TaskExecutionException {
log.trace("Starting ReceiveAustrianResidenceGuiResponseTask");
- UserInput input = parseHtmlInput(request);
- if (!input.isFormerResidenceAvailable()) {
- moveToNextTask(executionContext);
- return;
-
- }
-
- if (input.getStreet().isEmpty() || input.getCity().isEmpty() || input.getZipcode().isEmpty()) {
- // HTML form should ensure that mandatory fields are set => this should never happen
- executionContext.put(CONTEXT_FLAG_ADVANCED_MATCHING_FAILED, true);
- executionContext.put(TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK, true);
- return;
-
- }
+ try {
+ //return to AuswahlScreen if HTTP_PARAM_NO_RESIDENCE was selected
+ final boolean forwardWithOutMandate = parseFlagFromHttpRequest(request, HTTP_PARAM_NO_RESIDENCE, false);
+ if (forwardWithOutMandate) {
+ log.debug("User selects 'no residence' button. Switch back to 'other matching' selection ... ");
+ executionContext.put(TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK, true);
+
+ executionContext.put(CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON, MSG_PROP_20);
+ executionContext.put(CONTEXT_FLAG_ADVANCED_MATCHING_FAILED, true);
+ return;
+
+ }
+
+ //load search parameters from HTML form
+ AdresssucheOutput input = parseHtmlInput(request);
+ if (validateHtmlInput(input)) {
+ // HTML form should ensure that mandatory fields are set => this should never happen
+ log.warn("HTML form contains no residence information. Switch back to 'other matching' selection ... ");
+ executionContext.put(TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK, true);
+
+ executionContext.put(CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON, MSG_PROP_20);
+ executionContext.put(CONTEXT_FLAG_ADVANCED_MATCHING_FAILED, true);
+ return;
- try {
+ }
+
+ // get pre-processed information
SimpleEidasData eidasData = MatchingTaskUtils.getInitialEidasData(pendingReq);
RegisterStatusResults initialSearchResult = MatchingTaskUtils.getIntermediateMatchingResult(pendingReq);
+ // search in register
RegisterStatusResults residencyResult =
- registerSearchService.searchWithResidence(initialSearchResult.getOperationStatus(),
- eidasData, input.zipcode, input.city, input.street);
- if (residencyResult.getResultCount() == 0) {
- //TODO: her we should add a GUI step of result is zero to inform user an forward process by click
- moveToNextTask(executionContext);
-
- } else if (residencyResult.getResultCount() == 1) {
- compareSearchResultWithInitialData(executionContext, residencyResult, eidasData);
+ registerSearchService.searchWithResidence(initialSearchResult.getOperationStatus(), eidasData, input);
+
+ // validate matching response from registers
+ if (residencyResult.getResultCount() != 1) {
+ log.info("Find {} match by using residence information. Forward user to 'other matching' selection ... ",
+ residencyResult.getResultCount() == 0 ? "no" : "more-than-one");
+ executionContext.put(TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK, true);
+
+ executionContext.put(CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON, MSG_PROP_22);
+ executionContext.put(CONTEXT_FLAG_ADVANCED_MATCHING_FAILED, true);
} else {
- /*TODO: align with form generation task and to better error handling in case of more-than-one result.
- * Maybe the user has to provide more information.
- */
- throw new TaskExecutionException(pendingReq,
- "Manual Fix necessary", new ManualFixNecessaryException(eidasData));
+ log.debug("Find single match by using residence information. Starting data validation ... ");
+ compareSearchResultWithInitialData(executionContext, residencyResult, eidasData);
}
+ } catch (WorkflowException e) {
+ throw new TaskExecutionException(pendingReq, "Search with residency data failed", e);
+
} catch (EaafStorageException e) {
log.error("Search with residency data failed", e);
throw new TaskExecutionException(pendingReq, "Search with residency data failed", e);
@@ -151,58 +159,67 @@ public class ReceiveAustrianResidenceGuiResponseTask extends AbstractAuthServlet
}
}
+ private boolean validateHtmlInput(AdresssucheOutput input) {
+ return StringUtils.isEmpty(input.getMunicipality())
+ && StringUtils.isEmpty(input.getNumber())
+ && StringUtils.isEmpty(input.getPostleitzahl())
+ && StringUtils.isEmpty(input.getStreet())
+ && StringUtils.isEmpty(input.getVillage());
+ }
+
private void compareSearchResultWithInitialData(ExecutionContext executionContext,
RegisterStatusResults residencyResult, SimpleEidasData eidasData)
throws TaskExecutionException, EaafStorageException {
try {
- if (eidasData.equalsRegisterData(residencyResult.getResult())) {
+ if (!eidasData.equalsRegisterData(residencyResult.getResult())) {
// update register information
- registerSearchService.step7aKittProcess(residencyResult, eidasData);
+ RegisterStatusResults updateResult = registerSearchService.step7aKittProcess(residencyResult, eidasData);
- // store search result to re-used in CreateIdentityLink step, because there we need bPK and MDS
+ // store updated result to re-used in CreateIdentityLink step, because there we need bPK and MDS
MatchingTaskUtils.storeFinalMatchingResult(pendingReq,
MatchedPersonResult.generateFormMatchingResult(
- residencyResult.getResult(), eidasData.getCitizenCountryCode()));
+ updateResult.getResult(), eidasData.getCitizenCountryCode()));
} else {
- moveToNextTask(executionContext);
-
+ log.warn("Suspect state FOUND. Matching by residence was neccessary but NO register-update are required!");
+ // no update required. Data can be used as it is.
+ MatchingTaskUtils.storeFinalMatchingResult(pendingReq,
+ MatchedPersonResult.generateFormMatchingResult(
+ residencyResult.getResult(), eidasData.getCitizenCountryCode()));
+
}
-
+
} catch (WorkflowException e) {
throw new TaskExecutionException(pendingReq, "Search failed", new ManualFixNecessaryException(eidasData));
}
}
- private void moveToNextTask(ExecutionContext executionContext) {
- // Later on, this should transition to Step 20
- executionContext.put(Constants.TRANSITION_TO_CREATE_NEW_ERNP_ENTRY_TASK, true);
-
- }
-
- private @NotNull UserInput parseHtmlInput(HttpServletRequest request) {
+ private @NotNull AdresssucheOutput parseHtmlInput(HttpServletRequest request) {
Enumeration<String> reqParamNames = request.getParameterNames();
- UserInput result = new UserInput();
+ AdresssucheOutputBuilder resultBuilder = AdresssucheOutput.builder();
while (reqParamNames.hasMoreElements()) {
final String paramName = reqParamNames.nextElement();
String escaped = StringEscapeUtils.escapeHtml(request.getParameter(paramName));
- if (PARAM_FORMER_RESIDENCE_AVAILABLE.equalsIgnoreCase(paramName)) {
- result.setFormerResidenceAvailable(Boolean.parseBoolean(escaped));
+ if (AdresssucheController.PARAM_MUNIPICALITY.equalsIgnoreCase(paramName)) {
+ resultBuilder.municipality(escaped);
- } else if (PARAM_STREET.equalsIgnoreCase(paramName)) {
- result.setStreet(escaped);
+ } else if (AdresssucheController.PARAM_NUMBER.equalsIgnoreCase(paramName)) {
+ resultBuilder.number(escaped);
- } else if (PARAM_CITY.equalsIgnoreCase(paramName)) {
- result.setCity(escaped);
+ } else if (AdresssucheController.PARAM_POSTLEITZAHL.equalsIgnoreCase(paramName)) {
+ resultBuilder.postleitzahl(escaped);
- } else if (PARAM_ZIPCODE.equalsIgnoreCase(paramName)) {
- result.setZipcode(escaped);
+ } else if (AdresssucheController.PARAM_STREET.equalsIgnoreCase(paramName)) {
+ resultBuilder.street(escaped);
+
+ } else if (AdresssucheController.PARAM_VILLAGE.equalsIgnoreCase(paramName)) {
+ resultBuilder.village(escaped);
}
}
- return result;
-
+
+ return resultBuilder.build();
}
}
diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/resources/messages/eidas_connector_message.properties b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/messages/eidas_connector_message.properties
index 188c5a8f..f1bf2128 100644
--- a/eidas_modules/authmodule-eIDAS-v2/src/main/resources/messages/eidas_connector_message.properties
+++ b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/messages/eidas_connector_message.properties
@@ -23,5 +23,9 @@ module.eidasauth.matching.04=An error occurred while loading your data from offi
module.eidasauth.matching.11=Matching failed, because of an ERnP communication error. Reason: {0}
module.eidasauth.matching.12=Matching failed, because ERnP response contains historic information which is not supported.
+module.eidasauth.matching.20=Matching be using residence information was canceled. Use another method for matching or create a new Austrian identity.
+module.eidasauth.matching.21=Matching be using residence information failed by missing input information. Use another method for matching or create a new Austrian identity.
+module.eidasauth.matching.22=Can not find an unique match by using residence information. Provide more or other data, use another method for matching, or create a new Austrian identity.
+
module.eidasauth.matching.99=Matching failed, because of an unexpected processing error. Reason: {0}