From a3d1b2e9aaad4b00031cfcd76e26940697c876c2 Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Wed, 2 Feb 2022 18:02:11 +0100 Subject: refactor(ernp): move IErnpClient interface into another package --- .../auth/eidas/v2/clients/ernp/IErnpClient.java | 46 ++++++++++++++++++++++ .../auth/eidas/v2/ernp/DummyErnpClient.java | 1 + .../modules/auth/eidas/v2/ernp/IErnpClient.java | 46 ---------------------- .../eidas/v2/service/RegisterSearchService.java | 2 +- 4 files changed, 48 insertions(+), 47 deletions(-) create mode 100644 eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/IErnpClient.java delete mode 100644 eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/ernp/IErnpClient.java (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java') diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/IErnpClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/IErnpClient.java new file mode 100644 index 00000000..377048d9 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/IErnpClient.java @@ -0,0 +1,46 @@ +/* + * 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.clients.ernp; + +import java.util.List; + +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.RegisterResult; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData; + +public interface IErnpClient { + + List searchWithPersonIdentifier(String personIdentifier); + + List searchWithMds(String givenName, String familyName, String dateOfBirth); + + List searchDeSpecific(String givenName, String familyName, String dateOfBirth, + String birthPlace, String birthName); + + List searchItSpecific(String taxNumber); + + RegisterResult update(RegisterResult registerResult, SimpleEidasData eidData); + + List searchWithBpkZp(String bpkzp); + +} 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 index 77f5e3cd..db10752b 100644 --- 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 @@ -28,6 +28,7 @@ import java.util.List; import org.springframework.stereotype.Service; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.ernp.IErnpClient; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.RegisterResult; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData; 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 deleted file mode 100644 index b2a9005b..00000000 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/ernp/IErnpClient.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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 java.util.List; - -import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.RegisterResult; -import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData; - -public interface IErnpClient { - - List searchWithPersonIdentifier(String personIdentifier); - - List searchWithMds(String givenName, String familyName, String dateOfBirth); - - List searchDeSpecific(String givenName, String familyName, String dateOfBirth, - String birthPlace, String birthName); - - List searchItSpecific(String taxNumber); - - RegisterResult update(RegisterResult registerResult, SimpleEidasData eidData); - - List searchWithBpkZp(String bpkzp); - -} 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 047d75ae..5f1e96a4 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 @@ -11,11 +11,11 @@ import org.springframework.stereotype.Service; import com.google.common.collect.Streams; +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.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.EidasSAuthenticationException; import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.WorkflowException; import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.ZmrCommunicationException; -- cgit v1.2.3 From b70915cf52ecb08c881d33e8c65b6256922fc0f4 Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Thu, 3 Feb 2022 15:50:33 +0100 Subject: refactor(ernp): change API of ERnP client to same model as ZMR client --- .../auth/eidas/v2/clients/ernp/ErnpRestClient.java | 65 +++++++++++++++++++ .../auth/eidas/v2/clients/ernp/IErnpClient.java | 74 +++++++++++++++++++--- .../auth/eidas/v2/ernp/DummyErnpClient.java | 43 +++++++------ .../eidas/v2/service/RegisterSearchService.java | 30 +++++---- 4 files changed, 168 insertions(+), 44 deletions(-) create mode 100644 eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java') diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java new file mode 100644 index 00000000..7763fc9d --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java @@ -0,0 +1,65 @@ +package at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.ernp; + +import java.util.List; + +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; +import at.gv.bmi.namespace.zmr_su.zmr._20040201.PersonSuchenRequest; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * Implements an ERnP client that uses REST API for communication. + * + * @author tlenz + * + */ +public class ErnpRestClient implements IErnpClient { + + @AllArgsConstructor + @Getter + public static class ErnpRegisterResult { + private final List personResult; + + } + + @Override + public ErnpRegisterResult searchWithPersonIdentifier(String personIdentifier, String citizenCountryCode) + throws EidasSAuthenticationException { + // TODO Auto-generated method stub + return null; + } + + @Override + public ErnpRegisterResult searchWithMds(String givenName, String familyName, String dateOfBirth, + String citizenCountryCode) throws EidasSAuthenticationException { + // TODO Auto-generated method stub + return null; + } + + @Override + public ErnpRegisterResult searchCountrySpecific(PersonSuchenRequest personSearchDao, + String citizenCountryCode) throws EidasSAuthenticationException { + // TODO Auto-generated method stub + return null; + } + + @Override + public ErnpRegisterResult update(RegisterResult registerResult, SimpleEidasData eidData) + throws EidasSAuthenticationException { + // TODO Auto-generated method stub + return null; + } + + @Override + public ErnpRegisterResult searchWithResidenceData(String givenName, String familyName, String dateOfBirth, + String zipcode, String city, String street) { + // TODO Auto-generated method stub + return null; + } + + + + +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/IErnpClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/IErnpClient.java index 377048d9..4c8bcd3e 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/IErnpClient.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/IErnpClient.java @@ -23,24 +23,80 @@ package at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.ernp; -import java.util.List; +import javax.annotation.Nonnull; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.ernp.ErnpRestClient.ErnpRegisterResult; 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; +import at.gv.bmi.namespace.zmr_su.zmr._20040201.PersonSuchenRequest; public interface IErnpClient { - List searchWithPersonIdentifier(String personIdentifier); + /** + * Search person based on eIDAS personal identifier. + * + * @param personIdentifier Full eIDAS personal identifier with prefix + * @param citizenCountryCode CountryCode of the eIDAS proxy-service + * @return Search result but never null + * @throws EidasSAuthenticationException In case of a communication error + */ + @Nonnull + ErnpRegisterResult searchWithPersonIdentifier(@Nonnull String personIdentifier, + @Nonnull String citizenCountryCode) throws EidasSAuthenticationException; - List searchWithMds(String givenName, String familyName, String dateOfBirth); + /** + * Search person based on eIDSA MDS information. + * + * @param givenName eIDAS given name + * @param familyName eIDAS principle name + * @param dateOfBirth eIDAS date-of-birth + * @param citizenCountryCode CountryCode of the eIDAS proxy-service + * @return Search result but never null + * @throws EidasSAuthenticationException In case of a communication error + */ + @Nonnull + ErnpRegisterResult searchWithMds(@Nonnull String givenName, @Nonnull String familyName, + @Nonnull String dateOfBirth, @Nonnull String citizenCountryCode) + throws EidasSAuthenticationException; - List searchDeSpecific(String givenName, String familyName, String dateOfBirth, - String birthPlace, String birthName); + /** + * Search person based on country-specific natural person set. + * + * @param personSearchDao Specific set of natural person informations. + * @param citizenCountryCode CountryCode of the eIDAS proxy-service + * @return Search result but never null + * @throws EidasSAuthenticationException In case of a communication error + */ + @Nonnull + ErnpRegisterResult searchCountrySpecific(@Nonnull PersonSuchenRequest personSearchDao, + @Nonnull String citizenCountryCode) throws EidasSAuthenticationException; - List searchItSpecific(String taxNumber); + /** + * Update ERnP entry to KITT existing ERnP identity with this eIDAS authentication. + * + * @param registerResult Already matched eIDAS identity that should be KITT + * @param eidData eIDAS eID information from current authentication process + * @return Update result but never null + * @throws EidasSAuthenticationException In case of a communication error + */ + @Nonnull + ErnpRegisterResult update(RegisterResult registerResult, SimpleEidasData eidData) + throws EidasSAuthenticationException; - RegisterResult update(RegisterResult registerResult, SimpleEidasData eidData); - - List searchWithBpkZp(String bpkzp); + /** + * Search person based on address information. + * + * @param givenName eIDAS given name + * @param familyName eIDAS principle name + * @param dateOfBirth eIDAS date-of-birth + * @param zipcode ZipCode + * @param city City + * @param street Street + * @return Search result but never null + */ + @Nonnull + ErnpRegisterResult searchWithResidenceData(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/ernp/DummyErnpClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/ernp/DummyErnpClient.java index db10752b..52703232 100644 --- 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 @@ -24,52 +24,53 @@ package at.asitplus.eidas.specific.modules.auth.eidas.v2.ernp; import java.util.Collections; -import java.util.List; import org.springframework.stereotype.Service; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.ernp.ErnpRestClient.ErnpRegisterResult; import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.ernp.IErnpClient; 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; +import at.gv.bmi.namespace.zmr_su.zmr._20040201.PersonSuchenRequest; @Service("ErnbClientForeIDAS") public class DummyErnpClient implements IErnpClient { + @Override - public List searchWithPersonIdentifier(String personIdentifier) { - return Collections.emptyList(); + public ErnpRegisterResult searchWithPersonIdentifier(String personIdentifier, String citizenCountryCode) + throws EidasSAuthenticationException { + return buildEmptyResult(); } @Override - public List searchWithMds(String givenName, String familyName, String dateOfBirth) { - //TODO will I only receive matches where all three values match perfectly? - return Collections.emptyList(); + public ErnpRegisterResult searchWithMds(String givenName, String familyName, String dateOfBirth, + String citizenCountryCode) throws EidasSAuthenticationException { + return buildEmptyResult(); } @Override - public List searchDeSpecific(String givenName, String familyName, String dateOfBirth, - String birthPlace, String birthName) { - //TODO - return Collections.emptyList(); + public ErnpRegisterResult searchCountrySpecific(PersonSuchenRequest personSearchDao, + String citizenCountryCode) throws EidasSAuthenticationException { + return buildEmptyResult(); } @Override - public List searchItSpecific(String taxNumber) { - //TODO - return Collections.emptyList(); + public ErnpRegisterResult update(RegisterResult registerResult, SimpleEidasData eidData) + throws EidasSAuthenticationException { + return buildEmptyResult(); } @Override - public RegisterResult update(RegisterResult registerResult, SimpleEidasData eidData) { - //TODO - return null; + public ErnpRegisterResult searchWithResidenceData(String givenName, String familyName, String dateOfBirth, + String zipcode, String city, String street) { + return buildEmptyResult(); } - @Override - public List searchWithBpkZp(String bpkzp) { - //TODO - return Collections.emptyList(); + private static ErnpRegisterResult buildEmptyResult() { + return new ErnpRegisterResult(Collections.emptyList()); + } - } 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 5f1e96a4..fd9a67a9 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 @@ -11,6 +11,7 @@ import org.springframework.stereotype.Service; import com.google.common.collect.Streams; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.ernp.ErnpRestClient.ErnpRegisterResult; 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; @@ -77,8 +78,8 @@ public class RegisterSearchService { final ZmrRegisterResult resultsZmr = zmrClient.searchWithPersonIdentifier( operationStatus != null ? operationStatus.getZmrProcessId() : null, eidasData.getPseudonym(), eidasData.getCitizenCountryCode()); - final List resultsErnp = ernpClient.searchWithPersonIdentifier( - eidasData.getPersonalIdentifier()); + final ErnpRegisterResult resultsErnp = ernpClient.searchWithPersonIdentifier( + eidasData.getPseudonym(), eidasData.getCitizenCountryCode()); return RegisterStatusResults.fromZmrAndErnp(resultsZmr, resultsErnp); @@ -104,9 +105,9 @@ public class RegisterSearchService { zmrClient.searchWithMds(operationStatus.getZmrProcessId(), eidasData.getGivenName(), eidasData.getFamilyName(), eidasData.getDateOfBirth(), eidasData.getCitizenCountryCode()); - final List resultsErnp = - ernpClient.searchWithMds(eidasData.getGivenName(), eidasData.getFamilyName(), eidasData - .getDateOfBirth()); + final ErnpRegisterResult resultsErnp = + ernpClient.searchWithMds(eidasData.getGivenName(), + eidasData.getFamilyName(), eidasData.getDateOfBirth(), eidasData.getCitizenCountryCode()); return RegisterStatusResults.fromZmrAndErnp(resultsZmr, resultsErnp); @@ -141,7 +142,8 @@ public class RegisterSearchService { } else { // TODO: add search procesfor for ERnP searching - return RegisterStatusResults.fromErnp(operationStatus, Collections.emptyList()); + return RegisterStatusResults.fromErnp(operationStatus, + new ErnpRegisterResult(Collections.emptyList())); } @@ -193,8 +195,8 @@ public class RegisterSearchService { return RegisterStatusResults.fromZmr(updateZmr); } else { RegisterResult entryErnp = registerResult.getResultsErnp().get(0); - RegisterResult updateErnp = ernpClient.update(entryErnp, initialEidasData); - return RegisterStatusResults.fromErnp(registerResult.operationStatus, Collections.singletonList(updateErnp)); + ErnpRegisterResult updateErnp = ernpClient.update(entryErnp, initialEidasData); + return RegisterStatusResults.fromErnp(registerResult.operationStatus, updateErnp); } } catch (final EidasSAuthenticationException e) { throw new WorkflowException("kittMatchedIdentitiess", e.getMessage(), @@ -263,9 +265,9 @@ public class RegisterSearchService { ernpClient.update(entryErnp, initialEidasData); // update ZMR entry by using eIDAS information from alternative authentication - RegisterResult updateAlt = ernpClient.update(entryErnp, altEidasData); + ErnpRegisterResult updateAlt = ernpClient.update(entryErnp, altEidasData); - return RegisterStatusResults.fromErnp(altSearchResult.operationStatus, Collections.singletonList(updateAlt)); + return RegisterStatusResults.fromErnp(altSearchResult.operationStatus, updateAlt); } } catch (final EidasSAuthenticationException e) { throw new WorkflowException("kittMatchedIdentitiess", e.getMessage(), @@ -373,13 +375,13 @@ public class RegisterSearchService { result.getPersonResult(), Collections.emptyList()); } - static RegisterStatusResults fromZmrAndErnp(ZmrRegisterResult result, List resultsErnp) { + static RegisterStatusResults fromZmrAndErnp(ZmrRegisterResult result, ErnpRegisterResult resultErnp) { return new RegisterStatusResults(new RegisterOperationStatus(result.getProcessId()), - result.getPersonResult(), resultsErnp); + result.getPersonResult(), resultErnp.getPersonResult()); } - static RegisterStatusResults fromErnp(RegisterOperationStatus status, List resultsErnp) { - return new RegisterStatusResults(status, Collections.emptyList(), resultsErnp); + static RegisterStatusResults fromErnp(RegisterOperationStatus status, ErnpRegisterResult updateErnp) { + return new RegisterStatusResults(status, Collections.emptyList(), updateErnp.getPersonResult()); } } -- cgit v1.2.3 From 8d19a4097a61723950830c79aaee3168785b683b Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Thu, 3 Feb 2022 15:51:38 +0100 Subject: feature(ernp): implement 'searchByPersonalIdentifier' as a first test version --- .../specific/modules/auth/eidas/v2/Constants.java | 57 +++- .../auth/eidas/v2/clients/ernp/ErnpRestClient.java | 374 ++++++++++++++++++++- .../auth/eidas/v2/clients/zmr/ZmrSoapClient.java | 4 +- 3 files changed, 407 insertions(+), 28 deletions(-) (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java') 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 bfb82474..d48d69bf 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 @@ -100,6 +100,31 @@ public class Constants { public static final String FORWARD_METHOD_POST = "POST"; public static final String FORWARD_METHOD_GET = "GET"; + + // Common SSL client configuration + public static final String CONIG_PROPS_EIDAS_COMMON_CLIENT = CONIG_PROPS_EIDAS_PREFIX + ".client.common"; + public static final String CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_KEYSTORE_PATH = CONIG_PROPS_EIDAS_COMMON_CLIENT + + ".ssl.keyStore.path"; + public static final String CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_KEYSTORE_PASSWORD = CONIG_PROPS_EIDAS_COMMON_CLIENT + + ".ssl.keyStore.password"; + public static final String CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_KEYSTORE_TYPE = CONIG_PROPS_EIDAS_COMMON_CLIENT + + ".ssl.keyStore.type"; + public static final String CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_KEYSTORE_NAME = CONIG_PROPS_EIDAS_COMMON_CLIENT + + ".ssl.keyStore.name"; + public static final String CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_KEYS_ALIAS = CONIG_PROPS_EIDAS_COMMON_CLIENT + + ".ssl.key.alias"; + public static final String CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_KEY_PASSWORD = CONIG_PROPS_EIDAS_COMMON_CLIENT + + ".ssl.key.password"; + public static final String CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_TRUSTSTORE_PATH = CONIG_PROPS_EIDAS_COMMON_CLIENT + + ".ssl.trustStore.path"; + public static final String CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_TRUSTSTORE_PASSWORD = CONIG_PROPS_EIDAS_COMMON_CLIENT + + ".ssl.trustStore.password"; + public static final String CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_TRUSTSTORE_TYPE = CONIG_PROPS_EIDAS_COMMON_CLIENT + + ".ssl.trustStore.type"; + public static final String CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_TRUSTSTORE_NAME = CONIG_PROPS_EIDAS_COMMON_CLIENT + + ".ssl.trustStore.name"; + + // ZMR Client configuration properties public static final String CONIG_PROPS_EIDAS_ZMRCLIENT = CONIG_PROPS_EIDAS_PREFIX + ".zmrclient"; public static final String CONIG_PROPS_EIDAS_ZMRCLIENT_ENDPOINT = CONIG_PROPS_EIDAS_ZMRCLIENT @@ -110,6 +135,12 @@ public class Constants { + ".timeout.connection"; public static final String CONIG_PROPS_EIDAS_ZMRCLIENT_TIMEOUT_RESPONSE = CONIG_PROPS_EIDAS_ZMRCLIENT + ".timeout.response"; + public static final String CONIG_PROPS_EIDAS_ZMRCLIENT_REQ_ORGANIZATION_NR = CONIG_PROPS_EIDAS_ZMRCLIENT + + ".req.organisation.behoerdennr"; + public static final String CONIG_PROPS_EIDAS_ZMRCLIENT_REQ_UPDATE_REASON_CODE = CONIG_PROPS_EIDAS_ZMRCLIENT + + ".req.update.reason.code"; + public static final String CONIG_PROPS_EIDAS_ZMRCLIENT_REQ_UPDATE_REASON_TEXT = CONIG_PROPS_EIDAS_ZMRCLIENT + + ".req.update.reason.text"; public static final String CONIG_PROPS_EIDAS_ZMRCLIENT_SSL_KEYSTORE_PATH = CONIG_PROPS_EIDAS_ZMRCLIENT + ".ssl.keyStore.path"; public static final String CONIG_PROPS_EIDAS_ZMRCLIENT_SSL_KEYSTORE_PASSWORD = CONIG_PROPS_EIDAS_ZMRCLIENT @@ -130,15 +161,21 @@ public class Constants { + ".ssl.trustStore.type"; public static final String CONIG_PROPS_EIDAS_ZMRCLIENT_SSL_TRUSTSTORE_NAME = CONIG_PROPS_EIDAS_ZMRCLIENT + ".ssl.trustStore.name"; - - public static final String CONIG_PROPS_EIDAS_ZMRCLIENT_REQ_ORGANIZATION_NR = CONIG_PROPS_EIDAS_ZMRCLIENT + + // ErnP Client configuration properties + public static final String CONIG_PROPS_EIDAS_ERNPCLIENT = CONIG_PROPS_EIDAS_PREFIX + ".ernpclient"; + public static final String CONIG_PROPS_EIDAS_ERNPCLIENT_ENDPOINT = CONIG_PROPS_EIDAS_ERNPCLIENT + + ".endpoint"; + public static final String CONIG_PROPS_EIDAS_ERNPCLIENT_DEBUG_TRACEMESSAGES = CONIG_PROPS_EIDAS_ERNPCLIENT + + ".debug.logfullmessages"; + public static final String CONIG_PROPS_EIDAS_ERNPCLIENT_TIMEOUT_CONNECTION = CONIG_PROPS_EIDAS_ERNPCLIENT + + ".timeout.connection"; + public static final String CONIG_PROPS_EIDAS_ERNPCLIENT_TIMEOUT_RESPONSE = CONIG_PROPS_EIDAS_ERNPCLIENT + + ".timeout.response"; + public static final String CONIG_PROPS_EIDAS_ERNPCLIENT_REQ_ORGANIZATION_NR = CONIG_PROPS_EIDAS_ERNPCLIENT + ".req.organisation.behoerdennr"; - public static final String CONIG_PROPS_EIDAS_ZMRCLIENT_REQ_UPDATE_REASON_CODE = CONIG_PROPS_EIDAS_ZMRCLIENT - + ".req.update.reason.code"; - public static final String CONIG_PROPS_EIDAS_ZMRCLIENT_REQ_UPDATE_REASON_TEXT = CONIG_PROPS_EIDAS_ZMRCLIENT - + ".req.update.reason.text"; - - + + // SZR Client configuration properties public static final String CONIG_PROPS_EIDAS_SZRCLIENT = CONIG_PROPS_EIDAS_PREFIX + ".szrclient"; public static final String CONIG_PROPS_EIDAS_SZRCLIENT_USETESTSERVICE = CONIG_PROPS_EIDAS_SZRCLIENT @@ -255,8 +292,10 @@ public class Constants { public static final String SZR_SCHEMA_LOCATIONS = "urn:SZRServices" + " " + "/szr_client/szr.xsd"; - // Default values for SZR communication + // Default values for SZR / ZMR / ERnP communication public static final String SZR_CONSTANTS_DEFAULT_DOCUMENT_TYPE = "ELEKTR_DOKUMENT"; + public static final String CLIENT_INFO = "eIDAS MS-Connector v{0}"; + // AuthBlock public static final String SZR_AUTHBLOCK = "authData_AUTHBLOCK"; diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java index 7763fc9d..a651385f 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java @@ -1,13 +1,62 @@ package at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.ernp; +import java.io.IOException; +import java.text.MessageFormat; +import java.time.OffsetDateTime; +import java.util.Arrays; +import java.util.Collections; import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import javax.annotation.Nonnull; +import javax.annotation.PostConstruct; + +import org.apache.http.client.HttpClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.client.ClientHttpRequestFactory; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; +import org.springframework.web.client.ResponseErrorHandler; +import org.springframework.web.client.RestTemplate; + +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.databind.ObjectMapper; + +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.dao.SimpleEidasData; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.api.DefaultApi; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.invoker.ApiClient; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.PartialDate; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.Person; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.PersonSuchen; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.SuchEidas; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.Suchdaten; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.SuchenResponse; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.Suchoptionen; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.Suchoptionen.HistorischEnum; import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasSAuthenticationException; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.WorkflowException; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.VersionHolder; import at.gv.bmi.namespace.zmr_su.zmr._20040201.PersonSuchenRequest; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EaafAuthenticationException; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory; +import at.gv.egiz.eaaf.core.impl.http.HttpClientConfiguration; +import at.gv.egiz.eaaf.core.impl.http.HttpClientConfiguration.ClientAuthMode; +import at.gv.egiz.eaaf.core.impl.http.IHttpClientFactory; +import at.gv.egiz.eaaf.core.impl.utils.TransactionIdUtils; import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Getter; +import lombok.extern.slf4j.Slf4j; /** * Implements an ERnP client that uses REST API for communication. @@ -15,51 +64,344 @@ import lombok.Getter; * @author tlenz * */ +@Slf4j public class ErnpRestClient implements IErnpClient { - @AllArgsConstructor - @Getter - public static class ErnpRegisterResult { - private final List personResult; - - } + private static final String ERROR_MATCHING_01 = "module.eidasauth.matching.01"; + private static final String ERROR_MATCHING_02 = "module.eidasauth.matching.02"; + private static final String ERROR_MATCHING_99 = "module.eidasauth.matching.99"; + + private static final String LOGMSG_ERNP_ERROR = + "Receive an error from ERnP during '{}' operation with msg: {}"; + private static final String LOGMSG_ERNP_RESP_PROCESS = + "Proces ERnP response during '{}' operation failes with msg: {}"; + + private static final String LOGMSG_ERNP_SOAP_ERROR = + "ERnP anwser for transaction: {0} with code: {1} and message: {2}"; + + private static final String PROCESS_SEARCH_PERSONAL_IDENTIFIER = + "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_KITT_GENERAL = "KITT general-processing"; + private static final String PROCESS_KITT_IDENITIES_GET = "KITT get-latest-version"; + private static final String PROCESS_KITT_IDENITIES_UPDATE = "KITT update dataset"; + + private static final String FRIENDLYNAME_HTTP_CLIENT = "ERnP Client"; + + private static final String PATTERN_BIRTHDAY_STRING = "{0}-{1}-{2}"; + + + @Autowired IConfiguration basicConfig; + @Autowired EaafKeyStoreFactory keyStoreFactory; + @Autowired IHttpClientFactory httpClientFactory; + @Autowired VersionHolder versionHolder; + + private DefaultApi ernpClient; + @Override public ErnpRegisterResult searchWithPersonIdentifier(String personIdentifier, String citizenCountryCode) throws EidasSAuthenticationException { - // TODO Auto-generated method stub - return null; - } + + try { + + // build generic request metadata + GenericRequestParams generic = buildGenericRequestParameters("step1"); + // build search request + SuchEidas eidasInfos = new SuchEidas(); + eidasInfos.setArt(Constants.eIDAS_ATTRURN_PERSONALIDENTIFIER); + eidasInfos.setWert(personIdentifier); + eidasInfos.setStaatscode2(citizenCountryCode); + + PersonSuchen personSuchen = new PersonSuchen(); + personSuchen.setSuchoptionen(generateSearchParameters()); + personSuchen.setBegruendung(PROCESS_SEARCH_PERSONAL_IDENTIFIER); + Suchdaten searchInfos = new Suchdaten(); + searchInfos.setEidas(eidasInfos); + personSuchen.setSuchdaten(searchInfos); + + // request ERnP + log.trace("Requesting ERnP for '{}' operation", PROCESS_SEARCH_PERSONAL_IDENTIFIER); + SuchenResponse resp = ernpClient.suchen(generic.getClientBehkz(), generic.clientName, + generic.getClientRequestTime(), generic.getClientRequestId(), personSuchen); + + // parse ZMR response + return processErnpResponse(resp, citizenCountryCode, true, PROCESS_SEARCH_PERSONAL_IDENTIFIER); + + } catch (EidasSAuthenticationException e) { + throw e; + + } catch (Exception e) { + log.warn(LOGMSG_ERNP_RESP_PROCESS, PROCESS_SEARCH_PERSONAL_IDENTIFIER, e.getMessage()); + throw new EidasSAuthenticationException(ERROR_MATCHING_99, new Object[] { e.getMessage() }, e); + } + + } + @Override public ErnpRegisterResult searchWithMds(String givenName, String familyName, String dateOfBirth, String citizenCountryCode) throws EidasSAuthenticationException { - // TODO Auto-generated method stub - return null; + return new ErnpRegisterResult(Collections.emptyList()); } @Override public ErnpRegisterResult searchCountrySpecific(PersonSuchenRequest personSearchDao, String citizenCountryCode) throws EidasSAuthenticationException { - // TODO Auto-generated method stub - return null; + return new ErnpRegisterResult(Collections.emptyList()); } @Override public ErnpRegisterResult update(RegisterResult registerResult, SimpleEidasData eidData) throws EidasSAuthenticationException { - // TODO Auto-generated method stub - return null; + return new ErnpRegisterResult(Collections.emptyList()); } @Override public ErnpRegisterResult searchWithResidenceData(String givenName, String familyName, String dateOfBirth, String zipcode, String city, String street) { + return new ErnpRegisterResult(Collections.emptyList()); + } + + @PostConstruct + private void initialize() throws EaafException { + // set-up the Ernp client + ernpClient = new DefaultApi(new ApiClient(buildRestClient())); + + // validate additional Ernp communication parameters + valdiateAdditionalConfigParameters(); + + } + + private void valdiateAdditionalConfigParameters() { // TODO Auto-generated method stub - return null; + + } + + private Suchoptionen generateSearchParameters() { + Suchoptionen options = new Suchoptionen(); + options.setZmr(false); + options.setHistorisch(HistorischEnum.AKTUELLUNDHISTORISCH); + options.setSucheMitNamensteilen(false); + options.setSuchwizard(false); + return options; + + } + + @Nonnull + private ErnpRegisterResult processErnpResponse(SuchenResponse resp, @Nonnull String citizenCountryCode, + boolean forceSinglePersonMatch, @Nonnull String processStepFiendlyname) throws EaafAuthenticationException { + if (resp.getPerson() == null + || resp.getPerson().isEmpty()) { + log.debug("ERnP result contains NO 'Person' or 'Person' is empty"); + return new ErnpRegisterResult(Collections.emptyList()); + + } else { + log.debug("Get #{} person results from '{}' operation", + resp.getPerson().size(), processStepFiendlyname); + + if (forceSinglePersonMatch) { + return new ErnpRegisterResult(processSearchPersonResponseSingleResult( + resp.getPerson(), citizenCountryCode, processStepFiendlyname)); + + } else { + return new ErnpRegisterResult(processSearchPersonResponse( + resp.getPerson(), citizenCountryCode)); + + } + } + } + + @Nonnull + private List processSearchPersonResponse( + @Nonnull List list, + @Nonnull String citizenCountryCode) throws EaafAuthenticationException { + return list.stream() + .map(el -> mapErnpResponseToRegisterResult(el, citizenCountryCode)) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + } + @NonNull + private List processSearchPersonResponseSingleResult( + @Nonnull List persons, + @Nonnull String citizenCountryCode, String processStepFiendlyname) throws EaafAuthenticationException { + if (persons.size() > 1) { + log.error("Find more-than-one ERnP entry with search criteria that has to be unique"); + throw new WorkflowException(processStepFiendlyname, + "Find more-than-one ERnP entry with search criteria that has to be unique", true); + + } else { + return Arrays.asList(mapErnpResponseToRegisterResult(persons.get(0), citizenCountryCode)); + + } + } + + @Nonnull + private RegisterResult mapErnpResponseToRegisterResult(@Nonnull Person person, + @Nonnull String citizenCountryCode) { + // build result + return RegisterResult.builder() + .pseudonym(selectAllEidasDocument(person, citizenCountryCode, + Constants.eIDAS_ATTRURN_PERSONALIDENTIFIER)) + .familyName(person.getPersonendaten().getFamilienname()) + .givenName(person.getPersonendaten().getVorname()) + .dateOfBirth(buildTextualBirthday(person.getPersonendaten().getGeburtsdatum())) + .bpk(person.getPersonendaten().getBpkZp()) + .placeOfBirth(selectSingleEidasDocument(person, citizenCountryCode, + Constants.eIDAS_ATTRURN_PLACEOFBIRTH)) + .birthName(selectSingleEidasDocument(person, citizenCountryCode, + Constants.eIDAS_ATTRURN_BIRTHNAME)) + .build(); + + } + + private String buildTextualBirthday(PartialDate geburtsdatum) { + return MessageFormat.format(PATTERN_BIRTHDAY_STRING, + geburtsdatum.getJahr(), geburtsdatum.getMonat(), geburtsdatum.getTag()); + + } + + /** + * Get all eIDAS document with the specified country code and document type. + * + * @param person Person information from ERnP + * @param citizenCountryCode Country code of the eIDAS attribute + * @param eidasAttrurnPersonalidentifier eIDAS attribute identifier + * @return {@link List} of eIDAS attribute values or an empty list if's not + * found + */ + @NonNull + private List selectAllEidasDocument(Person person, String citizenCountryCode, + String eidasAttrurnPersonalidentifier) { + return person.getEidas().stream() + .filter(el -> eidasAttrurnPersonalidentifier.equals(el.getArt()) + && el.getStaatscode2().equals(citizenCountryCode)) + .map(el -> el.getWert()) + .collect(Collectors.toList()); + + } + + /** + * Get the first eIDAS document with the specified country code and document + * type. + * + * @param person Person information from ERnP + * @param citizenCountryCode Country code of the eIDAS attribute + * @param eidasAttrurnPersonalidentifier eIDAS attribute identifier + * @return Value of this eIDAS attribute or null if's not found + */ + @Nullable + private String selectSingleEidasDocument(Person person, String citizenCountryCode, + String eidasAttrurnPersonalidentifier) { + return person.getEidas().stream() + .filter(el -> eidasAttrurnPersonalidentifier.equals(el.getArt()) + && el.getStaatscode2().equals(citizenCountryCode)) + .findFirst() + .map(el -> el.getWert()) + .orElse(null); + + } + + private RestTemplate buildRestClient() throws EaafException { + log.debug("Building REST-Client for ERnP communication ... "); + final HttpClient httpClient = httpClientFactory.getHttpClient(buildHttpClientConfiguration()); + final ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient); + final RestTemplate springClient = new RestTemplate(requestFactory); + springClient.setErrorHandler(buildErrorHandler()); + springClient.getMessageConverters().add(0, buildCustomJacksonObjectMapper()); + return springClient; + + } + + private HttpMessageConverter buildCustomJacksonObjectMapper() { + MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.setSerializationInclusion(Include.NON_NULL); + converter.setObjectMapper(objectMapper); + return converter; + + } + + @Nonnull + private ResponseErrorHandler buildErrorHandler() { + return new ResponseErrorHandler() { + + @Override + public boolean hasError(ClientHttpResponse response) throws IOException { + return response.getStatusCode().is4xxClientError() + || response.getStatusCode().is5xxServerError(); + + } + + @Override + public void handleError(ClientHttpResponse response) throws IOException { + //TODO: implement errorHandling based on response infos + + if (response.getStatusCode().series() == HttpStatus.Series.SERVER_ERROR) { + log.warn("Receive http-server-error: {} from ERnP", response.getRawStatusCode()); + + } else if (response.getStatusCode().series() == HttpStatus.Series.CLIENT_ERROR) { + log.warn("Receive http-client-error: {} from ERnP", response.getRawStatusCode()); + + } + } + }; + } + @Nonnull + private HttpClientConfiguration buildHttpClientConfiguration() throws EaafException { + final HttpClientConfiguration config = new HttpClientConfiguration(FRIENDLYNAME_HTTP_CLIENT); + config.setAuthMode(ClientAuthMode.SSL.getMode()); + + // Set keystore configuration + config.buildKeyStoreConfig( + basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_KEYSTORE_TYPE), + basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_KEYSTORE_PATH), + basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_KEYSTORE_PASSWORD), + basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_KEYSTORE_NAME)); + // Set key information + config.setSslKeyAlias( + basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_KEYS_ALIAS)); + config.setSslKeyPassword( + basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_KEY_PASSWORD)); + + // Set connection parameters + //TODO: update EAAF-components to allow custom HTTP Connection-Timeouts + + return config; + } + + + @AllArgsConstructor + @Getter + public static class ErnpRegisterResult { + private final List personResult; + + } + + private GenericRequestParams buildGenericRequestParameters(String operationIdentifier) { + return GenericRequestParams.builder() + .clientBehkz(basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_ZMRCLIENT_REQ_ORGANIZATION_NR)) + .clientName(MessageFormat.format(Constants.CLIENT_INFO, versionHolder.getVersion())) + .clientRequestTime(OffsetDateTime.now()) + .clientRequestId(TransactionIdUtils.getTransactionId() + "_" + operationIdentifier) + .build(); + + } + + @Builder + @Getter + private static class GenericRequestParams { + String clientBehkz; + String clientName; + OffsetDateTime clientRequestTime; + String clientRequestId; + + } } 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 711226e2..432df9ef 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 @@ -100,7 +100,6 @@ public class ZmrSoapClient extends AbstractSoapClient implements IZmrClient { private static final String PROCESS_KITT_IDENITIES_GET = "KITT get-latest-version"; private static final String PROCESS_KITT_IDENITIES_UPDATE = "KITT update dataset"; - private static final String CLIENT_INFO = "eIDAS MS-Connector v{0}"; private static final String CLIENT_DEFAULT = "ZMR Client"; @@ -429,7 +428,7 @@ public class ZmrSoapClient extends AbstractSoapClient implements IZmrClient { clientInfo.setOrganisation(clientOrganisation); // set client information - clientInfo.setClient(MessageFormat.format(CLIENT_INFO, versionHolder.getVersion())); + clientInfo.setClient(MessageFormat.format(Constants.CLIENT_INFO, versionHolder.getVersion())); // set Behoerdennummer as organization identifier clientOrganisation.setBehoerdenNr(basicConfig.getBasicConfiguration( @@ -465,7 +464,6 @@ public class ZmrSoapClient extends AbstractSoapClient implements IZmrClient { return new ZmrRegisterResult(Collections.emptyList(), extractZmrProcessId(resp.getWorkflowInfoServer())); } else { - // TODO: what we to with ERnP results? log.debug("Get #{} person results from '{}' operation", searchPersonResp.getPersonensuchergebnis().getGefundeneSaetze(), processStepFiendlyname); -- cgit v1.2.3 From 84bb45ecb417f6a92b7d8884048bd7901c6b1b42 Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Thu, 3 Feb 2022 20:28:50 +0100 Subject: fix(ernp): fix some bugs in ERnP client implementation --- .../specific/modules/auth/eidas/v2/Constants.java | 2 - .../auth/eidas/v2/clients/ernp/ErnpRestClient.java | 265 ++++++++++++--------- .../exception/ErnpRestCommunicationException.java | 24 ++ 3 files changed, 180 insertions(+), 111 deletions(-) create mode 100644 eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/ErnpRestCommunicationException.java (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java') 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 d48d69bf..6da30299 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 @@ -166,8 +166,6 @@ public class Constants { public static final String CONIG_PROPS_EIDAS_ERNPCLIENT = CONIG_PROPS_EIDAS_PREFIX + ".ernpclient"; public static final String CONIG_PROPS_EIDAS_ERNPCLIENT_ENDPOINT = CONIG_PROPS_EIDAS_ERNPCLIENT + ".endpoint"; - public static final String CONIG_PROPS_EIDAS_ERNPCLIENT_DEBUG_TRACEMESSAGES = CONIG_PROPS_EIDAS_ERNPCLIENT - + ".debug.logfullmessages"; public static final String CONIG_PROPS_EIDAS_ERNPCLIENT_TIMEOUT_CONNECTION = CONIG_PROPS_EIDAS_ERNPCLIENT + ".timeout.connection"; public static final String CONIG_PROPS_EIDAS_ERNPCLIENT_TIMEOUT_RESPONSE = CONIG_PROPS_EIDAS_ERNPCLIENT diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java index a651385f..605f1d0f 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java @@ -2,6 +2,7 @@ package at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.ernp; import java.io.IOException; import java.text.MessageFormat; +import java.time.LocalDate; import java.time.OffsetDateTime; import java.util.Arrays; import java.util.Collections; @@ -12,9 +13,11 @@ import java.util.stream.Collectors; import javax.annotation.Nonnull; import javax.annotation.PostConstruct; +import org.apache.commons.lang3.StringUtils; import org.apache.http.client.HttpClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.ClientHttpResponse; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; @@ -23,10 +26,10 @@ import org.springframework.http.converter.json.MappingJackson2HttpMessageConvert import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; import org.springframework.web.client.ResponseErrorHandler; +import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestTemplate; import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.fasterxml.jackson.databind.ObjectMapper; import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.RegisterResult; @@ -42,6 +45,7 @@ import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.SuchenRes import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.Suchoptionen; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.Suchoptionen.HistorischEnum; import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasSAuthenticationException; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.ErnpRestCommunicationException; import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.WorkflowException; import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.VersionHolder; import at.gv.bmi.namespace.zmr_su.zmr._20040201.PersonSuchenRequest; @@ -60,17 +64,18 @@ import lombok.extern.slf4j.Slf4j; /** * Implements an ERnP client that uses REST API for communication. - * + * * @author tlenz * */ @Slf4j public class ErnpRestClient implements IErnpClient { - private static final String ERROR_MATCHING_01 = "module.eidasauth.matching.01"; - private static final String ERROR_MATCHING_02 = "module.eidasauth.matching.02"; + private static final String ERROR_MATCHING_11 = "module.eidasauth.matching.11"; + private static final String ERROR_MATCHING_12 = "module.eidasauth.matching.12"; private static final String ERROR_MATCHING_99 = "module.eidasauth.matching.99"; - + + private static final String LOGMSG_MISSING_CONFIG = "Missing configuration with key: {0}"; private static final String LOGMSG_ERNP_ERROR = "Receive an error from ERnP during '{}' operation with msg: {}"; private static final String LOGMSG_ERNP_RESP_PROCESS = @@ -78,69 +83,73 @@ public class ErnpRestClient implements IErnpClient { private static final String LOGMSG_ERNP_SOAP_ERROR = "ERnP anwser for transaction: {0} with code: {1} and message: {2}"; - - private static final String PROCESS_SEARCH_PERSONAL_IDENTIFIER = + + private static final String PROCESS_SEARCH_PERSONAL_IDENTIFIER = "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_KITT_GENERAL = "KITT general-processing"; private static final String PROCESS_KITT_IDENITIES_GET = "KITT get-latest-version"; private static final String PROCESS_KITT_IDENITIES_UPDATE = "KITT update dataset"; - + private static final String FRIENDLYNAME_HTTP_CLIENT = "ERnP Client"; - - private static final String PATTERN_BIRTHDAY_STRING = "{0}-{1}-{2}"; - - - @Autowired IConfiguration basicConfig; - @Autowired EaafKeyStoreFactory keyStoreFactory; - @Autowired IHttpClientFactory httpClientFactory; - @Autowired VersionHolder versionHolder; - + + @Autowired + IConfiguration basicConfig; + @Autowired + EaafKeyStoreFactory keyStoreFactory; + @Autowired + IHttpClientFactory httpClientFactory; + @Autowired + VersionHolder versionHolder; + private DefaultApi ernpClient; - @Override public ErnpRegisterResult searchWithPersonIdentifier(String personIdentifier, String citizenCountryCode) throws EidasSAuthenticationException { - + try { - + // build generic request metadata - GenericRequestParams generic = buildGenericRequestParameters("step1"); + final GenericRequestParams generic = buildGenericRequestParameters("step1"); - // build search request - SuchEidas eidasInfos = new SuchEidas(); + // build search request + final SuchEidas eidasInfos = new SuchEidas(); eidasInfos.setArt(Constants.eIDAS_ATTRURN_PERSONALIDENTIFIER); eidasInfos.setWert(personIdentifier); eidasInfos.setStaatscode2(citizenCountryCode); - - PersonSuchen personSuchen = new PersonSuchen(); + + final PersonSuchen personSuchen = new PersonSuchen(); personSuchen.setSuchoptionen(generateSearchParameters()); - personSuchen.setBegruendung(PROCESS_SEARCH_PERSONAL_IDENTIFIER); - Suchdaten searchInfos = new Suchdaten(); - searchInfos.setEidas(eidasInfos); + personSuchen.setBegruendung(PROCESS_SEARCH_PERSONAL_IDENTIFIER); + final Suchdaten searchInfos = new Suchdaten(); + searchInfos.setEidas(eidasInfos); personSuchen.setSuchdaten(searchInfos); - + // request ERnP log.trace("Requesting ERnP for '{}' operation", PROCESS_SEARCH_PERSONAL_IDENTIFIER); - SuchenResponse resp = ernpClient.suchen(generic.getClientBehkz(), generic.clientName, + final SuchenResponse resp = ernpClient.suchen(generic.getClientBehkz(), generic.clientName, generic.getClientRequestTime(), generic.getClientRequestId(), personSuchen); - + // parse ZMR response return processErnpResponse(resp, citizenCountryCode, true, PROCESS_SEARCH_PERSONAL_IDENTIFIER); + + } catch (RestClientException e) { + log.warn(LOGMSG_ERNP_ERROR, PROCESS_SEARCH_PERSONAL_IDENTIFIER, e.getMessage()); + throw new EidasSAuthenticationException(ERROR_MATCHING_11, new Object[] { e.getMessage() }, e); - } catch (EidasSAuthenticationException e) { + } catch (final EidasSAuthenticationException e) { throw e; - - } catch (Exception e) { + + } catch (final Exception e) { log.warn(LOGMSG_ERNP_RESP_PROCESS, PROCESS_SEARCH_PERSONAL_IDENTIFIER, e.getMessage()); throw new EidasSAuthenticationException(ERROR_MATCHING_99, new Object[] { e.getMessage() }, e); } - + } - + @Override public ErnpRegisterResult searchWithMds(String givenName, String familyName, String dateOfBirth, String citizenCountryCode) throws EidasSAuthenticationException { @@ -164,54 +173,66 @@ public class ErnpRestClient implements IErnpClient { String zipcode, String city, String street) { return new ErnpRegisterResult(Collections.emptyList()); } - + @PostConstruct private void initialize() throws EaafException { - // set-up the Ernp client - ernpClient = new DefaultApi(new ApiClient(buildRestClient())); - // validate additional Ernp communication parameters valdiateAdditionalConfigParameters(); - + + // set-up the Ernp client + final ApiClient baseClient = new ApiClient(buildRestClient()); + baseClient.setBasePath(basicConfig.getBasicConfiguration( + Constants.CONIG_PROPS_EIDAS_ERNPCLIENT_ENDPOINT)); + ernpClient = new DefaultApi(baseClient); + } - + private void valdiateAdditionalConfigParameters() { - // TODO Auto-generated method stub - + checkConfigurationValue(Constants.CONIG_PROPS_EIDAS_ERNPCLIENT_ENDPOINT); + checkConfigurationValue(Constants.CONIG_PROPS_EIDAS_ERNPCLIENT_REQ_ORGANIZATION_NR); + + } + + private void checkConfigurationValue(String key) { + if (StringUtils.isEmpty(basicConfig.getBasicConfiguration(key))) { + throw new RuntimeException(MessageFormat.format(LOGMSG_MISSING_CONFIG, key)); + + } } private Suchoptionen generateSearchParameters() { - Suchoptionen options = new Suchoptionen(); + final Suchoptionen options = new Suchoptionen(); options.setZmr(false); options.setHistorisch(HistorischEnum.AKTUELLUNDHISTORISCH); options.setSucheMitNamensteilen(false); - options.setSuchwizard(false); + options.setSuchwizard(false); return options; - + } @Nonnull private ErnpRegisterResult processErnpResponse(SuchenResponse resp, @Nonnull String citizenCountryCode, - boolean forceSinglePersonMatch, @Nonnull String processStepFiendlyname) throws EaafAuthenticationException { - if (resp.getPerson() == null + boolean forceSinglePersonMatch, @Nonnull String processStepFiendlyname) + throws EaafAuthenticationException { + if (resp.getPerson() == null || resp.getPerson().isEmpty()) { log.debug("ERnP result contains NO 'Person' or 'Person' is empty"); return new ErnpRegisterResult(Collections.emptyList()); - - } else { - log.debug("Get #{} person results from '{}' operation", + + } else { + log.debug("Get #{} person results from '{}' operation", resp.getPerson().size(), processStepFiendlyname); - + if (forceSinglePersonMatch) { return new ErnpRegisterResult(processSearchPersonResponseSingleResult( resp.getPerson(), citizenCountryCode, processStepFiendlyname)); - + } else { return new ErnpRegisterResult(processSearchPersonResponse( resp.getPerson(), citizenCountryCode)); - - } - } + + } + } } @Nonnull @@ -224,22 +245,22 @@ public class ErnpRestClient implements IErnpClient { .collect(Collectors.toList()); } - + @NonNull private List processSearchPersonResponseSingleResult( @Nonnull List persons, @Nonnull String citizenCountryCode, String processStepFiendlyname) throws EaafAuthenticationException { if (persons.size() > 1) { log.error("Find more-than-one ERnP entry with search criteria that has to be unique"); - throw new WorkflowException(processStepFiendlyname, + throw new WorkflowException(processStepFiendlyname, "Find more-than-one ERnP entry with search criteria that has to be unique", true); - + } else { return Arrays.asList(mapErnpResponseToRegisterResult(persons.get(0), citizenCountryCode)); } } - + @Nonnull private RegisterResult mapErnpResponseToRegisterResult(@Nonnull Person person, @Nonnull String citizenCountryCode) { @@ -254,15 +275,28 @@ public class ErnpRestClient implements IErnpClient { .placeOfBirth(selectSingleEidasDocument(person, citizenCountryCode, Constants.eIDAS_ATTRURN_PLACEOFBIRTH)) .birthName(selectSingleEidasDocument(person, citizenCountryCode, - Constants.eIDAS_ATTRURN_BIRTHNAME)) + Constants.eIDAS_ATTRURN_BIRTHNAME)) .build(); } - + + /** + * Build AT specific Date String 'yyyy-MM-dd' from ERnP birthday representation. + * + *

+ * Info: {@link LocalDate} can not be used, because '1940-00-00' is also + * a valid birthday on ERnP site. + *

+ * + * @param geburtsdatum ERnP birthday representation + * @return birthday in 'yyyy-MM-dd' format + */ private String buildTextualBirthday(PartialDate geburtsdatum) { - return MessageFormat.format(PATTERN_BIRTHDAY_STRING, - geburtsdatum.getJahr(), geburtsdatum.getMonat(), geburtsdatum.getTag()); - + return MessageFormat.format("{0}-{1}-{2}", + String.valueOf(geburtsdatum.getJahr()), + String.format("%02d", geburtsdatum.getMonat()), + String.format("%02d", geburtsdatum.getTag())); + } /** @@ -276,12 +310,18 @@ public class ErnpRestClient implements IErnpClient { */ @NonNull private List selectAllEidasDocument(Person person, String citizenCountryCode, - String eidasAttrurnPersonalidentifier) { - return person.getEidas().stream() - .filter(el -> eidasAttrurnPersonalidentifier.equals(el.getArt()) - && el.getStaatscode2().equals(citizenCountryCode)) - .map(el -> el.getWert()) - .collect(Collectors.toList()); + String eidasAttrurnPersonalidentifier) { + if (person.getEidas() != null) { + return person.getEidas().stream() + .filter(el -> eidasAttrurnPersonalidentifier.equals(el.getArt()) + && el.getStaatscode2().equals(citizenCountryCode)) + .map(el -> el.getWert()) + .collect(Collectors.toList()); + + } else { + return Collections.emptyList(); + + } } @@ -297,15 +337,20 @@ public class ErnpRestClient implements IErnpClient { @Nullable private String selectSingleEidasDocument(Person person, String citizenCountryCode, String eidasAttrurnPersonalidentifier) { - return person.getEidas().stream() - .filter(el -> eidasAttrurnPersonalidentifier.equals(el.getArt()) - && el.getStaatscode2().equals(citizenCountryCode)) - .findFirst() - .map(el -> el.getWert()) - .orElse(null); + if (person.getEidas() != null) { + return person.getEidas().stream() + .filter(el -> eidasAttrurnPersonalidentifier.equals(el.getArt()) + && el.getStaatscode2().equals(citizenCountryCode)) + .findFirst() + .map(el -> el.getWert()) + .orElse(null); + + } else { + return null; + } } - + private RestTemplate buildRestClient() throws EaafException { log.debug("Building REST-Client for ERnP communication ... "); final HttpClient httpClient = httpClientFactory.getHttpClient(buildHttpClientConfiguration()); @@ -316,42 +361,44 @@ public class ErnpRestClient implements IErnpClient { return springClient; } - + private HttpMessageConverter buildCustomJacksonObjectMapper() { - MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); - ObjectMapper objectMapper = new ObjectMapper(); - objectMapper.setSerializationInclusion(Include.NON_NULL); - converter.setObjectMapper(objectMapper); + final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); + converter.setSupportedMediaTypes(Collections.singletonList(MediaType.ALL)); + converter.getObjectMapper() + .setSerializationInclusion(Include.NON_NULL); return converter; - + } - + @Nonnull private ResponseErrorHandler buildErrorHandler() { return new ResponseErrorHandler() { @Override public boolean hasError(ClientHttpResponse response) throws IOException { - return response.getStatusCode().is4xxClientError() - || response.getStatusCode().is5xxServerError(); - + return response.getStatusCode().is4xxClientError() + || response.getStatusCode().is5xxServerError(); + } @Override - public void handleError(ClientHttpResponse response) throws IOException { - //TODO: implement errorHandling based on response infos - + public void handleError(ClientHttpResponse response) throws IOException { + // TODO: implement errorHandling based on response infos + if (response.getStatusCode().series() == HttpStatus.Series.SERVER_ERROR) { log.warn("Receive http-server-error: {} from ERnP", response.getRawStatusCode()); - + } else if (response.getStatusCode().series() == HttpStatus.Series.CLIENT_ERROR) { log.warn("Receive http-client-error: {} from ERnP", response.getRawStatusCode()); - + } + + throw new ErnpRestCommunicationException(response.getRawStatusCode()); } }; } - + @Nonnull private HttpClientConfiguration buildHttpClientConfiguration() throws EaafException { final HttpClientConfiguration config = new HttpClientConfiguration(FRIENDLYNAME_HTTP_CLIENT); @@ -369,39 +416,39 @@ public class ErnpRestClient implements IErnpClient { basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_KEYS_ALIAS)); config.setSslKeyPassword( basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_COMMON_CLIENT_SSL_KEY_PASSWORD)); - + // Set connection parameters - //TODO: update EAAF-components to allow custom HTTP Connection-Timeouts - + // TODO: update EAAF-components to allow custom HTTP Connection-Timeouts + return config; } - @AllArgsConstructor @Getter public static class ErnpRegisterResult { private final List personResult; - + } private GenericRequestParams buildGenericRequestParameters(String operationIdentifier) { return GenericRequestParams.builder() - .clientBehkz(basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_ZMRCLIENT_REQ_ORGANIZATION_NR)) + .clientBehkz(basicConfig.getBasicConfiguration( + Constants.CONIG_PROPS_EIDAS_ZMRCLIENT_REQ_ORGANIZATION_NR)) .clientName(MessageFormat.format(Constants.CLIENT_INFO, versionHolder.getVersion())) .clientRequestTime(OffsetDateTime.now()) .clientRequestId(TransactionIdUtils.getTransactionId() + "_" + operationIdentifier) - .build(); - + .build(); + } - + @Builder @Getter - private static class GenericRequestParams { + private static class GenericRequestParams { String clientBehkz; - String clientName; - OffsetDateTime clientRequestTime; + String clientName; + OffsetDateTime clientRequestTime; String clientRequestId; - + } } diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/ErnpRestCommunicationException.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/ErnpRestCommunicationException.java new file mode 100644 index 00000000..72a5ece6 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/ErnpRestCommunicationException.java @@ -0,0 +1,24 @@ +package at.asitplus.eidas.specific.modules.auth.eidas.v2.exception; + +import java.io.IOException; + +import lombok.Getter; + +/** + * ERnP exception in case of a REST communication error. + * + * @author tlenz + * + */ +public class ErnpRestCommunicationException extends IOException { + private static final long serialVersionUID = -3178689122077228976L; + + @Getter + int httpStatusCode; + + public ErnpRestCommunicationException(int rawStatusCode) { + super("ERnP service answers with an error and HTTP status-code: " + rawStatusCode); + this.httpStatusCode = rawStatusCode; + } + +} -- cgit v1.2.3 From 87a347c359ec7ee2a39bfcace1975f60c4eb9375 Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Mon, 7 Feb 2022 07:55:13 +0100 Subject: feature(ernp): port search and update steps from ZMR client to ERnP client because we need the same functionality on different API --- .../auth/eidas/v2/clients/ernp/ErnpRestClient.java | 308 +++++++++++++++++++-- .../exception/ErnpRestCommunicationException.java | 4 +- .../eidas/v2/service/RegisterSearchService.java | 24 +- .../auth/eidas/v2/tasks/InitialSearchTask.java | 5 +- 4 files changed, 310 insertions(+), 31 deletions(-) (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java') diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java index 605f1d0f..2eaece1d 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java @@ -5,9 +5,13 @@ import java.text.MessageFormat; import java.time.LocalDate; import java.time.OffsetDateTime; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Objects; +import java.util.Optional; +import java.util.Set; import java.util.stream.Collectors; import javax.annotation.Nonnull; @@ -16,7 +20,6 @@ import javax.annotation.PostConstruct; import org.apache.commons.lang3.StringUtils; import org.apache.http.client.HttpClient; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.ClientHttpResponse; @@ -25,6 +28,7 @@ import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; +import org.springframework.util.Assert; import org.springframework.web.client.ResponseErrorHandler; import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestTemplate; @@ -36,8 +40,11 @@ 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.dao.ernp.api.DefaultApi; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.invoker.ApiClient; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.AendernResponse; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.Eidas; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.PartialDate; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.Person; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.PersonAendern; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.PersonSuchen; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.SuchEidas; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.Suchdaten; @@ -48,6 +55,7 @@ import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasSAuthenti import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.ErnpRestCommunicationException; import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.WorkflowException; import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.VersionHolder; +import at.gv.bmi.namespace.zmr_su.base._20040201_.ServiceFault; import at.gv.bmi.namespace.zmr_su.zmr._20040201.PersonSuchenRequest; import at.gv.egiz.eaaf.core.api.idp.IConfiguration; import at.gv.egiz.eaaf.core.exceptions.EaafAuthenticationException; @@ -81,7 +89,7 @@ public class ErnpRestClient implements IErnpClient { private static final String LOGMSG_ERNP_RESP_PROCESS = "Proces ERnP response during '{}' operation failes with msg: {}"; - private static final String LOGMSG_ERNP_SOAP_ERROR = + private static final String LOGMSG_ERNP_REST_ERROR = "ERnP anwser for transaction: {0} with code: {1} and message: {2}"; private static final String PROCESS_SEARCH_PERSONAL_IDENTIFIER = @@ -95,6 +103,10 @@ public class ErnpRestClient implements IErnpClient { private static final String FRIENDLYNAME_HTTP_CLIENT = "ERnP Client"; + // HTTP header-names from ERnP response + private static final String ERNP_RESPONSE_HEADER_SERVER_ID = "Server-Request-Id"; + + @Autowired IConfiguration basicConfig; @Autowired @@ -109,11 +121,9 @@ public class ErnpRestClient implements IErnpClient { @Override public ErnpRegisterResult searchWithPersonIdentifier(String personIdentifier, String citizenCountryCode) throws EidasSAuthenticationException { - try { - // build generic request metadata - final GenericRequestParams generic = buildGenericRequestParameters("step1"); + final GenericRequestParams generic = buildGenericRequestParameters("stepId"); // build search request final SuchEidas eidasInfos = new SuchEidas(); @@ -153,19 +163,242 @@ public class ErnpRestClient implements IErnpClient { @Override public ErnpRegisterResult searchWithMds(String givenName, String familyName, String dateOfBirth, String citizenCountryCode) throws EidasSAuthenticationException { - return new ErnpRegisterResult(Collections.emptyList()); + try { + // build generic request metadata + final GenericRequestParams generic = buildGenericRequestParameters("stepMDS"); + + // build search request + final Suchdaten searchInfos = new Suchdaten(); + searchInfos.setFamilienname(familyName); + searchInfos.setVorname(givenName); + searchInfos.setGeburtsdatum(buildErnpBirthday(dateOfBirth)); + + final PersonSuchen personSuchen = new PersonSuchen(); + personSuchen.setSuchoptionen(generateSearchParameters()); + personSuchen.setBegruendung(PROCESS_SEARCH_MDS_ONLY); + personSuchen.setSuchdaten(searchInfos); + + // request ERnP + log.trace("Requesting ERnP for '{}' operation", PROCESS_SEARCH_MDS_ONLY); + final SuchenResponse resp = ernpClient.suchen(generic.getClientBehkz(), generic.clientName, + generic.getClientRequestTime(), generic.getClientRequestId(), personSuchen); + + // parse ZMR response + return processErnpResponse(resp, citizenCountryCode, false, PROCESS_SEARCH_MDS_ONLY); + + } catch (RestClientException e) { + log.warn(LOGMSG_ERNP_ERROR, PROCESS_SEARCH_MDS_ONLY, e.getMessage()); + throw new EidasSAuthenticationException(ERROR_MATCHING_11, new Object[] { e.getMessage() }, e); + + } catch (final EidasSAuthenticationException e) { + throw e; + + } catch (final Exception e) { + log.warn(LOGMSG_ERNP_RESP_PROCESS, PROCESS_SEARCH_MDS_ONLY, e.getMessage()); + throw new EidasSAuthenticationException(ERROR_MATCHING_99, new Object[] { e.getMessage() }, e); + } } @Override public ErnpRegisterResult searchCountrySpecific(PersonSuchenRequest personSearchDao, String citizenCountryCode) throws EidasSAuthenticationException { - return new ErnpRegisterResult(Collections.emptyList()); + try { + // build generic request metadata + final GenericRequestParams generic = buildGenericRequestParameters("stepCC"); + + // build search request + final PersonSuchen personSuchen = new PersonSuchen(); + personSuchen.setSuchoptionen(generateSearchParameters()); + personSuchen.setBegruendung(PROCESS_SEARCH_COUNTRY_SPECIFIC); + personSuchen.setSuchdaten(mapCountrySpecificSearchData(personSearchDao)); + + // request ERnP + log.trace("Requesting ERnP for '{}' operation", PROCESS_SEARCH_COUNTRY_SPECIFIC); + final SuchenResponse resp = ernpClient.suchen(generic.getClientBehkz(), generic.clientName, + generic.getClientRequestTime(), generic.getClientRequestId(), personSuchen); + + // parse ZMR response + return processErnpResponse(resp, citizenCountryCode, false, PROCESS_SEARCH_COUNTRY_SPECIFIC); + + } catch (RestClientException e) { + log.warn(LOGMSG_ERNP_ERROR, PROCESS_SEARCH_COUNTRY_SPECIFIC, e.getMessage()); + throw new EidasSAuthenticationException(ERROR_MATCHING_11, new Object[] { e.getMessage() }, e); + + } catch (final EidasSAuthenticationException e) { + throw e; + + } catch (final Exception e) { + log.warn(LOGMSG_ERNP_RESP_PROCESS, PROCESS_SEARCH_COUNTRY_SPECIFIC, e.getMessage()); + throw new EidasSAuthenticationException(ERROR_MATCHING_99, new Object[] { e.getMessage() }, e); + + } } @Override public ErnpRegisterResult update(RegisterResult registerResult, SimpleEidasData eidData) throws EidasSAuthenticationException { - return new ErnpRegisterResult(Collections.emptyList()); + try { + //search person with register result, because update needs information from search response + Person ernpPersonToKitt = searchPersonForUpdate(registerResult); + + // select elements that have to be updated + Collection eidasDocumentToAdd = + selectEidasDocumentsToAdd(ernpPersonToKitt, eidData); + + if (eidasDocumentToAdd.isEmpty()) { + log.info("Find no eIDAS document for update during: {}. Looks strange but nothing todo", + PROCESS_KITT_GENERAL); + return new ErnpRegisterResult(Arrays.asList(registerResult)); + + } else { + log.info("Find #{} eIDAS documents for update during: {}", eidasDocumentToAdd.size(), PROCESS_KITT_GENERAL); + + // update entry based on selected update info's and results from search response + return updatePersonInErnp(ernpPersonToKitt, eidasDocumentToAdd, eidData.getCitizenCountryCode()); + + } + + } catch (RestClientException e) { + log.warn(LOGMSG_ERNP_ERROR, PROCESS_SEARCH_COUNTRY_SPECIFIC, e.getMessage()); + throw new EidasSAuthenticationException(ERROR_MATCHING_11, new Object[] { e.getMessage() }, e); + + } catch (final EidasSAuthenticationException e) { + throw e; + + } catch (final Exception e) { + log.warn(LOGMSG_ERNP_RESP_PROCESS, PROCESS_SEARCH_COUNTRY_SPECIFIC, e.getMessage()); + throw new EidasSAuthenticationException(ERROR_MATCHING_99, new Object[] { e.getMessage() }, e); + + } + } + + private ErnpRegisterResult updatePersonInErnp(Person ernpPersonToKitt, + Collection eidasDocumentToAdd, String citizenCountryCode) + throws ServiceFault { + // build generic request metadata + final GenericRequestParams generic = buildGenericRequestParameters("stepKittUpdate"); + + // build update request + PersonAendern ernpReq = new PersonAendern(); + ernpReq.setBegruendung(PROCESS_KITT_IDENITIES_UPDATE); + + // set reference elements for person update + ernpReq.setEntityId(ernpPersonToKitt.getEntityId()); + ernpReq.setVersion(ernpPersonToKitt.getVersion()); + + // add new eIDAS attributes + eidasDocumentToAdd.stream().forEach(el -> ernpReq.getAnlegen().addEidasItem(el)); + + // TODO: should we update MDS also in that step? + + + // request ZMR + log.trace("Requesting ERnP for '{}' operation", PROCESS_KITT_IDENITIES_UPDATE); + AendernResponse ernpResp = ernpClient.aendern(generic.getClientBehkz(), generic.clientName, + generic.getClientRequestTime(), generic.getClientRequestId(), ernpReq); + log.trace("Receive response from ERnP for '{}' operation", PROCESS_KITT_IDENITIES_UPDATE); + + return new ErnpRegisterResult(Arrays.asList( + mapErnpResponseToRegisterResult(ernpResp.getPerson(), citizenCountryCode))); + + } + + private Collection selectEidasDocumentsToAdd( + Person ernpPersonToKitt, SimpleEidasData eidData) { + + //TODO: maybe we should re-factor SimpleEidasData to a generic data-model to facilitate arbitrary eIDAS attributes + Set result = new HashSet<>(); + addEidasDocumentIfNotAvailable(result, ernpPersonToKitt, eidData.getCitizenCountryCode(), + Constants.eIDAS_ATTRURN_PERSONALIDENTIFIER, eidData.getPseudonym(), true); + addEidasDocumentIfNotAvailable(result, ernpPersonToKitt, eidData.getCitizenCountryCode(), + Constants.eIDAS_ATTRURN_PLACEOFBIRTH, eidData.getPlaceOfBirth(), false); + addEidasDocumentIfNotAvailable(result, ernpPersonToKitt, eidData.getCitizenCountryCode(), + Constants.eIDAS_ATTRURN_BIRTHNAME, eidData.getBirthName(), false); + + return result; + + } + + private void addEidasDocumentIfNotAvailable(Set result, + Person ernpPersonToKitt, String citizenCountryCode, + String attrName, String attrValue, boolean allowMoreThanOneEntry) { + + if (StringUtils.isEmpty(attrValue)) { + log.trace("No eIDAS document: {}. Nothing todo for KITT process ... ", attrName); + return; + + } + + // check if eIDAS attribute is already includes an eIDAS-Document + boolean alreadyExist = ernpPersonToKitt.getEidas().stream() + .filter(el -> el.getWert().equals(attrValue) + && el.getArt().equals(attrName) + && el.getStaatscode2().equals(citizenCountryCode)) + .findAny() + .isPresent(); + + if (!alreadyExist) { + // check eIDAS documents already contains a document with this pair of country-code and attribute-name + Optional oneDocWithNameExists = ernpPersonToKitt.getEidas().stream() + .filter(el -> el.getStaatscode2().equals(citizenCountryCode) + && el.getArt().equals(attrName)) + .findAny(); + + if (!allowMoreThanOneEntry && oneDocWithNameExists.isPresent() + && !oneDocWithNameExists.get().getWert().equals(attrValue)) { + log.warn("eIDAS document: {} already exists for country: {} but attribute-value does not match. " + + "Skip update process because no multi-value allowed for this ... ", + attrName, citizenCountryCode); + + } else { + + Eidas eidasDocToAdd = new Eidas(); + eidasDocToAdd.setStaatscode2(citizenCountryCode); + eidasDocToAdd.setArt(attrName); + eidasDocToAdd.setWert(attrValue); + log.info("Add eIDAS document: {} for country: {} to ERnP person", attrName, citizenCountryCode); + result.add(eidasDocToAdd); + + } + + } else { + log.debug("eIDAS document: {} already exists for country: {}. Skip update process for this ... ", + attrName, citizenCountryCode); + + } + } + + private Person searchPersonForUpdate(RegisterResult registerResult) throws WorkflowException { + // build generic request metadata + final GenericRequestParams generic = buildGenericRequestParameters("stepKittSearch"); + + // build search request + final Suchdaten searchInfos = new Suchdaten(); + searchInfos.setFamilienname(registerResult.getFamilyName()); + searchInfos.setVorname(registerResult.getGivenName()); + searchInfos.setGeburtsdatum(buildErnpBirthday(registerResult.getDateOfBirth())); + + final PersonSuchen personSuchen = new PersonSuchen(); + personSuchen.setSuchoptionen(generateSearchParameters()); + personSuchen.setBegruendung(PROCESS_KITT_IDENITIES_GET); + personSuchen.setSuchdaten(searchInfos); + + // request ERnP + log.trace("Requesting ERnP for '{}' operation", PROCESS_KITT_IDENITIES_GET); + final SuchenResponse resp = ernpClient.suchen(generic.getClientBehkz(), generic.clientName, + generic.getClientRequestTime(), generic.getClientRequestId(), personSuchen); + + // perform shot validation of ERnP response + if (resp.getPerson() == null || resp.getPerson().size() != 1) { + log.error("ERnP result contains NO 'Person' or 'Person' is empty"); + throw new WorkflowException(PROCESS_KITT_IDENITIES_GET, + "Find NO data-set with already matchted eID during ERnP KITT process"); + + } else { + log.debug("Find person for '{}' operation", PROCESS_KITT_IDENITIES_GET); + return resp.getPerson().get(0); + + } } @Override @@ -270,7 +503,7 @@ public class ErnpRestClient implements IErnpClient { Constants.eIDAS_ATTRURN_PERSONALIDENTIFIER)) .familyName(person.getPersonendaten().getFamilienname()) .givenName(person.getPersonendaten().getVorname()) - .dateOfBirth(buildTextualBirthday(person.getPersonendaten().getGeburtsdatum())) + .dateOfBirth(getTextualBirthday(person.getPersonendaten().getGeburtsdatum())) .bpk(person.getPersonendaten().getBpkZp()) .placeOfBirth(selectSingleEidasDocument(person, citizenCountryCode, Constants.eIDAS_ATTRURN_PLACEOFBIRTH)) @@ -280,18 +513,31 @@ public class ErnpRestClient implements IErnpClient { } + private Suchdaten mapCountrySpecificSearchData(PersonSuchenRequest personSearchDao) { + final Suchdaten searchInfos = new Suchdaten(); + searchInfos.setFamilienname(personSearchDao.getNatuerlichePerson().getPersonenName().getFamilienname()); + searchInfos.setVorname(personSearchDao.getNatuerlichePerson().getPersonenName().getVorname()); + searchInfos.setGeburtsdatum(buildErnpBirthday(personSearchDao.getNatuerlichePerson().getGeburtsdatum())); + + //TODO: search eIDAS has to be a LIST!!!!!! + SuchEidas eidasInfos = new SuchEidas(); + searchInfos.setEidas(eidasInfos ); + return searchInfos; + + } + /** * Build AT specific Date String 'yyyy-MM-dd' from ERnP birthday representation. * *

- * Info: {@link LocalDate} can not be used, because '1940-00-00' is also + * Info: {@link LocalDate} can not be used, because '1940-00-00' is also * a valid birthday on ERnP site. *

* * @param geburtsdatum ERnP birthday representation * @return birthday in 'yyyy-MM-dd' format */ - private String buildTextualBirthday(PartialDate geburtsdatum) { + private String getTextualBirthday(PartialDate geburtsdatum) { return MessageFormat.format("{0}-{1}-{2}", String.valueOf(geburtsdatum.getJahr()), String.format("%02d", geburtsdatum.getMonat()), @@ -299,6 +545,29 @@ public class ErnpRestClient implements IErnpClient { } + /** + * Map an AT specific Date String 'yyyy-MM-dd' to ERnP birthday representation. + * + *

+ * Info: {@link LocalDate} can not be used, because '1940-00-00' is also + * a valid birthday. + *

+ * + * @param dateOfBirth in 'yyyy-MM-dd' format + * @return ERnP birthday representation + */ + private PartialDate buildErnpBirthday(String dateOfBirth) { + String[] elements = dateOfBirth.split("-"); + Assert.isTrue(elements.length == 3, "Find invalid dateOfBirth element: " + dateOfBirth); + + PartialDate result = new PartialDate(); + result.setJahr(Integer.valueOf(elements[0])); + result.setMonat(Integer.valueOf(elements[1])); + result.setTag(Integer.valueOf(elements[2])); + return result; + + } + /** * Get all eIDAS document with the specified country code and document type. * @@ -364,7 +633,7 @@ public class ErnpRestClient implements IErnpClient { private HttpMessageConverter buildCustomJacksonObjectMapper() { final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); - converter.setSupportedMediaTypes(Collections.singletonList(MediaType.ALL)); + converter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON)); converter.getObjectMapper() .setSerializationInclusion(Include.NON_NULL); return converter; @@ -384,17 +653,14 @@ public class ErnpRestClient implements IErnpClient { @Override public void handleError(ClientHttpResponse response) throws IOException { - // TODO: implement errorHandling based on response infos + // TODO: opimize errorHandling based on response info's from real ERnP + + List serverId = response.getHeaders().getOrEmpty(ERNP_RESPONSE_HEADER_SERVER_ID); + log.warn("Receive http-error: {} from ERnP with serverTransactionId", + response.getRawStatusCode(), serverId.isEmpty() ? "'not set'" : serverId.get(0)); - if (response.getStatusCode().series() == HttpStatus.Series.SERVER_ERROR) { - log.warn("Receive http-server-error: {} from ERnP", response.getRawStatusCode()); - - } else if (response.getStatusCode().series() == HttpStatus.Series.CLIENT_ERROR) { - log.warn("Receive http-client-error: {} from ERnP", response.getRawStatusCode()); - - } - throw new ErnpRestCommunicationException(response.getRawStatusCode()); + } }; } diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/ErnpRestCommunicationException.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/ErnpRestCommunicationException.java index 72a5ece6..e3224c93 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/ErnpRestCommunicationException.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/ErnpRestCommunicationException.java @@ -19,6 +19,6 @@ public class ErnpRestCommunicationException extends IOException { public ErnpRestCommunicationException(int rawStatusCode) { super("ERnP service answers with an error and HTTP status-code: " + rawStatusCode); this.httpStatusCode = rawStatusCode; - } - + + } } 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 fd9a67a9..488b571b 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 @@ -21,6 +21,7 @@ import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasSAuthenti import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.WorkflowException; import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.ZmrCommunicationException; import at.asitplus.eidas.specific.modules.auth.eidas.v2.handler.CountrySpecificDetailSearchProcessor; +import at.gv.bmi.namespace.zmr_su.zmr._20040201.PersonSuchenRequest; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.RequiredArgsConstructor; @@ -133,17 +134,22 @@ public class RegisterSearchService { try { @Nullable final CountrySpecificDetailSearchProcessor ccSpecificProcessor = findSpecificProcessor(eidasData); if (ccSpecificProcessor != null) { - log.debug("Selecting country-specific search processor: {}", ccSpecificProcessor.getName()); + log.debug("Selecting country-specific search processor: {}", ccSpecificProcessor.getName()); + PersonSuchenRequest ccSpecificSearchReq = ccSpecificProcessor.generateSearchRequest(eidasData); + + // search in ZMR final ZmrRegisterResult resultsZmr = zmrClient.searchCountrySpecific(operationStatus.getZmrProcessId(), - ccSpecificProcessor.generateSearchRequest(eidasData), - eidasData.getCitizenCountryCode()); - return RegisterStatusResults.fromZmr(resultsZmr); + ccSpecificSearchReq, eidasData.getCitizenCountryCode()); + + //search in ERnP + ErnpRegisterResult resultErnp = ernpClient.searchCountrySpecific( + ccSpecificSearchReq, eidasData.getCitizenCountryCode()); + + return RegisterStatusResults.fromZmrAndErnp(resultsZmr, resultErnp); } else { - // TODO: add search procesfor for ERnP searching - return RegisterStatusResults.fromErnp(operationStatus, - new ErnpRegisterResult(Collections.emptyList())); + return RegisterStatusResults.fromEmpty(operationStatus); } @@ -383,6 +389,10 @@ public class RegisterSearchService { static RegisterStatusResults fromErnp(RegisterOperationStatus status, ErnpRegisterResult updateErnp) { return new RegisterStatusResults(status, Collections.emptyList(), updateErnp.getPersonResult()); } + + static RegisterStatusResults fromEmpty(RegisterOperationStatus status) { + return new RegisterStatusResults(status, Collections.emptyList(), Collections.emptyList()); + } } 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 index f295d66b..c720cb7f 100644 --- 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 @@ -185,7 +185,10 @@ public class InitialSearchTask extends AbstractAuthServletTask { log.trace("Starting step3CheckRegisterUpdateNecessary"); if (!eidasData.equalsRegisterData(searchResult)) { log.info("Skipping update-register-information step, because it's not supported yet"); - //TODO: return updated search result if updates are allowed + + //TODO: update of ERnP information are allowed. Add ERnP update-step. Maybe we can use regular KITT steps + + return searchResult; } else { log.debug("Register information match to eIDAS information. No update required"); -- cgit v1.2.3 From 8c08120d543f4eba2b1d1480d6649f13c46e9ef0 Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Mon, 7 Feb 2022 10:37:42 +0100 Subject: feature(ernp): add person into ERnP of mathing ends with no result --- .../auth/eidas/v2/clients/ernp/ErnpRestClient.java | 301 ++++++++++++--------- .../auth/eidas/v2/clients/ernp/IErnpClient.java | 12 + .../auth/eidas/v2/ernp/DummyErnpClient.java | 5 + .../eidas/v2/tasks/CreateNewErnpEntryTask.java | 58 ++-- 4 files changed, 232 insertions(+), 144 deletions(-) (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java') diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java index 2eaece1d..58b3ca45 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java @@ -41,11 +41,14 @@ import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.api.DefaultApi; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.invoker.ApiClient; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.AendernResponse; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.AnlegenResponse; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.Eidas; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.PartialDate; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.Person; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.PersonAendern; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.PersonAnlegen; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.PersonSuchen; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.Personendaten; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.SuchEidas; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.Suchdaten; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.SuchenResponse; @@ -100,7 +103,8 @@ public class ErnpRestClient implements IErnpClient { private static final String PROCESS_KITT_GENERAL = "KITT general-processing"; private static final String PROCESS_KITT_IDENITIES_GET = "KITT get-latest-version"; private static final String PROCESS_KITT_IDENITIES_UPDATE = "KITT update dataset"; - + private static final String PROCESS_ADD_IDENITY = "Add new person"; + private static final String FRIENDLYNAME_HTTP_CLIENT = "ERnP Client"; // HTTP header-names from ERnP response @@ -272,141 +276,41 @@ public class ErnpRestClient implements IErnpClient { } } - private ErnpRegisterResult updatePersonInErnp(Person ernpPersonToKitt, - Collection eidasDocumentToAdd, String citizenCountryCode) - throws ServiceFault { + @Override + public ErnpRegisterResult add(SimpleEidasData eidData) throws EidasSAuthenticationException { // build generic request metadata - final GenericRequestParams generic = buildGenericRequestParameters("stepKittUpdate"); + final GenericRequestParams generic = buildGenericRequestParameters("stepNew"); // build update request - PersonAendern ernpReq = new PersonAendern(); - ernpReq.setBegruendung(PROCESS_KITT_IDENITIES_UPDATE); - - // set reference elements for person update - ernpReq.setEntityId(ernpPersonToKitt.getEntityId()); - ernpReq.setVersion(ernpPersonToKitt.getVersion()); - - // add new eIDAS attributes - eidasDocumentToAdd.stream().forEach(el -> ernpReq.getAnlegen().addEidasItem(el)); - - // TODO: should we update MDS also in that step? - + PersonAnlegen ernpReq = new PersonAnlegen(); + ernpReq.setBegruendung(PROCESS_ADD_IDENITY); + + // inject person data + Personendaten person = new Personendaten(); + person.setFamilienname(eidData.getFamilyName()); + person.setVorname(eidData.getGivenName()); + person.setGeburtsdatum(buildErnpBirthday(eidData.getDateOfBirth())); + ernpReq.setPersonendaten(person); - // request ZMR - log.trace("Requesting ERnP for '{}' operation", PROCESS_KITT_IDENITIES_UPDATE); - AendernResponse ernpResp = ernpClient.aendern(generic.getClientBehkz(), generic.clientName, + buildNewEidasDocumens(ernpReq, eidData); + + // request ERnP + log.trace("Requesting ERnP for '{}' operation", PROCESS_ADD_IDENITY); + AnlegenResponse ernpResp = ernpClient.anlegen(generic.getClientBehkz(), generic.clientName, generic.getClientRequestTime(), generic.getClientRequestId(), ernpReq); - log.trace("Receive response from ERnP for '{}' operation", PROCESS_KITT_IDENITIES_UPDATE); + log.trace("Receive response from ERnP for '{}' operation", PROCESS_ADD_IDENITY); return new ErnpRegisterResult(Arrays.asList( - mapErnpResponseToRegisterResult(ernpResp.getPerson(), citizenCountryCode))); - - } - - private Collection selectEidasDocumentsToAdd( - Person ernpPersonToKitt, SimpleEidasData eidData) { - - //TODO: maybe we should re-factor SimpleEidasData to a generic data-model to facilitate arbitrary eIDAS attributes - Set result = new HashSet<>(); - addEidasDocumentIfNotAvailable(result, ernpPersonToKitt, eidData.getCitizenCountryCode(), - Constants.eIDAS_ATTRURN_PERSONALIDENTIFIER, eidData.getPseudonym(), true); - addEidasDocumentIfNotAvailable(result, ernpPersonToKitt, eidData.getCitizenCountryCode(), - Constants.eIDAS_ATTRURN_PLACEOFBIRTH, eidData.getPlaceOfBirth(), false); - addEidasDocumentIfNotAvailable(result, ernpPersonToKitt, eidData.getCitizenCountryCode(), - Constants.eIDAS_ATTRURN_BIRTHNAME, eidData.getBirthName(), false); - - return result; + mapErnpResponseToRegisterResult(ernpResp.getPerson(), eidData.getCitizenCountryCode()))); } - private void addEidasDocumentIfNotAvailable(Set result, - Person ernpPersonToKitt, String citizenCountryCode, - String attrName, String attrValue, boolean allowMoreThanOneEntry) { - - if (StringUtils.isEmpty(attrValue)) { - log.trace("No eIDAS document: {}. Nothing todo for KITT process ... ", attrName); - return; - - } - - // check if eIDAS attribute is already includes an eIDAS-Document - boolean alreadyExist = ernpPersonToKitt.getEidas().stream() - .filter(el -> el.getWert().equals(attrValue) - && el.getArt().equals(attrName) - && el.getStaatscode2().equals(citizenCountryCode)) - .findAny() - .isPresent(); - - if (!alreadyExist) { - // check eIDAS documents already contains a document with this pair of country-code and attribute-name - Optional oneDocWithNameExists = ernpPersonToKitt.getEidas().stream() - .filter(el -> el.getStaatscode2().equals(citizenCountryCode) - && el.getArt().equals(attrName)) - .findAny(); - - if (!allowMoreThanOneEntry && oneDocWithNameExists.isPresent() - && !oneDocWithNameExists.get().getWert().equals(attrValue)) { - log.warn("eIDAS document: {} already exists for country: {} but attribute-value does not match. " - + "Skip update process because no multi-value allowed for this ... ", - attrName, citizenCountryCode); - - } else { - - Eidas eidasDocToAdd = new Eidas(); - eidasDocToAdd.setStaatscode2(citizenCountryCode); - eidasDocToAdd.setArt(attrName); - eidasDocToAdd.setWert(attrValue); - log.info("Add eIDAS document: {} for country: {} to ERnP person", attrName, citizenCountryCode); - result.add(eidasDocToAdd); - - } - - } else { - log.debug("eIDAS document: {} already exists for country: {}. Skip update process for this ... ", - attrName, citizenCountryCode); - - } - } - - private Person searchPersonForUpdate(RegisterResult registerResult) throws WorkflowException { - // build generic request metadata - final GenericRequestParams generic = buildGenericRequestParameters("stepKittSearch"); - - // build search request - final Suchdaten searchInfos = new Suchdaten(); - searchInfos.setFamilienname(registerResult.getFamilyName()); - searchInfos.setVorname(registerResult.getGivenName()); - searchInfos.setGeburtsdatum(buildErnpBirthday(registerResult.getDateOfBirth())); - - final PersonSuchen personSuchen = new PersonSuchen(); - personSuchen.setSuchoptionen(generateSearchParameters()); - personSuchen.setBegruendung(PROCESS_KITT_IDENITIES_GET); - personSuchen.setSuchdaten(searchInfos); - - // request ERnP - log.trace("Requesting ERnP for '{}' operation", PROCESS_KITT_IDENITIES_GET); - final SuchenResponse resp = ernpClient.suchen(generic.getClientBehkz(), generic.clientName, - generic.getClientRequestTime(), generic.getClientRequestId(), personSuchen); - - // perform shot validation of ERnP response - if (resp.getPerson() == null || resp.getPerson().size() != 1) { - log.error("ERnP result contains NO 'Person' or 'Person' is empty"); - throw new WorkflowException(PROCESS_KITT_IDENITIES_GET, - "Find NO data-set with already matchted eID during ERnP KITT process"); - - } else { - log.debug("Find person for '{}' operation", PROCESS_KITT_IDENITIES_GET); - return resp.getPerson().get(0); - - } - } - @Override public ErnpRegisterResult searchWithResidenceData(String givenName, String familyName, String dateOfBirth, String zipcode, String city, String street) { return new ErnpRegisterResult(Collections.emptyList()); } - + @PostConstruct private void initialize() throws EaafException { // validate additional Ernp communication parameters @@ -545,6 +449,161 @@ public class ErnpRestClient implements IErnpClient { } + private ErnpRegisterResult updatePersonInErnp(Person ernpPersonToKitt, + Collection eidasDocumentToAdd, String citizenCountryCode) + throws ServiceFault { + // build generic request metadata + final GenericRequestParams generic = buildGenericRequestParameters("stepKittUpdate"); + + // build update request + PersonAendern ernpReq = new PersonAendern(); + ernpReq.setBegruendung(PROCESS_KITT_IDENITIES_UPDATE); + + // set reference elements for person update + ernpReq.setEntityId(ernpPersonToKitt.getEntityId()); + ernpReq.setVersion(ernpPersonToKitt.getVersion()); + + // add new eIDAS attributes + eidasDocumentToAdd.stream().forEach(el -> ernpReq.getAnlegen().addEidasItem(el)); + + // TODO: should we update MDS also in that step? + + + // request ERnP + log.trace("Requesting ERnP for '{}' operation", PROCESS_KITT_IDENITIES_UPDATE); + AendernResponse ernpResp = ernpClient.aendern(generic.getClientBehkz(), generic.clientName, + generic.getClientRequestTime(), generic.getClientRequestId(), ernpReq); + log.trace("Receive response from ERnP for '{}' operation", PROCESS_KITT_IDENITIES_UPDATE); + + return new ErnpRegisterResult(Arrays.asList( + mapErnpResponseToRegisterResult(ernpResp.getPerson(), citizenCountryCode))); + + } + + private Collection selectEidasDocumentsToAdd( + Person ernpPersonToKitt, SimpleEidasData eidData) { + + //TODO: maybe we should re-factor SimpleEidasData to a generic data-model to facilitate arbitrary eIDAS attributes + Set result = new HashSet<>(); + addEidasDocumentIfNotAvailable(result, ernpPersonToKitt, eidData.getCitizenCountryCode(), + Constants.eIDAS_ATTRURN_PERSONALIDENTIFIER, eidData.getPseudonym(), true); + addEidasDocumentIfNotAvailable(result, ernpPersonToKitt, eidData.getCitizenCountryCode(), + Constants.eIDAS_ATTRURN_PLACEOFBIRTH, eidData.getPlaceOfBirth(), false); + addEidasDocumentIfNotAvailable(result, ernpPersonToKitt, eidData.getCitizenCountryCode(), + Constants.eIDAS_ATTRURN_BIRTHNAME, eidData.getBirthName(), false); + + return result; + + } + + private void addEidasDocumentIfNotAvailable(Set result, + Person ernpPersonToKitt, String citizenCountryCode, + String attrName, String attrValue, boolean allowMoreThanOneEntry) { + + if (StringUtils.isEmpty(attrValue)) { + log.trace("No eIDAS document: {}. Nothing todo for KITT process ... ", attrName); + return; + + } + + // check if eIDAS attribute is already includes an eIDAS-Document + boolean alreadyExist = ernpPersonToKitt.getEidas().stream() + .filter(el -> el.getWert().equals(attrValue) + && el.getArt().equals(attrName) + && el.getStaatscode2().equals(citizenCountryCode)) + .findAny() + .isPresent(); + + if (!alreadyExist) { + // check eIDAS documents already contains a document with this pair of country-code and attribute-name + Optional oneDocWithNameExists = ernpPersonToKitt.getEidas().stream() + .filter(el -> el.getStaatscode2().equals(citizenCountryCode) + && el.getArt().equals(attrName)) + .findAny(); + + if (!allowMoreThanOneEntry && oneDocWithNameExists.isPresent() + && !oneDocWithNameExists.get().getWert().equals(attrValue)) { + log.warn("eIDAS document: {} already exists for country: {} but attribute-value does not match. " + + "Skip update process because no multi-value allowed for this ... ", + attrName, citizenCountryCode); + + } else { + + Eidas eidasDocToAdd = new Eidas(); + eidasDocToAdd.setStaatscode2(citizenCountryCode); + eidasDocToAdd.setArt(attrName); + eidasDocToAdd.setWert(attrValue); + log.info("Add eIDAS document: {} for country: {} to ERnP person", attrName, citizenCountryCode); + result.add(eidasDocToAdd); + + } + + } else { + log.debug("eIDAS document: {} already exists for country: {}. Skip update process for this ... ", + attrName, citizenCountryCode); + + } + } + + private Person searchPersonForUpdate(RegisterResult registerResult) throws WorkflowException { + // build generic request metadata + final GenericRequestParams generic = buildGenericRequestParameters("stepKittSearch"); + + // build search request + final Suchdaten searchInfos = new Suchdaten(); + searchInfos.setFamilienname(registerResult.getFamilyName()); + searchInfos.setVorname(registerResult.getGivenName()); + searchInfos.setGeburtsdatum(buildErnpBirthday(registerResult.getDateOfBirth())); + + final PersonSuchen personSuchen = new PersonSuchen(); + personSuchen.setSuchoptionen(generateSearchParameters()); + personSuchen.setBegruendung(PROCESS_KITT_IDENITIES_GET); + personSuchen.setSuchdaten(searchInfos); + + // request ERnP + log.trace("Requesting ERnP for '{}' operation", PROCESS_KITT_IDENITIES_GET); + final SuchenResponse resp = ernpClient.suchen(generic.getClientBehkz(), generic.clientName, + generic.getClientRequestTime(), generic.getClientRequestId(), personSuchen); + + // perform shot validation of ERnP response + if (resp.getPerson() == null || resp.getPerson().size() != 1) { + log.error("ERnP result contains NO 'Person' or 'Person' is empty"); + throw new WorkflowException(PROCESS_KITT_IDENITIES_GET, + "Find NO data-set with already matchted eID during ERnP KITT process"); + + } else { + log.debug("Find person for '{}' operation", PROCESS_KITT_IDENITIES_GET); + return resp.getPerson().get(0); + + } + } + + private void buildNewEidasDocumens(PersonAnlegen ernpReq, SimpleEidasData eidData) { + ernpReq.addEidasItem(buildNewEidasDocument(eidData.getCitizenCountryCode(), + Constants.eIDAS_ATTRURN_PERSONALIDENTIFIER, eidData.getPseudonym())); + + if (StringUtils.isNotEmpty(eidData.getPlaceOfBirth())) { + ernpReq.addEidasItem(buildNewEidasDocument(eidData.getCitizenCountryCode(), + Constants.eIDAS_ATTRURN_PLACEOFBIRTH, eidData.getPlaceOfBirth())); + + } + + if (StringUtils.isNotEmpty(eidData.getBirthName())) { + ernpReq.addEidasItem(buildNewEidasDocument(eidData.getCitizenCountryCode(), + Constants.eIDAS_ATTRURN_BIRTHNAME, eidData.getBirthName())); + + } + } + + private Eidas buildNewEidasDocument(String citizenCountryCode, String eidasAttrName, + String eidasAddrValue) { + Eidas el = new Eidas(); + el.setArt(eidasAttrName); + el.setWert(eidasAddrValue); + el.setStaatscode2(citizenCountryCode); + return el; + } + /** * Map an AT specific Date String 'yyyy-MM-dd' to ERnP birthday representation. * diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/IErnpClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/IErnpClient.java index 4c8bcd3e..7a957531 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/IErnpClient.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/IErnpClient.java @@ -84,6 +84,18 @@ public interface IErnpClient { ErnpRegisterResult update(RegisterResult registerResult, SimpleEidasData eidData) throws EidasSAuthenticationException; + + /** + * Add new entry into ERnP by using identity from this eIDAS authentication. + * + * @param eidData eIDAS eID information from current authentication process + * @return Update result but never null + * @throws EidasSAuthenticationException In case of a communication error + */ + @Nonnull + ErnpRegisterResult add(SimpleEidasData eidData) throws EidasSAuthenticationException; + + /** * Search person based on address information. * 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 index 52703232..dabb73dc 100644 --- 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 @@ -73,4 +73,9 @@ public class DummyErnpClient implements IErnpClient { } + @Override + public ErnpRegisterResult add(SimpleEidasData eidData) throws EidasSAuthenticationException { + return buildEmptyResult(); + } + } diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/CreateNewErnpEntryTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/CreateNewErnpEntryTask.java index 6fc6d499..b63b0ca0 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/CreateNewErnpEntryTask.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/CreateNewErnpEntryTask.java @@ -26,9 +26,16 @@ package at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.ernp.ErnpRestClient; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.ernp.ErnpRestClient.ErnpRegisterResult; +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.WorkflowException; +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.TaskExecutionException; import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; @@ -46,6 +53,7 @@ import lombok.extern.slf4j.Slf4j; *
  • TODO MDS, BPK of new entry
  • * * + * @author tlenz * @author amarsalek * @author ckollmann */ @@ -53,36 +61,40 @@ import lombok.extern.slf4j.Slf4j; @Component("CreateNewErnbEntryTask") public class CreateNewErnpEntryTask extends AbstractAuthServletTask { - //private final SzrClient szrClient; + private final ErnpRestClient ernpClient; - ///** - // * Constructor. - // * @param szrClient SZR client for creating a new ERnP entry - // */ - //public CreateNewErnpEntryTask(SzrClient szrClient) { - // this.szrClient = szrClient; - //} + /** + * Constructor. + * @param szrClient SZR client for creating a new ERnP entry + */ + public CreateNewErnpEntryTask(@Autowired ErnpRestClient client) { + this.ernpClient = client; + } @Override public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) throws TaskExecutionException { try { - //SimpleEidasData simpleEidasData = MatchingTaskUtils.getInitialEidasData(pendingReq); - - // insert person into ERnP - //TODO: should we insert it directly into ERnP? - //TODO: has to updated to new eIDAS document model in ERnP - //String vsz = szrClient.createNewErnpEntry(simpleEidasData); - - // finish matching process, because new user-entry uniquly matches - //log.info("User successfully registerred into ERnP and matching tasks are finished "); - //MatchingTaskUtils.storeFinalMatchingResult(pendingReq, - // MatchedPersonResult.builder() - // .vsz(vsz) - // .build()); - - log.warn("Skipping new insert ERnP task, because it's currently unknown who we should it"); + SimpleEidasData simpleEidasData = MatchingTaskUtils.getInitialEidasData(pendingReq); + if (simpleEidasData == null) { + throw new WorkflowException("step09", "No initial eIDAS authn data", true); + + } + //add person into ERnP + ErnpRegisterResult resp = ernpClient.add(simpleEidasData); + if (resp.getPersonResult().size() != 1) { + log.error("Receive {} from ERnP during 'add person' step", + resp.getPersonResult().isEmpty() ? "no result" : "more-than-one result"); + throw new WorkflowException("step09", "Add person into ERnP failed", true); + + } + + // finish matching process, because new user-entry uniquly matches + log.info("User successfully registerred into ERnP and matching tasks are finished "); + MatchingTaskUtils.storeFinalMatchingResult(pendingReq, + MatchedPersonResult.generateFormMatchingResult( + resp.getPersonResult().get(0), simpleEidasData.getCitizenCountryCode())); } catch (final Exception e) { log.error("Initial search FAILED.", e); -- cgit v1.2.3 From 1a442f77692a0438cc9d43be563b0ca965ff6c2b Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Mon, 7 Feb 2022 11:17:42 +0100 Subject: refactor(szr): remove 'insertErnp' functionality from SZR client. After this, the person is directly added into ERnP by using ErnpRestClient --- .../auth/eidas/v2/clients/szr/SzrClient.java | 49 ---------------------- .../eidas/v2/tasks/CreateIdentityLinkTask.java | 29 ++----------- 2 files changed, 4 insertions(+), 74 deletions(-) (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java') diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/szr/SzrClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/szr/SzrClient.java index 397cbe46..bd1eb13e 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/szr/SzrClient.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/szr/SzrClient.java @@ -111,28 +111,6 @@ public class SzrClient extends AbstractSoapClient { final ObjectMapper mapper = new ObjectMapper(); - /** - * Get IdentityLink of a person. - * - * - * @param eidData minimum dataset of person - * @return IdentityLink - * @throws SzrCommunicationException In case of a SZR error - */ - public IdentityLinkType getIdentityLinkInRawMode(SimpleEidasData eidData) - throws SzrCommunicationException { - try { - final GetIdentityLinkEidas getIdl = new GetIdentityLinkEidas(); - getIdl.setPersonInfo(generateSzrRequest(eidData)); - - return getIdentityLinkGeneric(getIdl); - - } catch (final Exception e) { - log.warn("SZR communication FAILED. Reason: " + e.getMessage(), e); - throw new SzrCommunicationException("ernb.02", new Object[]{e.getMessage()}, e); - - } - } /** * Get IdentityLink of a person. @@ -206,33 +184,6 @@ public class SzrClient extends AbstractSoapClient { } return resp; } - - /** - * Request a encrypted baseId from SZR. - * - * Note: Previously, this method did create a new ERnP entry, if it did not exist. This is - * not the case any more. See {@link #createNewErnpEntry(SimpleEidasData)} for that functionality. - * - * @param eidData Minimum dataset of person - * @return encrypted baseId - * @throws SzrCommunicationException In case of a SZR error - */ - public String getEncryptedStammzahl(final SimpleEidasData eidData) - throws SzrCommunicationException { - final String resp; - try { - resp = this.szr.getStammzahlEncrypted(generateSzrRequest(eidData), false); - } catch (SZRException_Exception e) { - throw new SzrCommunicationException("ernb.02", new Object[]{e.getMessage()}, e); - } - - if (StringUtils.isEmpty(resp)) { - throw new SzrCommunicationException("ernb.01", new Object[]{"Stammzahl response empty"}); // TODO error handling - } - - return resp; - - } /** * Request a encrypted baseId from SZR. diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/CreateIdentityLinkTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/CreateIdentityLinkTask.java index c95c275e..740e5292 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/CreateIdentityLinkTask.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/CreateIdentityLinkTask.java @@ -86,9 +86,6 @@ import szrservices.IdentityLinkType; *
      *
    • {@link at.gv.egiz.eaaf.core.impl.idp.controller.tasks.FinalizeAuthenticationTask}
    • *
    - * TODO Take Constants#DATA_SIMPLE_EIDAS and Constants#DATA_RESULT_MATCHING_BPK - * TODO Only do VSZ Erstellung and eidasBind -- this is always the end of the whole process - * TODO Move Eintragung to separate Task, as it does not happen every time * @author tlenz */ @Slf4j @@ -192,16 +189,8 @@ public class CreateIdentityLinkTask extends AbstractAuthServletTask { private void executeEidMode(SimpleEidasData eidData, MatchedPersonResult matchedPersonData) throws JsonProcessingException, EaafException, JoseException { // get encrypted baseId - String vsz; - if (matchedPersonData != null) { - log.debug("Requesting encrypted baseId by already matched person information ... "); - vsz = szrClient.getEncryptedStammzahl(matchedPersonData); - - } else { - log.debug("Requesting encrypted baseId by using eIDAS information directly ... "); - vsz = szrClient.createNewErnpEntry(eidData); - - } + log.debug("Requesting encrypted baseId by already matched person information ... "); + String vsz = szrClient.getEncryptedStammzahl(matchedPersonData); //write revision-Log entry and extended infos personal-identifier mapping revisionsLogger.logEvent(pendingReq, MsConnectorEventCodes.SZR_VSZ_RECEIVED); @@ -252,18 +241,8 @@ public class CreateIdentityLinkTask extends AbstractAuthServletTask { private SzrResultHolder requestSzrForIdentityLink(SimpleEidasData eidData, MatchedPersonResult matchedPersonData) throws EaafException { //request IdentityLink from SZR - IdentityLinkType result; - - if (matchedPersonData != null) { - log.debug("Requesting encrypted baseId by already matched person information ... "); - result = szrClient.getIdentityLinkInRawMode(matchedPersonData); - - } else { - log.debug("Requesting encrypted baseId by using eIDAS information directly ... "); - result = szrClient.getIdentityLinkInRawMode(eidData); - - } - + log.debug("Requesting encrypted baseId by already matched person information ... "); + IdentityLinkType result = szrClient.getIdentityLinkInRawMode(matchedPersonData); final Element idlFromSzr = (Element) result.getAssertion(); final IIdentityLink identityLink = new SimpleIdentityLinkAssertionParser(idlFromSzr).parseIdentityLink(); -- cgit v1.2.3 From e9bb7aeaf5a9f7a445907ccb2abc96635e5b534c Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Mon, 7 Feb 2022 11:37:22 +0100 Subject: chore(szr): remove dummy code for SZR emulation --- .../eidas/v2/tasks/CreateIdentityLinkTask.java | 97 ++-------------------- 1 file changed, 6 insertions(+), 91 deletions(-) (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java') diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/CreateIdentityLinkTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/CreateIdentityLinkTask.java index 740e5292..0aba70d1 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/CreateIdentityLinkTask.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/CreateIdentityLinkTask.java @@ -23,21 +23,16 @@ package at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks; -import java.io.IOException; -import java.io.InputStream; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.xml.parsers.ParserConfigurationException; import org.jetbrains.annotations.Nullable; import org.jose4j.lang.JoseException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.xml.sax.SAXException; import com.fasterxml.jackson.core.JsonProcessingException; @@ -64,8 +59,6 @@ import at.gv.egiz.eaaf.core.impl.data.Pair; import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper; import at.gv.egiz.eaaf.core.impl.idp.auth.data.SimpleIdentityLinkAssertionParser; import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; -import at.gv.egiz.eaaf.core.impl.utils.DomUtils; -import at.gv.egiz.eaaf.core.impl.utils.XPathUtils; import lombok.Data; import lombok.extern.slf4j.Slf4j; import szrservices.IdentityLinkType; @@ -124,21 +117,17 @@ public class CreateIdentityLinkTask extends AbstractAuthServletTask { final SimpleEidasData eidData = MatchingTaskUtils.getInitialEidasData(pendingReq); MatchedPersonResult matchedPersonData = MatchingTaskUtils.getFinalMatchingResult(pendingReq); + // write log information based on current configuration writeMdsLogInformation(eidData); - if (basicConfig.getBasicConfigurationBoolean(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_DEBUG_USEDUMMY, false)) { - buildDummyIdentityLink(eidData); + //request SZR based on IDL or E-ID mode + if (pendingReq.getServiceProviderConfiguration() + .isConfigurationValue(MsEidasNodeConstants.PROP_CONFIG_SP_NEW_EID_MODE, false)) { + executeEidMode(eidData, matchedPersonData); } else { - //request SZR based on IDL or E-ID mode - if (pendingReq.getServiceProviderConfiguration() - .isConfigurationValue(MsEidasNodeConstants.PROP_CONFIG_SP_NEW_EID_MODE, false)) { - executeEidMode(eidData, matchedPersonData); + executeIdlMode(eidData, matchedPersonData); - } else { - executeIdlMode(eidData, matchedPersonData); - - } } storeGenericInfoToSession(eidData); @@ -213,21 +202,6 @@ public class CreateIdentityLinkTask extends AbstractAuthServletTask { } - private void buildDummyIdentityLink(SimpleEidasData eidData) - throws ParserConfigurationException, SAXException, IOException, EaafException { - AuthProcessDataWrapper authProcessDataWrapper = MatchingTaskUtils.getAuthProcessDataWrapper(pendingReq); - SzrResultHolder idlResult = createDummyIdentityLinkForTestDeployment(eidData); - //inject personal-data into session - authProcessDataWrapper.setIdentityLink(idlResult.getIdentityLink()); - - // set bPK and bPKType into auth session - authProcessDataWrapper.setGenericDataToSession(PvpAttributeDefinitions.BPK_NAME, extendBpkByPrefix( - idlResult.getBpK(), pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier())); - authProcessDataWrapper.setGenericDataToSession(PvpAttributeDefinitions.EID_SECTOR_FOR_IDENTIFIER_NAME, - pendingReq.getServiceProviderConfiguration() - .getAreaSpecificTargetIdentifier()); - } - private void writeExtendedRevisionLogEntry(SimpleEidasData eidData, String personalIdentifier) { // write ERnP input-data into revision-log if (basicConfig.getBasicConfigurationBoolean( @@ -343,63 +317,4 @@ public class CreateIdentityLinkTask extends AbstractAuthServletTask { final String bpK; } - - /** - * Build a dummy IdentityLink and a dummy bPK based on eIDAS information. - * - *

    - * FOR LOCAL TESTING ONLY!!! - * - * @param eidData Information from eIDAS response - * @return IdentityLink and bPK - * @throws ParserConfigurationException In case of an IDL processing error - * @throws SAXException In case of an IDL processing error - * @throws IOException In case of an IDL processing error - * @throws EaafException In case of a bPK generation error - */ - private SzrResultHolder createDummyIdentityLinkForTestDeployment(SimpleEidasData eidData) - throws ParserConfigurationException, SAXException, IOException, EaafException { - log.warn("SZR-Dummy IS ACTIVE! IdentityLink is NOT VALID!!!!"); - // create fake IdL - // - fetch IdL template from resources - final InputStream s = CreateIdentityLinkTask.class - .getResourceAsStream("/resources/xmldata/fakeIdL_IdL_template.xml"); - final Element idlTemplate = DomUtils.parseXmlValidating(s); - - IIdentityLink identityLink = new SimpleIdentityLinkAssertionParser(idlTemplate).parseIdentityLink(); - - // replace data - final Element idlassertion = identityLink.getSamlAssertion(); - - // - set fake baseID; - final Node prIdentification = XPathUtils - .selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_IDENT_VALUE_XPATH); - prIdentification.getFirstChild().setNodeValue(eidData.getPseudonym()); - - // - set last name - final Node prFamilyName = XPathUtils - .selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_FAMILY_NAME_XPATH); - prFamilyName.getFirstChild().setNodeValue(eidData.getFamilyName()); - - // - set first name - final Node prGivenName = XPathUtils - .selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_GIVEN_NAME_XPATH); - prGivenName.getFirstChild().setNodeValue(eidData.getGivenName()); - - // - set date of birth - final Node prDateOfBirth = XPathUtils - .selectSingleNode(idlassertion, SimpleIdentityLinkAssertionParser.PERSON_DATE_OF_BIRTH_XPATH); - - prDateOfBirth.getFirstChild().setNodeValue(eidData.getDateOfBirth()); - - identityLink = new SimpleIdentityLinkAssertionParser(idlassertion).parseIdentityLink(); - - String idValue = identityLink.getIdentificationValue(); - String idType = identityLink.getIdentificationType(); - String targetId = pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier(); - final Pair bpkCalc = BpkBuilder.generateAreaSpecificPersonIdentifier(idValue, idType, targetId); - return new SzrResultHolder(identityLink, bpkCalc.getFirst()); - - } - } -- cgit v1.2.3 From b430405209fb61d7de7dec19fe9b2da780a575ac Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Mon, 7 Feb 2022 15:11:55 +0100 Subject: feature(ernp): update MDS if register information does not match to information from eIDAS --- .../auth/eidas/v2/clients/ernp/ErnpRestClient.java | 111 ++++++++++++++++----- 1 file changed, 85 insertions(+), 26 deletions(-) (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java') diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java index 58b3ca45..15b7573c 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java @@ -38,8 +38,10 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include; 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.dao.SimpleEidasData; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData.SimpleEidasDataBuilder; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.api.DefaultApi; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.invoker.ApiClient; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.Aendern; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.AendernResponse; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.AnlegenResponse; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.Eidas; @@ -49,6 +51,7 @@ import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.PersonAen import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.PersonAnlegen; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.PersonSuchen; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.Personendaten; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.PersonendatenErgebnis; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.SuchEidas; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.Suchdaten; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.SuchenResponse; @@ -247,10 +250,11 @@ public class ErnpRestClient implements IErnpClient { // select elements that have to be updated Collection eidasDocumentToAdd = - selectEidasDocumentsToAdd(ernpPersonToKitt, eidData); + selectEidasDocumentsToAdd(ernpPersonToKitt, eidData); + SimpleEidasData mdsToUpdate = selectMdsInformationToUpdate(ernpPersonToKitt, eidData); - if (eidasDocumentToAdd.isEmpty()) { - log.info("Find no eIDAS document for update during: {}. Looks strange but nothing todo", + if (eidasDocumentToAdd.isEmpty() && mdsToUpdate == null) { + log.info("Find no eIDAS document or MDS for update during: {}. Nothing todo on ERnP side", PROCESS_KITT_GENERAL); return new ErnpRegisterResult(Arrays.asList(registerResult)); @@ -258,7 +262,7 @@ public class ErnpRestClient implements IErnpClient { log.info("Find #{} eIDAS documents for update during: {}", eidasDocumentToAdd.size(), PROCESS_KITT_GENERAL); // update entry based on selected update info's and results from search response - return updatePersonInErnp(ernpPersonToKitt, eidasDocumentToAdd, eidData.getCitizenCountryCode()); + return updatePersonInErnp(ernpPersonToKitt, eidasDocumentToAdd, mdsToUpdate, eidData.getCitizenCountryCode()); } @@ -430,27 +434,8 @@ public class ErnpRestClient implements IErnpClient { } - /** - * Build AT specific Date String 'yyyy-MM-dd' from ERnP birthday representation. - * - *

    - * Info: {@link LocalDate} can not be used, because '1940-00-00' is also - * a valid birthday on ERnP site. - *

    - * - * @param geburtsdatum ERnP birthday representation - * @return birthday in 'yyyy-MM-dd' format - */ - private String getTextualBirthday(PartialDate geburtsdatum) { - return MessageFormat.format("{0}-{1}-{2}", - String.valueOf(geburtsdatum.getJahr()), - String.format("%02d", geburtsdatum.getMonat()), - String.format("%02d", geburtsdatum.getTag())); - - } - private ErnpRegisterResult updatePersonInErnp(Person ernpPersonToKitt, - Collection eidasDocumentToAdd, String citizenCountryCode) + Collection eidasDocumentToAdd, SimpleEidasData mdsToUpdate, String citizenCountryCode) throws ServiceFault { // build generic request metadata final GenericRequestParams generic = buildGenericRequestParameters("stepKittUpdate"); @@ -466,8 +451,12 @@ public class ErnpRestClient implements IErnpClient { // add new eIDAS attributes eidasDocumentToAdd.stream().forEach(el -> ernpReq.getAnlegen().addEidasItem(el)); - // TODO: should we update MDS also in that step? - + // update MDS if required + if (mdsToUpdate != null) { + log.debug("Find MDS to update. Injection update entries into ERnP request ... "); + ernpReq.setAendern(generateMdsChangeRequest(ernpPersonToKitt, mdsToUpdate)); + + } // request ERnP log.trace("Requesting ERnP for '{}' operation", PROCESS_KITT_IDENITIES_UPDATE); @@ -604,6 +593,56 @@ public class ErnpRestClient implements IErnpClient { return el; } + private SimpleEidasData selectMdsInformationToUpdate(Person ernpPersonToKitt, SimpleEidasData eidData) { + PersonendatenErgebnis person = ernpPersonToKitt.getPersonendaten(); + SimpleEidasDataBuilder builder = SimpleEidasData.builder(); + + boolean findMismatch = false; + if (!person.getVorname().equals(eidData.getGivenName())) { + findMismatch = true; + builder.givenName(eidData.getGivenName()); + + } + + if (!person.getFamilienname().equals(eidData.getFamilyName())) { + findMismatch = true; + builder.familyName(eidData.getFamilyName()); + + } + + if (!getTextualBirthday(person.getGeburtsdatum()).equals(eidData.getDateOfBirth())) { + findMismatch = true; + builder.dateOfBirth(eidData.getDateOfBirth()); + + } + + return findMismatch ? builder.build() : null; + } + + private Aendern generateMdsChangeRequest(Person ernpPersonToKitt, SimpleEidasData mdsToUpdate) { + Aendern el = new Aendern(); + Personendaten person = new Personendaten(); + person.setEntityId(ernpPersonToKitt.getPersonendaten().getEntityId()); + el.setPersonendaten(person); + + if (StringUtils.isNotEmpty(mdsToUpdate.getFamilyName())) { + person.setFamilienname(mdsToUpdate.getFamilyName()); + + } + + if (StringUtils.isNotEmpty(mdsToUpdate.getGivenName())) { + person.setVorname(mdsToUpdate.getGivenName()); + + } + + if (StringUtils.isNotEmpty(mdsToUpdate.getDateOfBirth())) { + person.setGeburtsdatum(buildErnpBirthday(mdsToUpdate.getDateOfBirth())); + + } + return el; + + } + /** * Map an AT specific Date String 'yyyy-MM-dd' to ERnP birthday representation. * @@ -626,6 +665,26 @@ public class ErnpRestClient implements IErnpClient { return result; } + + /** + * Build AT specific Date String 'yyyy-MM-dd' from ERnP birthday representation. + * + *

    + * Info: {@link LocalDate} can not be used, because '1940-00-00' is also + * a valid birthday on ERnP site. + *

    + * + * @param geburtsdatum ERnP birthday representation + * @return birthday in 'yyyy-MM-dd' format + */ + private String getTextualBirthday(PartialDate geburtsdatum) { + return MessageFormat.format("{0}-{1}-{2}", + String.valueOf(geburtsdatum.getJahr()), + String.format("%02d", geburtsdatum.getMonat()), + String.format("%02d", geburtsdatum.getTag())); + + } + /** * Get all eIDAS document with the specified country code and document type. -- cgit v1.2.3 From 5b0a9142a0e00fa528f86f8fe432c0e44ed4ae8e Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Mon, 7 Feb 2022 15:19:56 +0100 Subject: refactor(matching): change 'kitt' and 'update' steps in 'InitialSearchTask' - Update MDS in case of changes eIDAS data and already existing ERnP entry - Add additional attributes in case of new eIDAS attributes outside of MDS --- .../modules/auth/eidas/v2/dao/SimpleEidasData.java | 22 ++++++++++-- .../eidas/v2/service/RegisterSearchService.java | 22 ++++++++++-- .../auth/eidas/v2/tasks/InitialSearchTask.java | 42 +++++++++++----------- 3 files changed, 59 insertions(+), 27 deletions(-) (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java') 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 index 5ad92507..e76768b6 100644 --- 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 @@ -23,10 +23,11 @@ package at.asitplus.eidas.specific.modules.auth.eidas.v2.dao; +import org.apache.commons.lang3.builder.EqualsBuilder; + import at.gv.e_government.reference.namespace.persondata._20020228.PostalAddressType; import lombok.Builder; import lombok.Data; -import org.apache.commons.lang3.builder.EqualsBuilder; @Data @Builder @@ -68,8 +69,11 @@ public class SimpleEidasData { .append(result.getGivenName(), givenName) .append(result.getFamilyName(), familyName) .append(result.getDateOfBirth(), dateOfBirth) - .isEquals() - && result.getPseudonym().stream().anyMatch(el -> el.equals(pseudonym)); + .appendSuper(result.getPseudonym().stream().anyMatch(el -> el.equals(pseudonym))) + .appendSuper(checkOptionalAttributes(result.getPlaceOfBirth(), placeOfBirth)) + .appendSuper(checkOptionalAttributes(result.getBirthName(), birthName)) + .isEquals(); + } /** @@ -84,5 +88,17 @@ public class SimpleEidasData { .isEquals(); } + /** + * Check if eIDAS attribute is available. + * + * @param registerData Attribute value from register + * @param eidasData Attribute value from eIDAS + * @return true if eidasData is null or eidasData does not match to register value, + * otherwise false + */ + private static boolean checkOptionalAttributes(String registerData, String eidasData) { + return eidasData == null || eidasData.equals(registerData); + + } } 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 488b571b..85ea942c 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 @@ -7,6 +7,7 @@ import java.util.List; import javax.annotation.Nonnull; import org.jetbrains.annotations.Nullable; +import org.springframework.lang.NonNull; import org.springframework.stereotype.Service; import com.google.common.collect.Streams; @@ -186,34 +187,49 @@ public class RegisterSearchService { * @param initialEidasData Received eidas data from initial authn * @return */ + @NonNull public RegisterStatusResults step7aKittProcess(RegisterStatusResults registerResult, SimpleEidasData initialEidasData) throws WorkflowException { log.trace("Starting step7aKittProcess"); - // TODO verify with which data this method gets called + + // check if only one single result was found if (registerResult.getResultCount() != 1) { throw new WorkflowException("step7aKittProcess", "getResultCount() != 1"); + } + + // perform updated operation in respect to register results try { if (registerResult.getResultsZmr().size() == 1) { RegisterResult entryZmr = registerResult.getResultsZmr().get(0); ZmrRegisterResult updateZmr = zmrClient .update(registerResult.getOperationStatus().getZmrProcessId(), entryZmr, initialEidasData); return RegisterStatusResults.fromZmr(updateZmr); + } else { RegisterResult entryErnp = registerResult.getResultsErnp().get(0); ErnpRegisterResult updateErnp = ernpClient.update(entryErnp, initialEidasData); return RegisterStatusResults.fromErnp(registerResult.operationStatus, updateErnp); + } } catch (final EidasSAuthenticationException e) { throw new WorkflowException("kittMatchedIdentitiess", e.getMessage(), !(e instanceof ZmrCommunicationException), e); + } } - //TODO: check this method, because it's different to 'step7aKittProcess'??? /** * Automatic process to fix the register entries. * Called when the alternative eIDAS authn leads to a match in a register. + * + *

    This method perform two additional operations: + *

      + *
    • Use bPK to check if altSearchResult is part of initialSearchResult.
    • + *
    • Update register entry twice, be using information from alternative authentication altEidasData + * and from initial authentication initialEidasData.
    • + *
    + *

    * * @param initialSearchResult Register results from initial authentication * @param initialEidasData Received eIDAS data from initial authentication @@ -273,7 +289,7 @@ public class RegisterSearchService { // update ZMR entry by using eIDAS information from alternative authentication ErnpRegisterResult updateAlt = ernpClient.update(entryErnp, altEidasData); - return RegisterStatusResults.fromErnp(altSearchResult.operationStatus, updateAlt); + return RegisterStatusResults.fromErnp(altSearchResult.getOperationStatus(), updateAlt); } } catch (final EidasSAuthenticationException e) { throw new WorkflowException("kittMatchedIdentitiess", e.getMessage(), 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 index c720cb7f..9564a8fc 100644 --- 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 @@ -122,8 +122,9 @@ public class InitialSearchTask extends AbstractAuthServletTask { if (resultCount == 0) { step6CountrySpecificSearch(executionContext, searchResult.getOperationStatus(), eidasData); - } else if (resultCount == 1) { - foundMatchFinalizeTask(searchResult, eidasData); + } else if (resultCount == 1) { + RegisterResult updatedResult = step3CheckRegisterUpdateNecessary(searchResult, eidasData); + foundMatchFinalizeTask(updatedResult, eidasData); } else { throw new WorkflowException("step2RegisterSearchWithPersonIdentifier", @@ -146,10 +147,12 @@ public class InitialSearchTask extends AbstractAuthServletTask { if (searchResult.getResultCount() == 0) { log.trace("'step6CountrySpecificSearch' ends with no result. Forward to next matching step ... "); step8RegisterSearchWithMds(executionContext, searchResult.getOperationStatus(), eidasData); + } else if (searchResult.getResultCount() == 1) { log.trace("'step6CountrySpecificSearch' finds a person. Forward to 'step7aKittProcess' step ... "); - registerSearchService.step7aKittProcess(searchResult, eidasData); - foundMatchFinalizeTask(searchResult, eidasData); + RegisterStatusResults updatedResult = registerSearchService.step7aKittProcess(searchResult, eidasData); + foundMatchFinalizeTask(updatedResult.getResult(), eidasData); + } else { throw new WorkflowException("step6CountrySpecificSearch", "More than one entry with unique country-specific information", true); @@ -172,29 +175,26 @@ public class InitialSearchTask extends AbstractAuthServletTask { } } - private void foundMatchFinalizeTask(RegisterStatusResults searchResult, SimpleEidasData eidasData) - throws WorkflowException, EaafStorageException { - RegisterResult updatedResult = step3CheckRegisterUpdateNecessary(searchResult.getResult(), eidasData); - MatchedPersonResult result = MatchedPersonResult.generateFormMatchingResult( - updatedResult, eidasData.getCitizenCountryCode()); - MatchingTaskUtils.storeFinalMatchingResult(pendingReq, result); - } - - private RegisterResult step3CheckRegisterUpdateNecessary(RegisterResult searchResult, - SimpleEidasData eidasData) { + private RegisterResult step3CheckRegisterUpdateNecessary( + RegisterStatusResults searchResult, SimpleEidasData eidasData) throws WorkflowException { log.trace("Starting step3CheckRegisterUpdateNecessary"); - if (!eidasData.equalsRegisterData(searchResult)) { - log.info("Skipping update-register-information step, because it's not supported yet"); - - //TODO: update of ERnP information are allowed. Add ERnP update-step. Maybe we can use regular KITT steps - + if (!eidasData.equalsRegisterData(searchResult.getResult())) { + log.debug("PersonalIdentifier match but MDS or other information changed. Starting update process ... "); + return registerSearchService.step7aKittProcess(searchResult, eidasData).getResult(); - return searchResult; } else { log.debug("Register information match to eIDAS information. No update required"); - return searchResult; + return searchResult.getResult(); } } + + private void foundMatchFinalizeTask(RegisterResult updatedResult, SimpleEidasData eidasData) + throws WorkflowException, EaafStorageException { + MatchedPersonResult result = + MatchedPersonResult.generateFormMatchingResult(updatedResult, eidasData.getCitizenCountryCode()); + MatchingTaskUtils.storeFinalMatchingResult(pendingReq, result); + + } @NotNull private SimpleEidasData convertEidasAttrToSimpleData() -- cgit v1.2.3 From 02e3d1b479234ac8d028f00263cfc1b311209a0c Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Mon, 7 Feb 2022 15:20:29 +0100 Subject: chore(mathing): change log level ZMRClient --- .../eidas/specific/modules/auth/eidas/v2/clients/zmr/ZmrSoapClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java') 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 432df9ef..18a80c33 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 @@ -269,7 +269,7 @@ public class ZmrSoapClient extends AbstractSoapClient implements IZmrClient { selectEidasDocumentsToAdd(zmrPersonToKitt, eidData); if (eidasDocumentToAdd.isEmpty()) { - log.info("Find no eIDAS document for update during: {}. Looks strange but nothing todo", + log.info("Find no eIDAS document for update during: {}. Nothing todo on ZMR side", PROCESS_KITT_GENERAL); return new ZmrRegisterResult(Arrays.asList(registerResult), zmrProzessId); -- cgit v1.2.3 From cc54421d99604cd2f2b01846f94bb11fb192028d Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Mon, 7 Feb 2022 18:22:27 +0100 Subject: chore(matching): fix some code-style and code-quality issues --- .../auth/eidas/v2/clients/ernp/ErnpRestClient.java | 20 ++++++++++---------- .../v2/exception/ErnpRestCommunicationException.java | 5 +++++ .../auth/eidas/v2/tasks/CreateNewErnpEntryTask.java | 2 +- 3 files changed, 16 insertions(+), 11 deletions(-) (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java') diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java index 15b7573c..3c19e9c1 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java @@ -86,7 +86,7 @@ import lombok.extern.slf4j.Slf4j; public class ErnpRestClient implements IErnpClient { private static final String ERROR_MATCHING_11 = "module.eidasauth.matching.11"; - private static final String ERROR_MATCHING_12 = "module.eidasauth.matching.12"; + //private static final String ERROR_MATCHING_12 = "module.eidasauth.matching.12"; private static final String ERROR_MATCHING_99 = "module.eidasauth.matching.99"; private static final String LOGMSG_MISSING_CONFIG = "Missing configuration with key: {0}"; @@ -95,8 +95,8 @@ public class ErnpRestClient implements IErnpClient { private static final String LOGMSG_ERNP_RESP_PROCESS = "Proces ERnP response during '{}' operation failes with msg: {}"; - private static final String LOGMSG_ERNP_REST_ERROR = - "ERnP anwser for transaction: {0} with code: {1} and message: {2}"; + //private static final String LOGMSG_ERNP_REST_ERROR = + // "ERnP anwser for transaction: {0} with code: {1} and message: {2}"; private static final String PROCESS_SEARCH_PERSONAL_IDENTIFIER = "Searching " + Constants.eIDAS_ATTR_PERSONALIDENTIFIER; @@ -429,7 +429,7 @@ public class ErnpRestClient implements IErnpClient { //TODO: search eIDAS has to be a LIST!!!!!! SuchEidas eidasInfos = new SuchEidas(); - searchInfos.setEidas(eidasInfos ); + searchInfos.setEidas(eidasInfos); return searchInfos; } @@ -542,7 +542,7 @@ public class ErnpRestClient implements IErnpClient { final Suchdaten searchInfos = new Suchdaten(); searchInfos.setFamilienname(registerResult.getFamilyName()); searchInfos.setVorname(registerResult.getGivenName()); - searchInfos.setGeburtsdatum(buildErnpBirthday(registerResult.getDateOfBirth())); + searchInfos.setGeburtsdatum(buildErnpBirthday(registerResult.getDateOfBirth())); final PersonSuchen personSuchen = new PersonSuchen(); personSuchen.setSuchoptionen(generateSearchParameters()); @@ -572,8 +572,8 @@ public class ErnpRestClient implements IErnpClient { Constants.eIDAS_ATTRURN_PERSONALIDENTIFIER, eidData.getPseudonym())); if (StringUtils.isNotEmpty(eidData.getPlaceOfBirth())) { - ernpReq.addEidasItem(buildNewEidasDocument(eidData.getCitizenCountryCode(), - Constants.eIDAS_ATTRURN_PLACEOFBIRTH, eidData.getPlaceOfBirth())); + ernpReq.addEidasItem(buildNewEidasDocument(eidData.getCitizenCountryCode(), + Constants.eIDAS_ATTRURN_PLACEOFBIRTH, eidData.getPlaceOfBirth())); } @@ -773,9 +773,9 @@ public class ErnpRestClient implements IErnpClient { public void handleError(ClientHttpResponse response) throws IOException { // TODO: opimize errorHandling based on response info's from real ERnP - List serverId = response.getHeaders().getOrEmpty(ERNP_RESPONSE_HEADER_SERVER_ID); - log.warn("Receive http-error: {} from ERnP with serverTransactionId", - response.getRawStatusCode(), serverId.isEmpty() ? "'not set'" : serverId.get(0)); + List serverId = response.getHeaders().getOrEmpty(ERNP_RESPONSE_HEADER_SERVER_ID); + log.warn("Receive http-error: {} from ERnP with serverTransactionId", + response.getRawStatusCode(), serverId.isEmpty() ? "'not set'" : serverId.get(0)); throw new ErnpRestCommunicationException(response.getRawStatusCode()); diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/ErnpRestCommunicationException.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/ErnpRestCommunicationException.java index e3224c93..566a8fa4 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/ErnpRestCommunicationException.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/ErnpRestCommunicationException.java @@ -16,6 +16,11 @@ public class ErnpRestCommunicationException extends IOException { @Getter int httpStatusCode; + /** + * ERnP communication error on HTTP REST level. + * + * @param rawStatusCode HTTP statuscode + */ public ErnpRestCommunicationException(int rawStatusCode) { super("ERnP service answers with an error and HTTP status-code: " + rawStatusCode); this.httpStatusCode = rawStatusCode; diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/CreateNewErnpEntryTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/CreateNewErnpEntryTask.java index b63b0ca0..c7843be5 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/CreateNewErnpEntryTask.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/CreateNewErnpEntryTask.java @@ -65,7 +65,7 @@ public class CreateNewErnpEntryTask extends AbstractAuthServletTask { /** * Constructor. - * @param szrClient SZR client for creating a new ERnP entry + * @param client SZR client for creating a new ERnP entry */ public CreateNewErnpEntryTask(@Autowired ErnpRestClient client) { this.ernpClient = client; -- cgit v1.2.3 From 6e7c333ec6e9a6fe33737ee3a67a23433854a55b Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Mon, 7 Feb 2022 18:37:05 +0100 Subject: fix(matching): make matching DTO's serializeable because the has to be stored into session --- .../specific/modules/auth/eidas/v2/dao/MatchedPersonResult.java | 6 +++++- .../eidas/specific/modules/auth/eidas/v2/dao/RegisterResult.java | 5 ++++- .../eidas/specific/modules/auth/eidas/v2/dao/SimpleEidasData.java | 6 +++++- .../modules/auth/eidas/v2/dao/SimpleMobileSignatureData.java | 6 +++++- 4 files changed, 19 insertions(+), 4 deletions(-) (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java') diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/MatchedPersonResult.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/MatchedPersonResult.java index 1e8fcecf..1dcea7fc 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/MatchedPersonResult.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/MatchedPersonResult.java @@ -1,5 +1,7 @@ package at.asitplus.eidas.specific.modules.auth.eidas.v2.dao; +import java.io.Serializable; + import lombok.Builder; import lombok.Getter; @@ -11,7 +13,9 @@ import lombok.Getter; */ @Getter @Builder -public class MatchedPersonResult { +public class MatchedPersonResult implements Serializable { + + private static final long serialVersionUID = 9110998952621456281L; /** * Matched person result from matching result. 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 index aa82d806..e5878ff3 100644 --- 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 @@ -23,6 +23,7 @@ package at.asitplus.eidas.specific.modules.auth.eidas.v2.dao; +import java.io.Serializable; import java.util.List; import at.gv.e_government.reference.namespace.persondata._20020228.PostalAddressType; @@ -31,8 +32,10 @@ import lombok.Getter; @Builder @Getter -public class RegisterResult { +public class RegisterResult implements Serializable { + private static final long serialVersionUID = 762728480185716130L; + // MDS private final List pseudonym; private final String givenName; 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 index e76768b6..f9301505 100644 --- 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 @@ -23,6 +23,8 @@ package at.asitplus.eidas.specific.modules.auth.eidas.v2.dao; +import java.io.Serializable; + import org.apache.commons.lang3.builder.EqualsBuilder; import at.gv.e_government.reference.namespace.persondata._20020228.PostalAddressType; @@ -31,7 +33,9 @@ import lombok.Data; @Data @Builder -public class SimpleEidasData { +public class SimpleEidasData implements Serializable { + + private static final long serialVersionUID = 2848914124372968418L; /** * Full eIDAS personal identifier with prefix. diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/SimpleMobileSignatureData.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/SimpleMobileSignatureData.java index 92e727ea..54cb3f31 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/SimpleMobileSignatureData.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/SimpleMobileSignatureData.java @@ -23,6 +23,8 @@ package at.asitplus.eidas.specific.modules.auth.eidas.v2.dao; +import java.io.Serializable; + import org.apache.commons.lang3.builder.EqualsBuilder; import lombok.Builder; @@ -30,7 +32,9 @@ import lombok.Data; @Data @Builder -public class SimpleMobileSignatureData { +public class SimpleMobileSignatureData implements Serializable { + + private static final long serialVersionUID = 7775305733438275312L; private final String bpk; private final String givenName; -- cgit v1.2.3 From 1a5d7bd12b0028b7cdb4e1b5e99d6162a323dce8 Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Tue, 8 Feb 2022 08:07:48 +0100 Subject: chore(ernp): ignore search requests with residence information. ERnP search is not used here, because we only search for people with Austrian residence and they are in ZMR only. --- .../specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java') diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java index 3c19e9c1..3822da01 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java @@ -311,8 +311,10 @@ public class ErnpRestClient implements IErnpClient { @Override public ErnpRegisterResult searchWithResidenceData(String givenName, String familyName, String dateOfBirth, - String zipcode, String city, String street) { + String zipcode, String city, String street) { + log.warn("Matching with residence information is prohibited by design! This requests will be ignored"); return new ErnpRegisterResult(Collections.emptyList()); + } @PostConstruct -- cgit v1.2.3 From a2baf085fcd3a1940585beb3f4a8acb2e4e5a461 Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Tue, 8 Feb 2022 11:40:01 +0100 Subject: refactor(matching): move AddresssucheController into eIDAS module to reuse data-model for tasks --- .../eidas/v2/controller/AdresssucheController.java | 258 +++++++++++++++++++++ 1 file changed, 258 insertions(+) create mode 100644 eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/controller/AdresssucheController.java (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java') 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 new file mode 100644 index 00000000..8505f5d5 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/controller/AdresssucheController.java @@ -0,0 +1,258 @@ +/* + * Copyright 2018 A-SIT Plus GmbH + * AT-specific eIDAS Connector has been developed in a cooperation between EGIZ, + * A-SIT Plus GmbH, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "License"); + * You may not use this work except in compliance with the License. + * You may obtain a copy of the License at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + +package at.asitplus.eidas.specific.modules.auth.eidas.v2.controller; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.builder.CompareToBuilder; +import org.jetbrains.annotations.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.ResourceLoader; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; + +import at.asitplus.eidas.specific.connector.MsEidasNodeConstants; +import at.asitplus.eidas.specific.connector.gui.StaticGuiBuilderConfiguration; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.zmr.ZmrAddressSoapClient; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasSAuthenticationException; +import at.gv.bmi.namespace.zmr_su.zrm._20040201_.address.Adressdaten; +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.api.gui.ISpringMvcGuiFormBuilder; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.api.utils.IPendingRequestIdGenerationStrategy; +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.Data; +import lombok.extern.slf4j.Slf4j; + +/** + * Default process-engine signaling controller. + * + * @author tlenz + */ +@Controller +@Slf4j +public class AdresssucheController { + + public static final String PARAM_POSTLEITZAHL = "postleitzahl"; + public static final String PARAM_MUNIPICALITY = "municipality"; + public static final String PARAM_VILLAGE = "village"; + public static final String PARAM_STREET = "street"; + public static final String PARAM_NUMBER = "number"; + + @Autowired + private ISpringMvcGuiFormBuilder guiBuilder; + + @Autowired + private IConfiguration basicConfig; + + @Autowired + private ResourceLoader resourceLoader; + + @Autowired + private ZmrAddressSoapClient client; + + @Autowired + private IPendingRequestIdGenerationStrategy pendingReqGeneration; + + /** + * Show the "residency.html" directly. + * TODO Remove this after testing. + */ + @RequestMapping(value = {"/test"}, method = {RequestMethod.GET}) + public void test(HttpServletRequest request, HttpServletResponse response) throws GuiBuildException, EaafException { + final StaticGuiBuilderConfiguration config = new StaticGuiBuilderConfiguration( + basicConfig, + "http://localhost:8080/ms_connector/", + basicConfig.getBasicConfiguration(//TODO + MsEidasNodeConstants.PROP_CONFIG_WEBCONTENT_TEMPLATES_RESIDENCY, + MsEidasNodeConstants.TEMPLATE_HTML_RESIDENCY), + MsEidasNodeConstants.ENDPOINT_RESIDENCY_INPUT, + resourceLoader); + config.putCustomParameter(null, "pendingid", pendingReqGeneration.generateExternalPendingRequestId()); + guiBuilder.build(request, response, config, "Query Austrian residency"); + } + + /** + * Show the "other_login_method.html" directly. + * TODO Remove this after testing. + */ + @RequestMapping(value = {"/olm"}, method = {RequestMethod.GET}) + public void otherloginmethod(HttpServletRequest request, HttpServletResponse response) throws GuiBuildException, + EaafException { + final StaticGuiBuilderConfiguration config = new StaticGuiBuilderConfiguration( + basicConfig, + "http://localhost:8080/ms_connector/", + basicConfig.getBasicConfiguration(//TODO + MsEidasNodeConstants.PROP_CONFIG_WEBCONTENT_TEMPLATES_OTHER_LOGIN_METHOD_SELECTION, + MsEidasNodeConstants.TEMPLATE_HTML_OTHERLOGINMETHODS), + MsEidasNodeConstants.ENDPOINT_OTHER_LOGIN_METHOD_SELECTION, + resourceLoader); + config.putCustomParameter(null, "pendingid", pendingReqGeneration.generateExternalPendingRequestId()); + guiBuilder.build(request, response, config, "Other Login Method"); + } + + /** + * Show the "country_selection.html" directly. + * TODO Remove this after testing. + */ + @RequestMapping(value = {"/country"}, method = {RequestMethod.GET}) + public void countryselection(HttpServletRequest request, HttpServletResponse response) throws GuiBuildException, + EaafException { + final StaticGuiBuilderConfiguration config = new StaticGuiBuilderConfiguration( + basicConfig, + "http://localhost:8080/ms_connector/", + basicConfig.getBasicConfiguration(//TODO + MsEidasNodeConstants.PROP_CONFIG_WEBCONTENT_TEMPLATES_CCSELECTION, + MsEidasNodeConstants.TEMPLATE_HTML_COUNTRYSELECTION), + MsEidasNodeConstants.ENDPOINT_COUNTRYSELECTION, + resourceLoader); + config.putCustomParameter(null, "pendingid", pendingReqGeneration.generateExternalPendingRequestId()); + guiBuilder.build(request, response, config, "Country Selection"); + } + + /** + * Performs search for addresses in ZMR. + */ + @RequestMapping(value = {"/residency/search"}, method = {RequestMethod.POST}) + public ResponseEntity search( + @RequestParam(PARAM_POSTLEITZAHL) String postleitzahl, + @RequestParam(PARAM_MUNIPICALITY) String municipality, + @RequestParam(PARAM_VILLAGE) String village, + @RequestParam(PARAM_STREET) String street, + @RequestParam(PARAM_NUMBER) String number, + @RequestParam(EaafConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID) String pendingId) { + log.info("Search with '{}', '{}', '{}', '{}', '{}'", + postleitzahl.replaceAll("[\r\n]", ""), + municipality.replaceAll("[\r\n]", ""), + village.replaceAll("[\r\n]", ""), + street.replaceAll("[\r\n]", ""), + 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(); + } + } + + private AdresssucheResult buildResponse(ZmrAddressSoapClient.AddressInfo searchOutput) { + if (searchOutput.getPersonResult().isEmpty()) { + log.warn("No result from ZMR"); + return new AdresssucheResult(Collections.emptyList(), 0); + } + log.info("Result level is {}", searchOutput.getLevel()); + Set result = searchOutput.getPersonResult().stream() + .map(Adressdaten::getPostAdresse) + .map(it -> new AdresssucheOutput(it.getPostleitzahl(), it.getGemeinde(), it.getOrtschaft(), + it.getZustelladresse().getStrassenname(), it.getZustelladresse().getOrientierungsnummer())) + .collect(Collectors.toSet()); + // TODO Add configuration option for the limit of 30 + List sorted = result.stream().sorted().limit(30).collect(Collectors.toList()); + return new AdresssucheResult(sorted, result.size()); + } + + private Adressdaten buildSearchInput(String postleitzahl, + String municipality, + String village, + String street, + String number) { + PostAdresseTyp postAdresse = new PostAdresseTyp(); + if (StringUtils.isNotBlank(postleitzahl)) { + postAdresse.setPostleitzahl(postleitzahl); + } + if (StringUtils.isNotBlank(municipality)) { + postAdresse.setGemeinde(municipality); + } + if (StringUtils.isNotBlank(village)) { + postAdresse.setOrtschaft(village); + } + if (StringUtils.isNotBlank(street) || StringUtils.isNotBlank(number)) { + ZustelladresseTyp zustelladresse = new ZustelladresseTyp(); + if (StringUtils.isNotBlank(street)) { + zustelladresse.setStrassenname(street); + } + if (StringUtils.isNotBlank(number)) { + zustelladresse.setOrientierungsnummer(number); + } + postAdresse.setZustelladresse(zustelladresse); + } + Adressdaten searchInput = new Adressdaten(); + searchInput.setPostAdresse(postAdresse); + return searchInput; + } + + @Data + @AllArgsConstructor + public static class AdresssucheResult { + private final Collection results; + private final int resultCount; + } + + @Data + @AllArgsConstructor + public static class AdresssucheOutput implements Comparable { + private final String postleitzahl; + private final String municipality; + private final String village; + private final String street; + private final String number; + + @Override + public int compareTo(@NotNull AdresssucheOutput o) { + return new CompareToBuilder() + .append(this.postleitzahl, o.postleitzahl) + .append(this.municipality, o.municipality) + .append(this.village, o.village) + .append(this.street, o.street) + .append(this.number, o.number) + .toComparison(); + } + } + +} -- cgit v1.2.3 From 33404685b1d8de14229f61ea5dfa1fbee6229916 Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Tue, 8 Feb 2022 14:50:03 +0100 Subject: feature(matching): finalize matching by residence search Add ZMR communication and state validation for match-by-residence operation --- .../specific/modules/auth/eidas/v2/Constants.java | 4 +- .../auth/eidas/v2/clients/zmr/IZmrClient.java | 21 ++- .../auth/eidas/v2/clients/zmr/ZmrSoapClient.java | 96 +++++++++-- .../eidas/v2/controller/AdresssucheController.java | 11 ++ .../eidas/v2/service/RegisterSearchService.java | 28 ++-- .../ReceiveAustrianResidenceGuiResponseTask.java | 175 +++++++++++---------- 6 files changed, 230 insertions(+), 105 deletions(-) (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java') 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; @@ -79,6 +80,23 @@ public interface IZmrClient { @Nonnull PersonSuchenRequest personSearchDao, @Nonnull String citizenCountryCode) throws EidasSAuthenticationException; + /** + * Search person based on MDS information and Austrian residence. + * + * @param zmrProzessId zmrProzessId zmrProzessId ProcessId from ZMR or null 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 null + * @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. * @@ -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 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 result = searchOutput.getPersonResult().stream() .map(Adressdaten::getPostAdresse) @@ -195,6 +203,7 @@ public class AdresssucheController { // TODO Add configuration option for the limit of 30 List 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 { 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 * * Transitions: *
      - *
    • {@link CreateNewErnpEntryTask} if no results from search with residency data in registers
    • + *
    • {@link GenerateOtherLoginMethodGuiTask} if no results from search with residency data in registers
    • *
    • {@link CreateIdentityLinkTask} if one exact match between initial register search (with MDS) and results * from search with residency data in registers exists
    • *
    • {@link GenerateOtherLoginMethodGuiTask} if a user input error has happened
    • @@ -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 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(); } } -- cgit v1.2.3 From d4027bf1ac134e50a1b8f1a59f862cf8abaa6c8c Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Tue, 8 Feb 2022 15:43:39 +0100 Subject: fix(zmr): update wrong workflow identifier in ZMR request in case of match-by-residence step --- .../eidas/specific/modules/auth/eidas/v2/clients/zmr/ZmrSoapClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java') 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 0f2f94cc..11c7cffe 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 @@ -308,7 +308,7 @@ public class ZmrSoapClient extends AbstractSoapClient implements IZmrClient { searchPersonReq.setPostAdresse(buildSearchAddress(address)); // set work-flow client information - req.setWorkflowInfoClient(generateWorkFlowInfos(PROCESS_SEARCH_BY_RESIDENCE, zmrProzessId)); + req.setWorkflowInfoClient(generateWorkFlowInfos(PROCESS_TASK_SEARCH, zmrProzessId)); req.setClientInfo(generateClientInfos()); // set additionl search parameters -- cgit v1.2.3 From e3eae0a6f822d66f33c1a32459dd4ba3cfc76852 Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Tue, 8 Feb 2022 16:31:08 +0100 Subject: chore(matching): update matching by 'ID Austria login' to forward user to 'otherLoginMethod' GUI in case of an error --- .../v2/tasks/ReceiveMobilePhoneSignatureResponseTask.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java') diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveMobilePhoneSignatureResponseTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveMobilePhoneSignatureResponseTask.java index 3e57ea24..2d28709b 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveMobilePhoneSignatureResponseTask.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveMobilePhoneSignatureResponseTask.java @@ -24,6 +24,7 @@ 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 static at.asitplus.eidas.specific.modules.auth.eidas.v2.idaustriaclient.IdAustriaClientAuthConstants.MODULE_NAME_FOR_LOGGING; @@ -127,6 +128,9 @@ public class ReceiveMobilePhoneSignatureResponseTask extends AbstractAuthServlet private static final String ERROR_MSG_02 = "PVP response decryption FAILED. No credential found."; private static final String ERROR_MSG_03 = "PVP response validation FAILED."; + private static final String MSG_PROP_23 = "module.eidasauth.matching.23"; + private static final String MSG_PROP_24 = "module.eidasauth.matching.24"; + /** * Creates the new task, with autowired dependencies from Spring. */ @@ -152,7 +156,9 @@ public class ReceiveMobilePhoneSignatureResponseTask extends AbstractAuthServlet Pair processedMsg = validateAssertion((PvpSProfileResponse) inboundMessage); if (processedMsg.getSecond()) { // forward to next matching step in case of ID Autria authentication was stopped by user - executionContext.put(Constants.TRANSITION_TO_GENERATE_GUI_QUERY_AUSTRIAN_RESIDENCE_TASK, true); + executionContext.put(Constants.TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK, true); + executionContext.put(CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON, MSG_PROP_23); + executionContext.put(CONTEXT_FLAG_ADVANCED_MATCHING_FAILED, true); return; } @@ -171,8 +177,9 @@ public class ReceiveMobilePhoneSignatureResponseTask extends AbstractAuthServlet // check if MDS from ID Austria authentication matchs to eIDAS authentication if (!simpleMobileSignatureData.equalsSimpleEidasData(eidasData)) { - executionContext.put(CONTEXT_FLAG_ADVANCED_MATCHING_FAILED, true); executionContext.put(TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK, true); + executionContext.put(CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON, MSG_PROP_24); + executionContext.put(CONTEXT_FLAG_ADVANCED_MATCHING_FAILED, true); return; } -- cgit v1.2.3 From 6936c9a9350ad5d83f6c84d649df63d5de1c188a Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Tue, 8 Feb 2022 16:37:50 +0100 Subject: chore(matching): update matching by 'alternative eIDAS Login' to forward user to 'otherLoginMethod' GUI in case of an error and show specific error message --- .../specific/modules/auth/eidas/v2/tasks/AlternativeSearchTask.java | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java') diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/AlternativeSearchTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/AlternativeSearchTask.java index f021fae9..96aa9c51 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/AlternativeSearchTask.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/AlternativeSearchTask.java @@ -23,6 +23,8 @@ 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.Map; @@ -78,6 +80,8 @@ import lombok.extern.slf4j.Slf4j; @SuppressWarnings("PMD.TooManyStaticImports") public class AlternativeSearchTask extends AbstractAuthServletTask { + private static final String MSG_PROP_25 = "module.eidasauth.matching.25"; + private final RegisterSearchService registerSearchService; private final ICcSpecificEidProcessingService eidPostProcessor; @@ -200,6 +204,8 @@ public class AlternativeSearchTask extends AbstractAuthServletTask { log.trace("'step12CountrySpecificSearch' ends with no result. Forward to GUI based matching step ... "); log.debug("Forward to GUI based matching steps ... "); executionContext.put(TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK, true); + executionContext.put(CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON, MSG_PROP_25); + executionContext.put(CONTEXT_FLAG_ADVANCED_MATCHING_FAILED, true); } else if (ccAltSearchResult.getResultCount() == 1) { log.debug("'step12CountrySpecificSearch' find single result. Starting KITT operation ... "); -- cgit v1.2.3 From 71d94fdd4435187c13321322893cd9b1bf273402 Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Tue, 8 Feb 2022 17:16:42 +0100 Subject: chore(matching): update 'other-login-method' GUI steps to use it as common starting-point for any other alternative matching method --- .../eidas/specific/modules/auth/eidas/v2/Constants.java | 4 +++- .../eidas/v2/tasks/GenerateOtherLoginMethodGuiTask.java | 7 +++++++ .../tasks/ReceiveOtherLoginMethodGuiResponseTask.java | 17 ++++++++++------- 3 files changed, 20 insertions(+), 8 deletions(-) (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java') 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 40bcd27a..e642c5ec 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,12 +314,14 @@ public class Constants { // UI options public static final String HTML_FORM_ADVANCED_MATCHING_FAILED = "advancedMatchingFailed"; + public static final String HTML_FORM_ADVANCED_MATCHING_FAILED_REASON = + HTML_FORM_ADVANCED_MATCHING_FAILED + "Reason"; // 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"; + 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/tasks/GenerateOtherLoginMethodGuiTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/GenerateOtherLoginMethodGuiTask.java index 7107709f..d29519be 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/GenerateOtherLoginMethodGuiTask.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/GenerateOtherLoginMethodGuiTask.java @@ -79,6 +79,13 @@ public class GenerateOtherLoginMethodGuiTask extends AbstractAuthServletTask { config.putCustomParameter(AbstractGuiFormBuilderConfiguration.PARAM_GROUP_UIOPTIONS, Constants.HTML_FORM_ADVANCED_MATCHING_FAILED, String.valueOf(true)); + //set detailed error-code + if (executionContext.get(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON) != null) { + config.putCustomParameter(AbstractGuiFormBuilderConfiguration.PARAM_GROUP_UIOPTIONS, + Constants.HTML_FORM_ADVANCED_MATCHING_FAILED_REASON, + executionContext.get(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON).toString()); + } + } guiBuilder.build(request, response, config, "Other login methods selection form"); diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveOtherLoginMethodGuiResponseTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveOtherLoginMethodGuiResponseTask.java index f4419c1c..c9f043b5 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveOtherLoginMethodGuiResponseTask.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveOtherLoginMethodGuiResponseTask.java @@ -23,17 +23,19 @@ package at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks; +import java.util.Enumeration; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang.StringEscapeUtils; +import org.springframework.stereotype.Component; + import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SelectedLoginMethod; import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; import at.gv.egiz.eaaf.core.impl.idp.controller.tasks.AbstractLocaleAuthServletTask; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang.StringEscapeUtils; -import org.springframework.stereotype.Component; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.util.Enumeration; /** * Handles user's selection from {@link GenerateOtherLoginMethodGuiTask}. @@ -65,12 +67,13 @@ public class ReceiveOtherLoginMethodGuiResponseTask extends AbstractLocaleAuthSe SelectedLoginMethod selection = SelectedLoginMethod.valueOf(extractUserSelection(request)); executionContext.put(Constants.REQ_SELECTED_LOGIN_METHOD_PARAMETER, selection); executionContext.remove(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED); + executionContext.remove(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON); transitionToNextTask(executionContext, selection); } catch (final Exception e) { log.error("Parsing selected login method FAILED.", e); executionContext.put(Constants.CONTEXT_FLAG_ADVANCED_MATCHING_FAILED, true); - executionContext.put(Constants.TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK, true); + executionContext.put(Constants.TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK, true); } } -- cgit v1.2.3 From a16e5ba2c6030788524e6dc49f6bb5ae4f0cabe0 Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Tue, 8 Feb 2022 17:17:52 +0100 Subject: chore(core): add log message and add empty lines for better reading --- .../eidas/specific/modules/auth/eidas/v2/tasks/InitialSearchTask.java | 2 ++ .../auth/eidas/v2/tasks/ReceiveAustrianResidenceGuiResponseTask.java | 1 + 2 files changed, 3 insertions(+) (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java') 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 index 9564a8fc..3a775837 100644 --- 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 @@ -167,11 +167,13 @@ public class InitialSearchTask extends AbstractAuthServletTask { if (registerData.getResultCount() == 0) { log.debug("Matching step: 'step8RegisterSearchWithMds' has no result. Forward to create new ERnP entry ... "); executionContext.put(TRANSITION_TO_CREATE_NEW_ERNP_ENTRY_TASK, true); + } else { log.debug("Matching step: 'step8RegisterSearchWithMds' has #{} results. " + "Forward to GUI based matching steps ... ", registerData.getResultCount()); MatchingTaskUtils.storeIntermediateMatchingResult(pendingReq, registerData); executionContext.put(TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK, true); + } } 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 67addf94..08d2bfa1 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 @@ -190,6 +190,7 @@ public class ReceiveAustrianResidenceGuiResponseTask extends AbstractLocaleAuthS } } catch (WorkflowException e) { + log.warn("Kitt operation after successful residence matching FAILED.", e); throw new TaskExecutionException(pendingReq, "Search failed", new ManualFixNecessaryException(eidasData)); } -- cgit v1.2.3 From 0fb02a267d231ce130f7ea419cade9a0cc79bb6e Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Tue, 8 Feb 2022 17:35:24 +0100 Subject: fix(matching): update wrong error-reason and remove an unused method parameter --- .../v2/tasks/ReceiveAustrianResidenceGuiResponseTask.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java') 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 08d2bfa1..89a3f350 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 @@ -117,11 +117,11 @@ public class ReceiveAustrianResidenceGuiResponseTask extends AbstractLocaleAuthS 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 ... "); + 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); + + executionContext.put(CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON, MSG_PROP_21); + executionContext.put(CONTEXT_FLAG_ADVANCED_MATCHING_FAILED, true); return; } @@ -145,7 +145,7 @@ public class ReceiveAustrianResidenceGuiResponseTask extends AbstractLocaleAuthS } else { log.debug("Find single match by using residence information. Starting data validation ... "); - compareSearchResultWithInitialData(executionContext, residencyResult, eidasData); + compareSearchResultWithInitialData(residencyResult, eidasData); } @@ -167,8 +167,7 @@ public class ReceiveAustrianResidenceGuiResponseTask extends AbstractLocaleAuthS && StringUtils.isEmpty(input.getVillage()); } - private void compareSearchResultWithInitialData(ExecutionContext executionContext, - RegisterStatusResults residencyResult, SimpleEidasData eidasData) + private void compareSearchResultWithInitialData(RegisterStatusResults residencyResult, SimpleEidasData eidasData) throws TaskExecutionException, EaafStorageException { try { if (!eidasData.equalsRegisterData(residencyResult.getResult())) { -- cgit v1.2.3 From 474fc2b1c7645672e3ed60039177c3c04ba85dc9 Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Tue, 8 Feb 2022 17:41:14 +0100 Subject: chore(core): fix some code-quality and code-style issues --- .../specific/modules/auth/eidas/v2/clients/zmr/ZmrSoapClient.java | 2 +- .../modules/auth/eidas/v2/service/RegisterSearchService.java | 6 ++++-- .../eidas/v2/tasks/ReceiveMobilePhoneSignatureResponseTask.java | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java') 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 11c7cffe..f24c75eb 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 @@ -731,7 +731,7 @@ public class ZmrSoapClient extends AbstractSoapClient implements IZmrClient { private PostAdresseTyp buildSearchAddress(AdresssucheOutput address) { PostAdresseTyp postAdresse = new PostAdresseTyp(); - if (StringUtils.isNotBlank(address.getPostleitzahl())){ + if (StringUtils.isNotBlank(address.getPostleitzahl())) { postAdresse.setPostleitzahl(address.getPostleitzahl()); } if (StringUtils.isNotBlank(address.getMunicipality())) { 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 d95aadda..c3bf4309 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 @@ -174,11 +174,13 @@ public class RegisterSearchService { public RegisterStatusResults searchWithResidence(RegisterOperationStatus operationStatus, SimpleEidasData eidasData, AdresssucheOutput address) throws WorkflowException { try { - final ZmrRegisterResult resultsZmr = zmrClient.searchWithResidenceData( + 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 + /* 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); diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveMobilePhoneSignatureResponseTask.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveMobilePhoneSignatureResponseTask.java index 2d28709b..514e38ba 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveMobilePhoneSignatureResponseTask.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/ReceiveMobilePhoneSignatureResponseTask.java @@ -156,7 +156,7 @@ public class ReceiveMobilePhoneSignatureResponseTask extends AbstractAuthServlet Pair processedMsg = validateAssertion((PvpSProfileResponse) inboundMessage); if (processedMsg.getSecond()) { // forward to next matching step in case of ID Autria authentication was stopped by user - executionContext.put(Constants.TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK, true); + executionContext.put(TRANSITION_TO_GENERATE_OTHER_LOGIN_METHOD_GUI_TASK, true); executionContext.put(CONTEXT_FLAG_ADVANCED_MATCHING_FAILED_REASON, MSG_PROP_23); executionContext.put(CONTEXT_FLAG_ADVANCED_MATCHING_FAILED, true); return; -- cgit v1.2.3 From e4ccd3df84e7ea509e66f2f832719529fe408839 Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Wed, 9 Feb 2022 08:34:26 +0100 Subject: feature(zmr): add MDS attributes as 'eIdAS-Documents' too ZMR does not allow MDS update on regular places. Therefore, we add it as 'eIDAS-Documents' for later usage. --- .../eidas/specific/modules/auth/eidas/v2/Constants.java | 8 +++++++- .../modules/auth/eidas/v2/clients/zmr/ZmrSoapClient.java | 12 ++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java') 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 e642c5ec..272d79c4 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 @@ -268,7 +268,13 @@ public class Constants { public static final String eIDAS_ATTRURN_PREFIX_NATURAL = eIDAS_ATTRURN_PREFIX + "naturalperson/"; public static final String eIDAS_ATTRURN_PERSONALIDENTIFIER = - eIDAS_ATTRURN_PREFIX_NATURAL + eIDAS_ATTR_PERSONALIDENTIFIER; + eIDAS_ATTRURN_PREFIX_NATURAL + eIDAS_ATTR_PERSONALIDENTIFIER; + public static final String eIDAS_ATTRURN_CURRENTGIVENNAME = + eIDAS_ATTRURN_PREFIX_NATURAL + "CurrentGivenName"; + public static final String eIDAS_ATTRURN_CURRENTFAMILYNAME = + eIDAS_ATTRURN_PREFIX_NATURAL + "CurrentFamilyName"; + public static final String eIDAS_ATTRURN_DATEOFBIRTH = + eIDAS_ATTRURN_PREFIX_NATURAL + eIDAS_ATTR_DATEOFBIRTH; public static final String eIDAS_ATTRURN_PLACEOFBIRTH = eIDAS_ATTRURN_PREFIX_NATURAL + eIDAS_ATTR_PLACEOFBIRTH; public static final String eIDAS_ATTRURN_BIRTHNAME = 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 f24c75eb..8dbd0632 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 @@ -264,6 +264,10 @@ public class ZmrSoapClient extends AbstractSoapClient implements IZmrClient { Collection eidasDocumentToAdd = selectEidasDocumentsToAdd(zmrPersonToKitt, eidData); + /*TODO: Is there a requirement to change 'eIDAS-Documents'? + * We add MDS information as 'eIDAS-Documents' too. Maybe, we should update that in a later version. + */ + if (eidasDocumentToAdd.isEmpty()) { log.info("Find no eIDAS document for update during: {}. Nothing todo on ZMR side", PROCESS_KITT_GENERAL); @@ -766,6 +770,14 @@ public class ZmrSoapClient extends AbstractSoapClient implements IZmrClient { Constants.eIDAS_ATTRURN_PLACEOFBIRTH, eidData.getPlaceOfBirth(), false); addEidasDocumentIfNotAvailable(result, zmrPersonToKitt, eidData.getCitizenCountryCode(), Constants.eIDAS_ATTRURN_BIRTHNAME, eidData.getBirthName(), false); + + // add MDS attributes as 'eIDAS-Documents' too, because ZMR does not allow a MDS update on regular places. + addEidasDocumentIfNotAvailable(result, zmrPersonToKitt, eidData.getCitizenCountryCode(), + Constants.eIDAS_ATTRURN_CURRENTGIVENNAME, eidData.getGivenName(), false); + addEidasDocumentIfNotAvailable(result, zmrPersonToKitt, eidData.getCitizenCountryCode(), + Constants.eIDAS_ATTRURN_CURRENTFAMILYNAME, eidData.getFamilyName(), false); + addEidasDocumentIfNotAvailable(result, zmrPersonToKitt, eidData.getCitizenCountryCode(), + Constants.eIDAS_ATTRURN_DATEOFBIRTH, eidData.getDateOfBirth(), false); return result; -- cgit v1.2.3 From be411ba3e668eb86f87c0d8a021989d97b63c7a3 Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Wed, 2 Mar 2022 13:10:39 +0100 Subject: chore(ernp): update ERnP REST API to v1.5.1 --- .../auth/eidas/v2/clients/ernp/ErnpRestClient.java | 25 ++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java') diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java index 3822da01..45a4010b 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java @@ -62,6 +62,7 @@ import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.ErnpRestCommun import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.WorkflowException; import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.VersionHolder; import at.gv.bmi.namespace.zmr_su.base._20040201_.ServiceFault; +import at.gv.bmi.namespace.zmr_su.zmr._20040201.EidasSuchdatenType; import at.gv.bmi.namespace.zmr_su.zmr._20040201.PersonSuchenRequest; import at.gv.egiz.eaaf.core.api.idp.IConfiguration; import at.gv.egiz.eaaf.core.exceptions.EaafAuthenticationException; @@ -142,7 +143,7 @@ public class ErnpRestClient implements IErnpClient { personSuchen.setSuchoptionen(generateSearchParameters()); personSuchen.setBegruendung(PROCESS_SEARCH_PERSONAL_IDENTIFIER); final Suchdaten searchInfos = new Suchdaten(); - searchInfos.setEidas(eidasInfos); + searchInfos.setEidas(Arrays.asList(eidasInfos)); personSuchen.setSuchdaten(searchInfos); // request ERnP @@ -429,9 +430,11 @@ public class ErnpRestClient implements IErnpClient { searchInfos.setVorname(personSearchDao.getNatuerlichePerson().getPersonenName().getVorname()); searchInfos.setGeburtsdatum(buildErnpBirthday(personSearchDao.getNatuerlichePerson().getGeburtsdatum())); - //TODO: search eIDAS has to be a LIST!!!!!! - SuchEidas eidasInfos = new SuchEidas(); - searchInfos.setEidas(eidasInfos); + // map all eIDAS documents into ERnP format + searchInfos.setEidas(personSearchDao.getEidasSuchdaten().stream() + .map(el -> buildErnpEidasDocument(el)) + .collect(Collectors.toList())); + return searchInfos; } @@ -668,6 +671,20 @@ public class ErnpRestClient implements IErnpClient { } + /** + * Map eIDAS search-data from ZMR model into ERnP model. + * + * @param daten eIDAS document as ZMR model + * @return the same eIDAS document as an ERnP model + */ + private SuchEidas buildErnpEidasDocument(EidasSuchdatenType daten) { + return new SuchEidas() + .art(daten.getEidasArt()) + .wert(daten.getEidasWert()) + .staatscode2(daten.getStaatscode2()); + } + + /** * Build AT specific Date String 'yyyy-MM-dd' from ERnP birthday representation. * -- cgit v1.2.3 From df894a4076abbcb4357509eb453f4c447a8856d5 Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Thu, 3 Mar 2022 11:42:53 +0100 Subject: chore(ernp): optimize ERnP client based on results from integration test --- .../auth/eidas/v2/clients/ernp/ErnpRestClient.java | 74 +++++++++++----------- 1 file changed, 38 insertions(+), 36 deletions(-) (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java') diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java index 45a4010b..66fec9dc 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java @@ -17,6 +17,7 @@ import java.util.stream.Collectors; import javax.annotation.Nonnull; import javax.annotation.PostConstruct; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.http.client.HttpClient; import org.springframework.beans.factory.annotation.Autowired; @@ -34,6 +35,8 @@ import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestTemplate; import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.RegisterResult; @@ -43,6 +46,7 @@ import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.api.DefaultApi; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.invoker.ApiClient; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.Aendern; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.AendernResponse; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.Anlegen; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.AnlegenResponse; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.Eidas; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ernp.model.PartialDate; @@ -206,37 +210,39 @@ public class ErnpRestClient implements IErnpClient { throw new EidasSAuthenticationException(ERROR_MATCHING_99, new Object[] { e.getMessage() }, e); } } - + @Override public ErnpRegisterResult searchCountrySpecific(PersonSuchenRequest personSearchDao, String citizenCountryCode) throws EidasSAuthenticationException { - try { + String countrySearchMsg = MessageFormat.format(PROCESS_SEARCH_COUNTRY_SPECIFIC, citizenCountryCode); + + try { // build generic request metadata final GenericRequestParams generic = buildGenericRequestParameters("stepCC"); // build search request final PersonSuchen personSuchen = new PersonSuchen(); personSuchen.setSuchoptionen(generateSearchParameters()); - personSuchen.setBegruendung(PROCESS_SEARCH_COUNTRY_SPECIFIC); + personSuchen.setBegruendung(countrySearchMsg); personSuchen.setSuchdaten(mapCountrySpecificSearchData(personSearchDao)); // request ERnP - log.trace("Requesting ERnP for '{}' operation", PROCESS_SEARCH_COUNTRY_SPECIFIC); + log.trace("Requesting ERnP for '{}' operation", countrySearchMsg); final SuchenResponse resp = ernpClient.suchen(generic.getClientBehkz(), generic.clientName, generic.getClientRequestTime(), generic.getClientRequestId(), personSuchen); // parse ZMR response - return processErnpResponse(resp, citizenCountryCode, false, PROCESS_SEARCH_COUNTRY_SPECIFIC); + return processErnpResponse(resp, citizenCountryCode, false, countrySearchMsg); } catch (RestClientException e) { - log.warn(LOGMSG_ERNP_ERROR, PROCESS_SEARCH_COUNTRY_SPECIFIC, e.getMessage()); + log.warn(LOGMSG_ERNP_ERROR, countrySearchMsg, e.getMessage()); throw new EidasSAuthenticationException(ERROR_MATCHING_11, new Object[] { e.getMessage() }, e); } catch (final EidasSAuthenticationException e) { throw e; } catch (final Exception e) { - log.warn(LOGMSG_ERNP_RESP_PROCESS, PROCESS_SEARCH_COUNTRY_SPECIFIC, e.getMessage()); + log.warn(LOGMSG_ERNP_RESP_PROCESS, countrySearchMsg, e.getMessage()); throw new EidasSAuthenticationException(ERROR_MATCHING_99, new Object[] { e.getMessage() }, e); } @@ -268,14 +274,14 @@ public class ErnpRestClient implements IErnpClient { } } catch (RestClientException e) { - log.warn(LOGMSG_ERNP_ERROR, PROCESS_SEARCH_COUNTRY_SPECIFIC, e.getMessage()); + log.warn(LOGMSG_ERNP_ERROR, PROCESS_KITT_GENERAL, e.getMessage()); throw new EidasSAuthenticationException(ERROR_MATCHING_11, new Object[] { e.getMessage() }, e); } catch (final EidasSAuthenticationException e) { throw e; } catch (final Exception e) { - log.warn(LOGMSG_ERNP_RESP_PROCESS, PROCESS_SEARCH_COUNTRY_SPECIFIC, e.getMessage()); + log.warn(LOGMSG_ERNP_RESP_PROCESS, PROCESS_KITT_GENERAL, e.getMessage()); throw new EidasSAuthenticationException(ERROR_MATCHING_99, new Object[] { e.getMessage() }, e); } @@ -454,7 +460,12 @@ public class ErnpRestClient implements IErnpClient { ernpReq.setVersion(ernpPersonToKitt.getVersion()); // add new eIDAS attributes - eidasDocumentToAdd.stream().forEach(el -> ernpReq.getAnlegen().addEidasItem(el)); + if (!eidasDocumentToAdd.isEmpty()) { + log.debug("Find eIDAS Documents to update. Injection update entries into ERnP request ... "); + ernpReq.setAnlegen(new Anlegen()); + eidasDocumentToAdd.stream().forEach(el -> ernpReq.getAnlegen().addEidasItem(el)); + + } // update MDS if required if (mdsToUpdate != null) { @@ -545,10 +556,11 @@ public class ErnpRestClient implements IErnpClient { // build search request final Suchdaten searchInfos = new Suchdaten(); + searchInfos.setBpkZp(registerResult.getBpk()); searchInfos.setFamilienname(registerResult.getFamilyName()); searchInfos.setVorname(registerResult.getGivenName()); - searchInfos.setGeburtsdatum(buildErnpBirthday(registerResult.getDateOfBirth())); - + searchInfos.setGeburtsdatum(buildErnpBirthday(registerResult.getDateOfBirth())); + final PersonSuchen personSuchen = new PersonSuchen(); personSuchen.setSuchoptionen(generateSearchParameters()); personSuchen.setBegruendung(PROCESS_KITT_IDENITIES_GET); @@ -600,28 +612,16 @@ public class ErnpRestClient implements IErnpClient { private SimpleEidasData selectMdsInformationToUpdate(Person ernpPersonToKitt, SimpleEidasData eidData) { PersonendatenErgebnis person = ernpPersonToKitt.getPersonendaten(); - SimpleEidasDataBuilder builder = SimpleEidasData.builder(); + SimpleEidasDataBuilder builder = SimpleEidasData.builder() + .givenName(eidData.getGivenName()) + .familyName(eidData.getFamilyName()) + .dateOfBirth(eidData.getDateOfBirth()); - boolean findMismatch = false; - if (!person.getVorname().equals(eidData.getGivenName())) { - findMismatch = true; - builder.givenName(eidData.getGivenName()); - - } - - if (!person.getFamilienname().equals(eidData.getFamilyName())) { - findMismatch = true; - builder.familyName(eidData.getFamilyName()); - - } - - if (!getTextualBirthday(person.getGeburtsdatum()).equals(eidData.getDateOfBirth())) { - findMismatch = true; - builder.dateOfBirth(eidData.getDateOfBirth()); - - } + boolean findMatch = person.getVorname().equals(eidData.getGivenName()) + && person.getFamilienname().equals(eidData.getFamilyName()) + && getTextualBirthday(person.getGeburtsdatum()).equals(eidData.getDateOfBirth()); + return findMatch ? null : builder.build(); - return findMismatch ? builder.build() : null; } private Aendern generateMdsChangeRequest(Person ernpPersonToKitt, SimpleEidasData mdsToUpdate) { @@ -771,8 +771,10 @@ public class ErnpRestClient implements IErnpClient { private HttpMessageConverter buildCustomJacksonObjectMapper() { final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); converter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON)); - converter.getObjectMapper() - .setSerializationInclusion(Include.NON_NULL); + converter.getObjectMapper().setSerializationInclusion(Include.NON_NULL); + + converter.getObjectMapper().registerModule(new JavaTimeModule()); + converter.getObjectMapper().configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); return converter; } @@ -793,9 +795,9 @@ public class ErnpRestClient implements IErnpClient { // TODO: opimize errorHandling based on response info's from real ERnP List serverId = response.getHeaders().getOrEmpty(ERNP_RESPONSE_HEADER_SERVER_ID); - log.warn("Receive http-error: {} from ERnP with serverTransactionId", + log.warn("Receive http-error: {} from ERnP with serverTransactionId {}", response.getRawStatusCode(), serverId.isEmpty() ? "'not set'" : serverId.get(0)); - + log.warn(" Full ERnP response-body: {}", IOUtils.toString(response.getBody(), "UTF-8")); throw new ErnpRestCommunicationException(response.getRawStatusCode()); } -- cgit v1.2.3 From 0020b5d6084501b6ee6b6b07fdc40ab47dc30dc7 Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Thu, 3 Mar 2022 11:43:59 +0100 Subject: test(ernp): add all ERnP integration tests into test that operates in real test ERnP --- .../eidas/specific/modules/auth/eidas/v2/dao/SimpleEidasData.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java') 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 index f9301505..094b2a9f 100644 --- 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 @@ -32,7 +32,7 @@ import lombok.Builder; import lombok.Data; @Data -@Builder +@Builder(toBuilder=true) public class SimpleEidasData implements Serializable { private static final long serialVersionUID = 2848914124372968418L; -- cgit v1.2.3 From 7b2c31e14aa5f4823d970ec6ebd3e134a280f442 Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Thu, 3 Mar 2022 15:06:28 +0100 Subject: fix(ernp): fix some problems in ERnP client that we found during tests --- .../auth/eidas/v2/clients/ernp/ErnpRestClient.java | 78 +++++++++++----------- 1 file changed, 38 insertions(+), 40 deletions(-) (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java') diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java index 66fec9dc..4c4e3d87 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/ernp/ErnpRestClient.java @@ -232,7 +232,7 @@ public class ErnpRestClient implements IErnpClient { generic.getClientRequestTime(), generic.getClientRequestId(), personSuchen); // parse ZMR response - return processErnpResponse(resp, citizenCountryCode, false, countrySearchMsg); + return processErnpResponse(resp, citizenCountryCode, true, countrySearchMsg); } catch (RestClientException e) { log.warn(LOGMSG_ERNP_ERROR, countrySearchMsg, e.getMessage()); @@ -289,31 +289,41 @@ public class ErnpRestClient implements IErnpClient { @Override public ErnpRegisterResult add(SimpleEidasData eidData) throws EidasSAuthenticationException { - // build generic request metadata - final GenericRequestParams generic = buildGenericRequestParameters("stepNew"); - - // build update request - PersonAnlegen ernpReq = new PersonAnlegen(); - ernpReq.setBegruendung(PROCESS_ADD_IDENITY); - - // inject person data - Personendaten person = new Personendaten(); - person.setFamilienname(eidData.getFamilyName()); - person.setVorname(eidData.getGivenName()); - person.setGeburtsdatum(buildErnpBirthday(eidData.getDateOfBirth())); - ernpReq.setPersonendaten(person); - - buildNewEidasDocumens(ernpReq, eidData); - - // request ERnP - log.trace("Requesting ERnP for '{}' operation", PROCESS_ADD_IDENITY); - AnlegenResponse ernpResp = ernpClient.anlegen(generic.getClientBehkz(), generic.clientName, - generic.getClientRequestTime(), generic.getClientRequestId(), ernpReq); - log.trace("Receive response from ERnP for '{}' operation", PROCESS_ADD_IDENITY); - - return new ErnpRegisterResult(Arrays.asList( - mapErnpResponseToRegisterResult(ernpResp.getPerson(), eidData.getCitizenCountryCode()))); + try { + // build generic request metadata + final GenericRequestParams generic = buildGenericRequestParameters("stepNew"); + + // build update request + PersonAnlegen ernpReq = new PersonAnlegen(); + ernpReq.setBegruendung(PROCESS_ADD_IDENITY); + + // inject person data + Personendaten person = new Personendaten(); + person.setFamilienname(eidData.getFamilyName()); + person.setVorname(eidData.getGivenName()); + person.setGeburtsdatum(buildErnpBirthday(eidData.getDateOfBirth())); + ernpReq.setPersonendaten(person); + + buildNewEidasDocumens(ernpReq, eidData); + + // request ERnP + log.trace("Requesting ERnP for '{}' operation", PROCESS_ADD_IDENITY); + AnlegenResponse ernpResp = ernpClient.anlegen(generic.getClientBehkz(), generic.clientName, + generic.getClientRequestTime(), generic.getClientRequestId(), ernpReq); + log.trace("Receive response from ERnP for '{}' operation", PROCESS_ADD_IDENITY); + + return new ErnpRegisterResult(Arrays.asList( + mapErnpResponseToRegisterResult(ernpResp.getPerson(), eidData.getCitizenCountryCode()))); + } catch (RestClientException e) { + log.warn(LOGMSG_ERNP_ERROR, PROCESS_ADD_IDENITY, e.getMessage()); + throw new EidasSAuthenticationException(ERROR_MATCHING_11, new Object[] { e.getMessage() }, e); + + } catch (final Exception e) { + log.warn(LOGMSG_ERNP_RESP_PROCESS, PROCESS_ADD_IDENITY, e.getMessage()); + throw new EidasSAuthenticationException(ERROR_MATCHING_99, new Object[] { e.getMessage() }, e); + + } } @Override @@ -629,21 +639,9 @@ public class ErnpRestClient implements IErnpClient { Personendaten person = new Personendaten(); person.setEntityId(ernpPersonToKitt.getPersonendaten().getEntityId()); el.setPersonendaten(person); - - if (StringUtils.isNotEmpty(mdsToUpdate.getFamilyName())) { - person.setFamilienname(mdsToUpdate.getFamilyName()); - - } - - if (StringUtils.isNotEmpty(mdsToUpdate.getGivenName())) { - person.setVorname(mdsToUpdate.getGivenName()); - - } - - if (StringUtils.isNotEmpty(mdsToUpdate.getDateOfBirth())) { - person.setGeburtsdatum(buildErnpBirthday(mdsToUpdate.getDateOfBirth())); - - } + person.setFamilienname(mdsToUpdate.getFamilyName()); + person.setVorname(mdsToUpdate.getGivenName()); + person.setGeburtsdatum(buildErnpBirthday(mdsToUpdate.getDateOfBirth())); return el; } -- cgit v1.2.3 From c3bba97c9093eca911f6edd9cbb9742d5f32583c Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Thu, 3 Mar 2022 15:40:39 +0100 Subject: fix(core): solve code-style issue --- .../eidas/specific/modules/auth/eidas/v2/dao/SimpleEidasData.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'eidas_modules/authmodule-eIDAS-v2/src/main/java') 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 index 094b2a9f..aca5025f 100644 --- 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 @@ -32,7 +32,7 @@ import lombok.Builder; import lombok.Data; @Data -@Builder(toBuilder=true) +@Builder(toBuilder = true) public class SimpleEidasData implements Serializable { private static final long serialVersionUID = 2848914124372968418L; -- cgit v1.2.3