From 4b7abac5a3090b924c3c2a6c6bc0c2da8cf05bdd Mon Sep 17 00:00:00 2001 From: Alexander Marsalek Date: Fri, 4 Dec 2020 12:59:42 +0100 Subject: added dummy ZMR & ERnB client --- .../auth/eidas/v2/dao/InitialSearchResult.java | 12 -- .../eidas/v2/dao/MergedRegisterSearchResult.java | 16 ++ .../modules/auth/eidas/v2/dao/RegisterResult.java | 59 +++++++ .../modules/auth/eidas/v2/dao/SimpleEidasData.java | 52 ++++++ .../auth/eidas/v2/ernb/DummyErnbClient.java | 49 ++++++ .../modules/auth/eidas/v2/ernb/IErnbClient.java | 12 ++ .../v2/exception/ManualFixNecessaryException.java | 6 +- .../eidas/v2/handler/AbstractEidProcessor.java | 115 +++---------- .../ICountrySpecificDetailSearchProcessor.java | 6 +- .../auth/eidas/v2/tasks/InitialSearchTask.java | 189 +++++++++++++++------ .../auth/eidas/v2/utils/EidasResponseUtils.java | 168 ++++++++++++++++++ .../modules/auth/eidas/v2/zmr/DummyZmrClient.java | 49 ++++++ .../modules/auth/eidas/v2/zmr/IZmrClient.java | 12 ++ .../src/main/resources/eidas_v2_auth.beans.xml | 6 + 14 files changed, 584 insertions(+), 167 deletions(-) delete mode 100644 eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/InitialSearchResult.java create mode 100644 eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/MergedRegisterSearchResult.java create mode 100644 eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/RegisterResult.java create mode 100644 eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/SimpleEidasData.java create mode 100644 eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/ernb/DummyErnbClient.java create mode 100644 eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/ernb/IErnbClient.java create mode 100644 eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/zmr/DummyZmrClient.java create mode 100644 eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/zmr/IZmrClient.java (limited to 'eidas_modules/authmodule-eIDAS-v2') diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/InitialSearchResult.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/InitialSearchResult.java deleted file mode 100644 index 8fe69414..00000000 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/InitialSearchResult.java +++ /dev/null @@ -1,12 +0,0 @@ -package at.asitplus.eidas.specific.modules.auth.eidas.v2.dao; - -public class InitialSearchResult { - - int resultsZmr; - int resultsErnb; - - public int getResultCount() { - return resultsErnb + resultsZmr; - } - -} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/MergedRegisterSearchResult.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/MergedRegisterSearchResult.java new file mode 100644 index 00000000..bc5b358d --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/MergedRegisterSearchResult.java @@ -0,0 +1,16 @@ +package at.asitplus.eidas.specific.modules.auth.eidas.v2.dao; + +import lombok.Data; + +import java.util.ArrayList; + +@Data public class MergedRegisterSearchResult { + + ArrayList resultsZmr = new ArrayList<>(); + ArrayList resultsErnb = new ArrayList<>(); + + public int getResultCount() { + return resultsZmr.size() + resultsErnb.size(); + } + +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/RegisterResult.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/RegisterResult.java new file mode 100644 index 00000000..9509e7de --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/RegisterResult.java @@ -0,0 +1,59 @@ +package at.asitplus.eidas.specific.modules.auth.eidas.v2.dao; + +import at.gv.e_government.reference.namespace.persondata._20020228.PostalAddressType; +import lombok.Data; + +@Data public class RegisterResult { + + // MDS + private String pseudonym = null; + private String givenName = null; + private String familyName = null; + private String dateOfBirth = null; + + // additional attributes + private String placeOfBirth = null; + private String birthName = null; + private String taxNumber = null; + private PostalAddressType address = null; + + /** + * Register search result. + * @param pseudonym The pseudonym + * @param givenName The givenName + * @param familyName The familyName + * @param dateOfBirth The dateOfBirth + * @param placeOfBirth The placeOfBirth + */ + public RegisterResult(String pseudonym, String givenName, String familyName, String dateOfBirth, + String placeOfBirth) { + this.pseudonym = pseudonym; + this.givenName = givenName; + this.familyName = familyName; + this.dateOfBirth = dateOfBirth; + this.placeOfBirth = placeOfBirth; + } + + /** + * Register search result. + * @param pseudonym The pseudonym + * @param givenName The givenName + * @param familyName The familyName + * @param dateOfBirth The dateOfBirth + * @param placeOfBirth The placeOfBirth + * @param birthName The birthName + * @param taxNumber The taxNumber + * @param address The address + */ + public RegisterResult(String pseudonym, String givenName, String familyName, String dateOfBirth, + String placeOfBirth, String birthName, String taxNumber, PostalAddressType address) { + this.pseudonym = pseudonym; + this.givenName = givenName; + this.familyName = familyName; + this.dateOfBirth = dateOfBirth; + this.placeOfBirth = placeOfBirth; + this.birthName = birthName; + this.taxNumber = taxNumber; + this.address = address; + } +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/SimpleEidasData.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/SimpleEidasData.java new file mode 100644 index 00000000..0b116bfb --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/SimpleEidasData.java @@ -0,0 +1,52 @@ +/* + * Copyright 2018 A-SIT Plus GmbH + * AT-specific eIDAS Connector has been developed in a cooperation between EGIZ, + * A-SIT Plus GmbH, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "License"); + * You may not use this work except in compliance with the License. + * You may obtain a copy of the License at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + +package at.asitplus.eidas.specific.modules.auth.eidas.v2.dao; + +import at.gv.e_government.reference.namespace.persondata._20020228.PostalAddressType; +import lombok.Data; +import org.joda.time.DateTime; + +import java.text.SimpleDateFormat; + +@Data public class SimpleEidasData { + + private String citizenCountryCode = null; + + // MDS + private String pseudonym = null; + private String givenName = null; + private String familyName = null; + private DateTime dateOfBirth = null; + + // additional attributes + private String placeOfBirth = null; + private String birthName = null; + private PostalAddressType address = null; + private String taxNumber; + + public String getFormatedDateOfBirth() { + return new SimpleDateFormat("yyyy-MM-dd").format(dateOfBirth.toDate()); + } + +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/ernb/DummyErnbClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/ernb/DummyErnbClient.java new file mode 100644 index 00000000..8b2379bf --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/ernb/DummyErnbClient.java @@ -0,0 +1,49 @@ +package at.asitplus.eidas.specific.modules.auth.eidas.v2.ernb; + +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.RegisterResult; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; + +@Service("ErnbClientForeIDAS") +public class DummyErnbClient implements IErnbClient { + + @Override + public ArrayList searchWithPersonIdentifer(String personIdentifer) { + switch (personIdentifer) { + case "a12345": + case "a12345-": + return result1(); + case "a123456": + return result2(); + default: + return resultEmpty(); + } + } + + @Override + public ArrayList searchWithMds(String givenName, String familyName, String dateOfBirth) { + return resultEmpty();//TODO will I only receive matches where all three values match perfectly? + } + + private ArrayList resultEmpty() { + return new ArrayList();//Nobody found + } + + private ArrayList result1() { + ArrayList results = new ArrayList<>(); + RegisterResult result1 = new RegisterResult("a12345", "Tom", "Mustermann", "1950-01-01", "Wien"); + results.add(result1); + RegisterResult result2 = new RegisterResult("a12345-", "Tom", "Mustermann", "1950-01-01", "Wien"); + results.add(result2); + return results; + } + + private ArrayList result2() { + ArrayList results = new ArrayList<>(); + RegisterResult result = new RegisterResult("a123456", "Max", "Mustermann", "2000-01-01", "Wien"); + results.add(result); + return results; + } + +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/ernb/IErnbClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/ernb/IErnbClient.java new file mode 100644 index 00000000..4873b939 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/ernb/IErnbClient.java @@ -0,0 +1,12 @@ +package at.asitplus.eidas.specific.modules.auth.eidas.v2.ernb; + +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.RegisterResult; + +import java.util.ArrayList; + +public interface IErnbClient { + + ArrayList searchWithPersonIdentifer(String personIdentifer); + + ArrayList searchWithMds(String givenName, String familyName, String dateOfBirth); +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/ManualFixNecessaryException.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/ManualFixNecessaryException.java index f3916ed6..c22e8135 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/ManualFixNecessaryException.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/ManualFixNecessaryException.java @@ -23,18 +23,16 @@ package at.asitplus.eidas.specific.modules.auth.eidas.v2.exception; -import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ErnbEidData; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData; public class ManualFixNecessaryException extends EidasSAuthenticationException { private static final long serialVersionUID = 1L; public ManualFixNecessaryException(String personIdentifier) { super("eidas.00", new Object[] { personIdentifier });//TODO "eidas.00" - } - public ManualFixNecessaryException(ErnbEidData eidData) { - + public ManualFixNecessaryException(SimpleEidasData eidData) { super("eidas.00", new Object[] { eidData.getPseudonym() });//TODO "eidas.00" => what info to pass??? } } diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/AbstractEidProcessor.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/AbstractEidProcessor.java index 42dbfeac..3691ee47 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/AbstractEidProcessor.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/AbstractEidProcessor.java @@ -23,6 +23,7 @@ package at.asitplus.eidas.specific.modules.auth.eidas.v2.handler; + import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -52,7 +53,6 @@ import eu.eidas.auth.commons.attribute.AttributeDefinition; import eu.eidas.auth.commons.attribute.ImmutableAttributeMap; import eu.eidas.auth.commons.light.impl.LightRequest.Builder; import eu.eidas.auth.commons.protocol.eidas.SpType; -import eu.eidas.auth.commons.protocol.eidas.impl.PostalAddress; public abstract class AbstractEidProcessor implements INationalEidProcessor { private static final Logger log = LoggerFactory.getLogger(AbstractEidProcessor.class); @@ -68,7 +68,6 @@ public abstract class AbstractEidProcessor implements INationalEidProcessor { buildLevelOfAssurance(pendingReq.getServiceProviderConfiguration(), authnRequestBuilder); buildProviderNameAttribute(pendingReq, authnRequestBuilder); buildRequestedAttributes(authnRequestBuilder); - } @@ -94,13 +93,12 @@ public abstract class AbstractEidProcessor implements INationalEidProcessor { result.setAddress(processAddress(eidasAttrMap.get(Constants.eIDAS_ATTR_CURRENTADDRESS))); return result; - } - + /** * Get a Map of country-specific requested attributes. - * + * * @return */ @NonNull @@ -108,7 +106,7 @@ public abstract class AbstractEidProcessor implements INationalEidProcessor { /** * Post-Process the eIDAS CurrentAddress attribute. - * + * * @param currentAddressObj eIDAS current address information * @return current address or null if no attribute is available * @throws EidPostProcessingException if post-processing fails @@ -116,34 +114,12 @@ public abstract class AbstractEidProcessor implements INationalEidProcessor { */ protected PostalAddressType processAddress(Object currentAddressObj) throws EidPostProcessingException, EidasAttributeException { - - if (currentAddressObj != null) { - if (currentAddressObj instanceof PostalAddress) { - final PostalAddressType result = new PostalAddressType(); - result.setPostalCode(((PostalAddress) currentAddressObj).getPostCode()); - result.setMunicipality(((PostalAddress) currentAddressObj).getPostName()); - - // TODO: add more mappings - - return result; - - } else { - log.warn("eIDAS attr: " + Constants.eIDAS_ATTR_CURRENTADDRESS + " is of WRONG type"); - throw new EidasAttributeException(Constants.eIDAS_ATTR_CURRENTADDRESS); - - } - - } else { - log.debug("NO '" + Constants.eIDAS_ATTR_CURRENTADDRESS + "' attribute. Post-Processing skipped ... "); - } - - return null; - + return EidasResponseUtils.processAddress(currentAddressObj); } /** * Post-Process the eIDAS BirthName attribute. - * + * * @param birthNameObj eIDAS birthname information * @return birthName or null if no attribute is available * @throws EidPostProcessingException if post-processing fails @@ -151,27 +127,12 @@ public abstract class AbstractEidProcessor implements INationalEidProcessor { */ protected String processBirthName(Object birthNameObj) throws EidPostProcessingException, EidasAttributeException { - if (birthNameObj != null) { - if (birthNameObj instanceof String) { - return (String) birthNameObj; - - } else { - log.warn("eIDAS attr: " + Constants.eIDAS_ATTR_BIRTHNAME + " is of WRONG type"); - throw new EidasAttributeException(Constants.eIDAS_ATTR_BIRTHNAME); - - } - - } else { - log.debug("NO '" + Constants.eIDAS_ATTR_BIRTHNAME + "' attribute. Post-Processing skipped ... "); - } - - return null; - + return EidasResponseUtils.processBirthName(birthNameObj); } /** * Post-Process the eIDAS PlaceOfBirth attribute. - * + * * @param placeOfBirthObj eIDAS Place-of-Birth information * @return place of Birth or null if no attribute is available * @throws EidPostProcessingException if post-processing fails @@ -179,27 +140,12 @@ public abstract class AbstractEidProcessor implements INationalEidProcessor { */ protected String processPlaceOfBirth(Object placeOfBirthObj) throws EidPostProcessingException, EidasAttributeException { - if (placeOfBirthObj != null) { - if (placeOfBirthObj instanceof String) { - return (String) placeOfBirthObj; - - } else { - log.warn("eIDAS attr: " + Constants.eIDAS_ATTR_PLACEOFBIRTH + " is of WRONG type"); - throw new EidasAttributeException(Constants.eIDAS_ATTR_PLACEOFBIRTH); - - } - - } else { - log.debug("NO '" + Constants.eIDAS_ATTR_PLACEOFBIRTH + "' attribute. Post-Processing skipped ... "); - } - - return null; - + return EidasResponseUtils.processPlaceOfBirth(placeOfBirthObj); } /** * Post-Process the eIDAS DateOfBirth attribute. - * + * * @param dateOfBirthObj eIDAS date-of-birth attribute information * @return formated user's date-of-birth * @throws EidasAttributeException if NO attribute is available @@ -207,17 +153,12 @@ public abstract class AbstractEidProcessor implements INationalEidProcessor { */ protected DateTime processDateOfBirth(Object dateOfBirthObj) throws EidPostProcessingException, EidasAttributeException { - if (dateOfBirthObj == null || !(dateOfBirthObj instanceof DateTime)) { - throw new EidasAttributeException(Constants.eIDAS_ATTR_DATEOFBIRTH); - } - - return (DateTime) dateOfBirthObj; - + return EidasResponseUtils.processDateOfBirth(dateOfBirthObj); } /** * Post-Process the eIDAS GivenName attribute. - * + * * @param givenNameObj eIDAS givenName attribute information * @return formated user's givenname * @throws EidasAttributeException if NO attribute is available @@ -225,17 +166,12 @@ public abstract class AbstractEidProcessor implements INationalEidProcessor { */ protected String processGivenName(Object givenNameObj) throws EidPostProcessingException, EidasAttributeException { - if (givenNameObj == null || !(givenNameObj instanceof String)) { - throw new EidasAttributeException(Constants.eIDAS_ATTR_CURRENTGIVENNAME); - } - - return (String) givenNameObj; - + return EidasResponseUtils.processGivenName(givenNameObj); } /** * Post-Process the eIDAS FamilyName attribute. - * + * * @param familyNameObj eIDAS familyName attribute information * @return formated user's familyname * @throws EidasAttributeException if NO attribute is available @@ -243,17 +179,12 @@ public abstract class AbstractEidProcessor implements INationalEidProcessor { */ protected String processFamilyName(Object familyNameObj) throws EidPostProcessingException, EidasAttributeException { - if (familyNameObj == null || !(familyNameObj instanceof String)) { - throw new EidasAttributeException(Constants.eIDAS_ATTR_CURRENTFAMILYNAME); - } - - return (String) familyNameObj; - + return EidasResponseUtils.processFamilyName(familyNameObj); } /** * Post-Process the eIDAS pseudonym to ERnB unique identifier. - * + * * @param personalIdObj eIDAS PersonalIdentifierAttribute * @return Unique personal identifier without country-code information * @throws EidasAttributeException if NO attribute is available @@ -261,15 +192,7 @@ public abstract class AbstractEidProcessor implements INationalEidProcessor { */ protected String processPseudonym(Object personalIdObj) throws EidPostProcessingException, EidasAttributeException { - if (personalIdObj == null || !(personalIdObj instanceof String)) { - throw new EidasAttributeException(Constants.eIDAS_ATTR_PERSONALIDENTIFIER); - } - - final Triple eIdentifier = - EidasResponseUtils.parseEidasPersonalIdentifier((String) personalIdObj); - - return eIdentifier.getThird(); - + return EidasResponseUtils.processPseudonym(personalIdObj); } private void buildRequestedAttributes(Builder authnRequestBuilder) { @@ -335,8 +258,8 @@ public abstract class AbstractEidProcessor implements INationalEidProcessor { final String providerName = pendingReq.getRawData(Constants.DATA_PROVIDERNAME, String.class); if (StringUtils.isNotEmpty(providerName) && basicConfig.getBasicConfigurationBoolean( - Constants.CONIG_PROPS_EIDAS_NODE_WORKAROUND_ADD_ALWAYS_PROVIDERNAME, - false)) { + Constants.CONIG_PROPS_EIDAS_NODE_WORKAROUND_ADD_ALWAYS_PROVIDERNAME, + false)) { authnRequestBuilder.providerName(providerName); } diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/ICountrySpecificDetailSearchProcessor.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/ICountrySpecificDetailSearchProcessor.java index c35f6e16..13d9117d 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/ICountrySpecificDetailSearchProcessor.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/ICountrySpecificDetailSearchProcessor.java @@ -24,7 +24,7 @@ package at.asitplus.eidas.specific.modules.auth.eidas.v2.handler; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.CountrySpecificDetailSearchResult; -import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ErnbEidData; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData; public interface ICountrySpecificDetailSearchProcessor { @@ -52,7 +52,7 @@ public interface ICountrySpecificDetailSearchProcessor { * @param eidData eID data * @return true if this implementation can handle the country, otherwise false */ - boolean canHandle(String countryCode, ErnbEidData eidData); + boolean canHandle(String countryCode, SimpleEidasData eidData); - CountrySpecificDetailSearchResult search(ErnbEidData eidData); + CountrySpecificDetailSearchResult search(SimpleEidasData eidData); } 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 d9f70a81..bcada70f 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 @@ -23,40 +23,48 @@ package at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.annotation.PostConstruct; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.joda.time.DateTime; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Component; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; + import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants; import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.CountrySpecificDetailSearchResult; -import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ErnbEidData; -import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.InitialSearchResult; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.MergedRegisterSearchResult; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.RegisterResult; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.ernb.IErnbClient; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidPostProcessingException; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasAttributeException; import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.ManualFixNecessaryException; import at.asitplus.eidas.specific.modules.auth.eidas.v2.handler.ICountrySpecificDetailSearchProcessor; -import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.ICcSpecificEidProcessingService; import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.EidasResponseUtils; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.zmr.IZmrClient; import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; +import at.gv.egiz.eaaf.core.impl.data.Triple; import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper; import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; import eu.eidas.auth.commons.attribute.AttributeDefinition; import eu.eidas.auth.commons.attribute.AttributeValue; import eu.eidas.auth.commons.light.ILightResponse; import eu.eidas.auth.commons.protocol.eidas.impl.PostalAddress; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.joda.time.DateTime; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; /** * Task that creates the IdentityLink for an eIDAS authenticated person. @@ -75,13 +83,19 @@ public class InitialSearchTask extends AbstractAuthServletTask { // private IConfiguration basicConfig; // @Autowired // private SzrClient szrClient; - @Autowired - private ICcSpecificEidProcessingService eidPostProcessor; + // @Autowired + // private ICcSpecificEidProcessingService eidPostProcessor; // private static final String EID_STATUS = "urn:eidgvat:eid.status.eidas"; @Autowired private ApplicationContext context; + @Autowired + private IErnbClient ernbClient; + + @Autowired + private IZmrClient zmrClient; + @PostConstruct private void initialize() { log.debug("Initialize country specific detail search services ... "); @@ -127,36 +141,82 @@ public class InitialSearchTask extends AbstractAuthServletTask { eidasResponse.getAttributes().getAttributeMap()); // post-process eIDAS attributes - final ErnbEidData eidData = eidPostProcessor.postProcess(simpleAttrMap); - - String personIdentifier = eidData.getPseudonym(); - - //search in register(step 2) - InitialSearchResult result = searchInZmrAndErnp(personIdentifier); - switch (result.getResultCount()) { - case 0: - step5(result, eidData); - break; - case 1: - step3(result, eidData); - break; - default://should not happen - throw new TaskExecutionException(pendingReq, "Initial search - Kitt Process necessary.", - new ManualFixNecessaryException(personIdentifier)); - } + final SimpleEidasData eidData = convertSimpleMapToSimpleData(simpleAttrMap); + step2(eidData); } catch (final Exception e) { log.error("Initial search FAILED.", e); throw new TaskExecutionException(pendingReq, "Initial search FAILED.", e); } } - private void step3(InitialSearchResult result, ErnbEidData eidData) { + private void step2(SimpleEidasData eidData) throws TaskExecutionException { + String personIdentifier = eidData.getPseudonym(); + //search in register(step 2) + MergedRegisterSearchResult result = searchInZmrAndErnp(personIdentifier); + switch (result.getResultCount()) { + case 0: + step5(result, eidData); + break; + case 1: + step3(result, eidData); + break; + default://should not happen + throw new TaskExecutionException(pendingReq, "Initial search - Kitt Process necessary.", + new ManualFixNecessaryException(personIdentifier)); + } + } + + private SimpleEidasData convertSimpleMapToSimpleData(Map eidasAttrMap) + throws EidasAttributeException, EidPostProcessingException { + SimpleEidasData simpleEidasData = new SimpleEidasData(); + + final Object eIdentifierObj = eidasAttrMap.get(Constants.eIDAS_ATTR_PERSONALIDENTIFIER); + final Triple eIdentifier = + EidasResponseUtils.parseEidasPersonalIdentifier((String) eIdentifierObj); + simpleEidasData.setCitizenCountryCode(eIdentifier.getFirst()); + + // MDS attributes + simpleEidasData.setPseudonym(EidasResponseUtils.processPseudonym( + eidasAttrMap.get(Constants.eIDAS_ATTR_PERSONALIDENTIFIER))); + simpleEidasData.setFamilyName(EidasResponseUtils.processFamilyName( + eidasAttrMap.get(Constants.eIDAS_ATTR_CURRENTFAMILYNAME))); + simpleEidasData.setGivenName(EidasResponseUtils.processGivenName( + eidasAttrMap.get(Constants.eIDAS_ATTR_CURRENTGIVENNAME))); + simpleEidasData.setDateOfBirth(EidasResponseUtils.processDateOfBirth( + eidasAttrMap.get(Constants.eIDAS_ATTR_DATEOFBIRTH))); + + // additional attributes + simpleEidasData.setPlaceOfBirth(EidasResponseUtils.processPlaceOfBirth( + eidasAttrMap.get(Constants.eIDAS_ATTR_PLACEOFBIRTH))); + simpleEidasData.setBirthName(EidasResponseUtils.processBirthName( + eidasAttrMap.get(Constants.eIDAS_ATTR_BIRTHNAME))); + simpleEidasData.setAddress(EidasResponseUtils.processAddress( + eidasAttrMap.get(Constants.eIDAS_ATTR_CURRENTADDRESS))); + + //TODO other additional attributes + return simpleEidasData; + } + + private void step3(MergedRegisterSearchResult result, SimpleEidasData eidData) { //check if data from eidas authentication matches with data from register - //TODO + log.debug("Compare " + result + " with " + eidData); + //TODO check if data matches + boolean match = true; + if (match) { + return; + } else { + step4(result, eidData); + } } - private void step5(InitialSearchResult result, ErnbEidData eidData) throws TaskExecutionException { + private void step4(MergedRegisterSearchResult result, SimpleEidasData eidData) { + log.debug("Update " + result + " with " + eidData); + //TODO + } + + private void step5(MergedRegisterSearchResult result, SimpleEidasData eidData) + throws TaskExecutionException { String citizenCountry = eidData.getCitizenCountryCode(); ICountrySpecificDetailSearchProcessor foundHandler = null; for (final ICountrySpecificDetailSearchProcessor el : handlers) { @@ -178,7 +238,8 @@ public class InitialSearchTask extends AbstractAuthServletTask { } private void step6(ICountrySpecificDetailSearchProcessor countrySpecificDetailSearchProcessor, - InitialSearchResult initialSearchResult, ErnbEidData eidData) throws TaskExecutionException { + MergedRegisterSearchResult initialSearchResult, SimpleEidasData eidData) + throws TaskExecutionException { //6 country specific search CountrySpecificDetailSearchResult countrySpecificDetailSearchResult = countrySpecificDetailSearchProcessor.search(eidData); @@ -196,19 +257,40 @@ public class InitialSearchTask extends AbstractAuthServletTask { } } - private void step7a(InitialSearchResult initialSearchResult, - CountrySpecificDetailSearchResult countrySpecificDetailSearchResult, ErnbEidData eidData) { + private void step7a(MergedRegisterSearchResult initialSearchResult, + CountrySpecificDetailSearchResult countrySpecificDetailSearchResult, SimpleEidasData eidData) { //TODO automerge - + log.debug("Automerge " + initialSearchResult + " with " + eidData + " " + countrySpecificDetailSearchResult); } - private void step8(InitialSearchResult initialSearchResult, ErnbEidData eidData) { - //TODO MDS Suche + private void step8(MergedRegisterSearchResult initialSearchResult, SimpleEidasData eidData) { + MergedRegisterSearchResult mdsSearchResult = new MergedRegisterSearchResult(); + + ArrayList resultsZmr = + zmrClient.searchWithMds(eidData.getGivenName(), eidData.getFamilyName(), eidData.getFormatedDateOfBirth()); + mdsSearchResult.setResultsZmr(resultsZmr); + + ArrayList resultsErnb = + ernbClient.searchWithMds(eidData.getGivenName(), eidData.getFamilyName(), eidData.getFormatedDateOfBirth()); + mdsSearchResult.setResultsErnb(resultsErnb); + + log.debug("Automerge " + initialSearchResult + " with " + eidData + " " + mdsSearchResult); + //TODO + } - private InitialSearchResult searchInZmrAndErnp(String personIdentifier) { - //search TODO - return new InitialSearchResult();//TODO + private MergedRegisterSearchResult searchInZmrAndErnp(String personIdentifier) { + MergedRegisterSearchResult initialSearchResult = new MergedRegisterSearchResult(); + + ArrayList resultsZmr = + zmrClient.searchWithPersonIdentifer(personIdentifier); + initialSearchResult.setResultsZmr(resultsZmr); + + ArrayList resultsErnb = + ernbClient.searchWithPersonIdentifer(personIdentifier); + initialSearchResult.setResultsErnb(resultsErnb); + + return initialSearchResult; } private Map convertEidasAttrToSimpleMap( @@ -241,7 +323,7 @@ public class InitialSearchTask extends AbstractAuthServletTask { } else { final List natPersonIdObj = EidasResponseUtils - .translateStringListAttribute(el, attributeMap.get(el).asList()); + .translateStringListAttribute(el, attributeMap.get(el)); final String stringAttr = natPersonIdObj.get(0); if (StringUtils.isNotEmpty(stringAttr)) { result.put(el.getFriendlyName(), stringAttr); @@ -250,9 +332,12 @@ public class InitialSearchTask extends AbstractAuthServletTask { } else { log.info("Ignore empty 'String' attribute"); } + } } + log.debug("Receive #" + result.size() + " attributes with names: " + result.keySet().toString()); + return result; } } diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/utils/EidasResponseUtils.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/utils/EidasResponseUtils.java index c8c5a069..ea4a4c76 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/utils/EidasResponseUtils.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/utils/EidasResponseUtils.java @@ -30,6 +30,9 @@ import java.util.regex.Pattern; import javax.annotation.Nullable; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidPostProcessingException; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasAttributeException; +import at.gv.e_government.reference.namespace.persondata._20020228.PostalAddressType; import org.apache.commons.lang3.StringUtils; import org.joda.time.DateTime; import org.slf4j.Logger; @@ -176,4 +179,169 @@ public class EidasResponseUtils { } + /** + * Post-Process the eIDAS CurrentAddress attribute. + * + * @param currentAddressObj eIDAS current address information + * @return current address or null if no attribute is available + * @throws EidPostProcessingException if post-processing fails + * @throws EidasAttributeException if eIDAS attribute is of a wrong type + */ + public static PostalAddressType processAddress(Object currentAddressObj) throws EidPostProcessingException, + EidasAttributeException { + + if (currentAddressObj != null) { + if (currentAddressObj instanceof PostalAddress) { + final PostalAddressType result = new PostalAddressType(); + result.setPostalCode(((PostalAddress) currentAddressObj).getPostCode()); + result.setMunicipality(((PostalAddress) currentAddressObj).getPostName()); + + // TODO: add more mappings + + return result; + + } else { + log.warn("eIDAS attr: " + Constants.eIDAS_ATTR_CURRENTADDRESS + " is of WRONG type"); + throw new EidasAttributeException(Constants.eIDAS_ATTR_CURRENTADDRESS); + + } + + } else { + log.debug("NO '" + Constants.eIDAS_ATTR_CURRENTADDRESS + "' attribute. Post-Processing skipped ... "); + } + + return null; + + } + + /** + * Post-Process the eIDAS BirthName attribute. + * + * @param birthNameObj eIDAS birthname information + * @return birthName or null if no attribute is available + * @throws EidPostProcessingException if post-processing fails + * @throws EidasAttributeException if eIDAS attribute is of a wrong type + */ + public static String processBirthName(Object birthNameObj) throws EidPostProcessingException, + EidasAttributeException { + if (birthNameObj != null) { + if (birthNameObj instanceof String) { + return (String) birthNameObj; + + } else { + log.warn("eIDAS attr: " + Constants.eIDAS_ATTR_BIRTHNAME + " is of WRONG type"); + throw new EidasAttributeException(Constants.eIDAS_ATTR_BIRTHNAME); + + } + + } else { + log.debug("NO '" + Constants.eIDAS_ATTR_BIRTHNAME + "' attribute. Post-Processing skipped ... "); + } + + return null; + + } + + /** + * Post-Process the eIDAS PlaceOfBirth attribute. + * + * @param placeOfBirthObj eIDAS Place-of-Birth information + * @return place of Birth or null if no attribute is available + * @throws EidPostProcessingException if post-processing fails + * @throws EidasAttributeException if eIDAS attribute is of a wrong type + */ + public static String processPlaceOfBirth(Object placeOfBirthObj) throws EidPostProcessingException, + EidasAttributeException { + if (placeOfBirthObj != null) { + if (placeOfBirthObj instanceof String) { + return (String) placeOfBirthObj; + + } else { + log.warn("eIDAS attr: " + Constants.eIDAS_ATTR_PLACEOFBIRTH + " is of WRONG type"); + throw new EidasAttributeException(Constants.eIDAS_ATTR_PLACEOFBIRTH); + + } + + } else { + log.debug("NO '" + Constants.eIDAS_ATTR_PLACEOFBIRTH + "' attribute. Post-Processing skipped ... "); + } + + return null; + + } + + /** + * Post-Process the eIDAS DateOfBirth attribute. + * + * @param dateOfBirthObj eIDAS date-of-birth attribute information + * @return formated user's date-of-birth + * @throws EidasAttributeException if NO attribute is available + * @throws EidPostProcessingException if post-processing fails + */ + public static DateTime processDateOfBirth(Object dateOfBirthObj) throws EidPostProcessingException, + EidasAttributeException { + if (dateOfBirthObj == null || !(dateOfBirthObj instanceof DateTime)) { + throw new EidasAttributeException(Constants.eIDAS_ATTR_DATEOFBIRTH); + } + + return (DateTime) dateOfBirthObj; + + } + + /** + * Post-Process the eIDAS GivenName attribute. + * + * @param givenNameObj eIDAS givenName attribute information + * @return formated user's givenname + * @throws EidasAttributeException if NO attribute is available + * @throws EidPostProcessingException if post-processing fails + */ + public static String processGivenName(Object givenNameObj) throws EidPostProcessingException, + EidasAttributeException { + if (givenNameObj == null || !(givenNameObj instanceof String)) { + throw new EidasAttributeException(Constants.eIDAS_ATTR_CURRENTGIVENNAME); + } + + return (String) givenNameObj; + + } + + /** + * Post-Process the eIDAS FamilyName attribute. + * + * @param familyNameObj eIDAS familyName attribute information + * @return formated user's familyname + * @throws EidasAttributeException if NO attribute is available + * @throws EidPostProcessingException if post-processing fails + */ + public static String processFamilyName(Object familyNameObj) throws EidPostProcessingException, + EidasAttributeException { + if (familyNameObj == null || !(familyNameObj instanceof String)) { + throw new EidasAttributeException(Constants.eIDAS_ATTR_CURRENTFAMILYNAME); + } + + return (String) familyNameObj; + + } + + /** + * Post-Process the eIDAS pseudonym to ERnB unique identifier. + * + * @param personalIdObj eIDAS PersonalIdentifierAttribute + * @return Unique personal identifier without country-code information + * @throws EidasAttributeException if NO attribute is available + * @throws EidPostProcessingException if post-processing fails + */ + public static String processPseudonym(Object personalIdObj) throws EidPostProcessingException, + EidasAttributeException { + if (personalIdObj == null || !(personalIdObj instanceof String)) { + throw new EidasAttributeException(Constants.eIDAS_ATTR_PERSONALIDENTIFIER); + } + + final Triple eIdentifier = + EidasResponseUtils.parseEidasPersonalIdentifier((String) personalIdObj); + + return eIdentifier.getThird(); + + } } diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/zmr/DummyZmrClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/zmr/DummyZmrClient.java new file mode 100644 index 00000000..9a7cc9b3 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/zmr/DummyZmrClient.java @@ -0,0 +1,49 @@ +package at.asitplus.eidas.specific.modules.auth.eidas.v2.zmr; + +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.RegisterResult; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; + +@Service("ZmrClientForeIDAS") +public class DummyZmrClient implements IZmrClient { + + @Override + public ArrayList searchWithPersonIdentifer(String personIdentifer) { + switch (personIdentifer) { + case "a12345": + case "a12345-": + return result1(); + case "a123456": + return result2(); + default: + return resultEmpty(); + } + } + + @Override + public ArrayList searchWithMds(String givenName, String familyName, String dateOfBirth) { + return resultEmpty();//TODO will I only receive matches where all three values match perfectly? + } + + private ArrayList resultEmpty() { + return new ArrayList();//Nobody found + } + + private ArrayList result1() { + ArrayList results = new ArrayList<>(); + RegisterResult result1 = new RegisterResult("12345", "Tom", "Mustermann", "1950-01-01", "Wien"); + results.add(result1); + RegisterResult result2 = new RegisterResult("12345-", "Tom", "Mustermann", "1950-01-01", "Wien"); + results.add(result2); + return results; + } + + private ArrayList result2() { + ArrayList results = new ArrayList<>(); + RegisterResult result = new RegisterResult("123456", "Max", "Mustermann", "2000-01-01", "Wien"); + results.add(result); + return results; + } + +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/zmr/IZmrClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/zmr/IZmrClient.java new file mode 100644 index 00000000..1f7e4949 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/zmr/IZmrClient.java @@ -0,0 +1,12 @@ +package at.asitplus.eidas.specific.modules.auth.eidas.v2.zmr; + +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.RegisterResult; + +import java.util.ArrayList; + +public interface IZmrClient { + + ArrayList searchWithPersonIdentifer(String personIdentifer); + + ArrayList searchWithMds(String givenName, String familyName, String dateOfBirth); +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/resources/eidas_v2_auth.beans.xml b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/eidas_v2_auth.beans.xml index 9c28bf07..0f6277c0 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/resources/eidas_v2_auth.beans.xml +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/eidas_v2_auth.beans.xml @@ -17,6 +17,12 @@ + + + + -- cgit v1.2.3