diff options
| author | Alexander Marsalek <amarsalek@iaik.tugraz.at> | 2020-12-03 10:13:44 +0100 | 
|---|---|---|
| committer | Alexander Marsalek <amarsalek@iaik.tugraz.at> | 2021-01-04 14:14:47 +0100 | 
| commit | 5649772eedcb67d79ebb95e2074455bef6d3ba56 (patch) | |
| tree | 6cb13ce6066a12d79636f2984a1cfa8dc1aa7ad5 /eidas_modules/authmodule-eIDAS-v2/src | |
| parent | 1247debcf4807dfdd9d9080d48f546c933a472b1 (diff) | |
| download | National_eIDAS_Gateway-5649772eedcb67d79ebb95e2074455bef6d3ba56.tar.gz National_eIDAS_Gateway-5649772eedcb67d79ebb95e2074455bef6d3ba56.tar.bz2 National_eIDAS_Gateway-5649772eedcb67d79ebb95e2074455bef6d3ba56.zip | |
general workflow steps 1-8
Diffstat (limited to 'eidas_modules/authmodule-eIDAS-v2/src')
8 files changed, 391 insertions, 1 deletions
| diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/CountrySpecificDetailSearchResult.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/CountrySpecificDetailSearchResult.java new file mode 100644 index 00000000..710e286c --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/CountrySpecificDetailSearchResult.java @@ -0,0 +1,14 @@ +package at.asitplus.eidas.specific.modules.auth.eidas.v2.dao; + +public class CountrySpecificDetailSearchResult { + +  //TODO is the result the same as the one form the initial search? +  int resultsZmr; +  int resultsErnb; + +  public int getResultCount() { +    return resultsZmr + resultsErnb; +  } + + +} 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 new file mode 100644 index 00000000..8fe69414 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/dao/InitialSearchResult.java @@ -0,0 +1,12 @@ +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/exception/ManualFixNecessaryException.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/ManualFixNecessaryException.java new file mode 100644 index 00000000..f3916ed6 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/exception/ManualFixNecessaryException.java @@ -0,0 +1,40 @@ +/* + * 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.exception; + +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ErnbEidData; + +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) { + +    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/ICountrySpecificDetailSearchProcessor.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/ICountrySpecificDetailSearchProcessor.java new file mode 100644 index 00000000..c35f6e16 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/handler/ICountrySpecificDetailSearchProcessor.java @@ -0,0 +1,58 @@ +/* + * 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.handler; + +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.CountrySpecificDetailSearchResult; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ErnbEidData; + +public interface ICountrySpecificDetailSearchProcessor { + +  /** +   * Get a friendlyName of this post-processor implementation. +   * +   * @return +   */ +  String getName(); + +  /** +   * Get the priority of this eID Post-Processor <br> +   * If more than one Post-Processor implementations can handle the eID data, the +   * post-processor with the highest priority are selected. The Default-Processor +   * has priority '0' +   * +   * @return Priority of this handler +   */ +  int getPriority(); + +  /** +   * Check if this postProcessor is sensitive for a specific country. +   * +   * @param countryCode of the eID data that should be processed +   * @param eidData eID data +   * @return true if this implementation can handle the country, otherwise false +   */ +  boolean canHandle(String countryCode, ErnbEidData eidData); + +  CountrySpecificDetailSearchResult search(ErnbEidData 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 new file mode 100644 index 00000000..d9f70a81 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/tasks/InitialSearchTask.java @@ -0,0 +1,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.tasks; + +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.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.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.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. + * + * @author tlenz + */ +@Slf4j +@Component("InitialSearchTask") +public class InitialSearchTask extends AbstractAuthServletTask { + +  private final List<ICountrySpecificDetailSearchProcessor> handlers = new ArrayList<>(); + +  //  @Autowired +  //  private AuthBlockSigningService authBlockSigner; +  //  @Autowired +  //  private IConfiguration basicConfig; +  //  @Autowired +  //  private SzrClient szrClient; +  @Autowired +  private ICcSpecificEidProcessingService eidPostProcessor; + +  //  private static final String EID_STATUS = "urn:eidgvat:eid.status.eidas"; +  @Autowired +  private ApplicationContext context; + +  @PostConstruct +  private void initialize() { +    log.debug("Initialize country specific detail search services ... "); +    final Map<String, ICountrySpecificDetailSearchProcessor> postProcessors = context.getBeansOfType( +        ICountrySpecificDetailSearchProcessor.class); +    final Iterator<Map.Entry<String, ICountrySpecificDetailSearchProcessor>> iterator = +        postProcessors.entrySet().iterator(); +    while (iterator.hasNext()) { +      final Map.Entry<String, ICountrySpecificDetailSearchProcessor> el = iterator.next(); +      log.debug("Find country specific detail search services with name: " + el.getKey()); +      handlers.add(el.getValue()); + +    } + +    log.trace("Sorting country specific detail search services on priority ... "); +    Collections.sort(handlers, (thisAuthModule, otherAuthModule) -> { +      final int thisOrder = thisAuthModule.getPriority(); +      final int otherOrder = otherAuthModule.getPriority(); +      return thisOrder < otherOrder ? 1 : thisOrder == otherOrder ? 0 : -1; +    }); + +    log.info("# " + handlers.size() + " country specific detail search services are registrated"); + +  } + +  /* +   * (non-Javadoc) +   * +   * @see at.gv.egovernment.moa.id.process.springweb.MoaIdTask#execute(at.gv. +   * egovernment.moa.id.process.api.ExecutionContext, +   * javax.servlet.http.HttpServletRequest, +   * javax.servlet.http.HttpServletResponse) +   */ +  @Override +  public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) +      throws TaskExecutionException { +    try { +      final AuthProcessDataWrapper authProcessData = pendingReq.getSessionData(AuthProcessDataWrapper.class); +      final ILightResponse eidasResponse = authProcessData +          .getGenericDataFromSession(Constants.DATA_FULL_EIDAS_RESPONSE, ILightResponse.class); + +      final Map<String, Object> simpleAttrMap = convertEidasAttrToSimpleMap( +          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)); +      } +    } 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) { +    //check if data from eidas authentication matches with data from register +    //TODO + +  } + +  private void step5(InitialSearchResult result, ErnbEidData eidData) throws TaskExecutionException { +    String citizenCountry = eidData.getCitizenCountryCode(); +    ICountrySpecificDetailSearchProcessor foundHandler = null; +    for (final ICountrySpecificDetailSearchProcessor el : handlers) { +      //5 check if country specific search is possible +      if (el.canHandle(citizenCountry, eidData)) { +        log.debug("Found suitable country specific search handler for " + citizenCountry +            + " by using: " + el.getName()); +        foundHandler = el; +        break; +      } +    } +    if (foundHandler == null) { +      //MDS search +      step8(result, eidData); +    } else { +      //country specific search +      step6(foundHandler, result, eidData); +    } +  } + +  private void step6(ICountrySpecificDetailSearchProcessor countrySpecificDetailSearchProcessor, +                     InitialSearchResult initialSearchResult, ErnbEidData eidData) throws TaskExecutionException { +    //6 country specific search +    CountrySpecificDetailSearchResult countrySpecificDetailSearchResult = +        countrySpecificDetailSearchProcessor.search(eidData); + +    switch (countrySpecificDetailSearchResult.getResultCount()) { +      case 0: +        step8(initialSearchResult, eidData); +        break; +      case 1: +        step7a(initialSearchResult, countrySpecificDetailSearchResult, eidData); +        break; +      default://should not happen +        throw new TaskExecutionException(pendingReq, "Detail search - Kitt Process necessary.", +            new ManualFixNecessaryException(eidData)); +    } +  } + +  private void step7a(InitialSearchResult initialSearchResult, +                      CountrySpecificDetailSearchResult countrySpecificDetailSearchResult, ErnbEidData eidData) { +    //TODO automerge + +  } + +  private void step8(InitialSearchResult initialSearchResult, ErnbEidData eidData) { +    //TODO MDS Suche +  } + +  private InitialSearchResult searchInZmrAndErnp(String personIdentifier) { +    //search TODO +    return new InitialSearchResult();//TODO +  } + +  private Map<String, Object> convertEidasAttrToSimpleMap( +      ImmutableMap<AttributeDefinition<?>, ImmutableSet<? extends AttributeValue<?>>> attributeMap) { +    final Map<String, Object> result = new HashMap<>(); + +    for (final AttributeDefinition<?> el : attributeMap.keySet()) { + +      final Class<?> parameterizedType = el.getParameterizedType(); +      if (DateTime.class.equals(parameterizedType)) { +        final DateTime attribute = EidasResponseUtils.translateDateAttribute(el, attributeMap.get(el).asList()); +        if (attribute != null) { +          result.put(el.getFriendlyName(), attribute); +          log.trace("Find attr '" + el.getFriendlyName() + "' with value: " + attribute.toString()); + +        } else { +          log.info("Ignore empty 'DateTime' attribute"); +        } + +      } else if (PostalAddress.class.equals(parameterizedType)) { +        final PostalAddress addressAttribute = EidasResponseUtils +            .translateAddressAttribute(el, attributeMap.get(el).asList()); +        if (addressAttribute != null) { +          result.put(el.getFriendlyName(), addressAttribute); +          log.trace("Find attr '" + el.getFriendlyName() + "' with value: " + addressAttribute.toString()); + +        } else { +          log.info("Ignore empty 'PostalAddress' attribute"); +        } + +      } else { +        final List<String> natPersonIdObj = EidasResponseUtils +            .translateStringListAttribute(el, attributeMap.get(el).asList()); +        final String stringAttr = natPersonIdObj.get(0); +        if (StringUtils.isNotEmpty(stringAttr)) { +          result.put(el.getFriendlyName(), stringAttr); +          log.trace("Find attr '" + el.getFriendlyName() + "' with value: " + stringAttr); + +        } else { +          log.info("Ignore empty 'String' attribute"); +        } +      } +    } +    log.debug("Receive #" + result.size() + " attributes with names: " + result.keySet().toString()); +    return result; +  } +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/resources/eIDAS.Authentication.process.xml b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/eIDAS.Authentication.process.xml index 55bb1ace..e199d379 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/resources/eIDAS.Authentication.process.xml +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/eIDAS.Authentication.process.xml @@ -10,6 +10,8 @@      class="FinalizeAuthenticationTask" />    <pd:Task id="generateIdentityLink"      class="CreateIdentityLinkTask" /> +  <pd:Task id="initialRegisterSearch" +           class="InitialSearchTask" />    <pd:StartEvent id="start" /> @@ -18,6 +20,8 @@    <pd:Transition  from="createAuthnRequest"                    to="receiveAuthnResponse" />    <pd:Transition  from="receiveAuthnResponse" +                  to="initialRegisterSearch" /> +  <pd:Transition  from="initialRegisterSearch"                    to="generateIdentityLink" />    <pd:Transition  from="generateIdentityLink"                    to="finalizeAuthentication" /> diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/resources/eidas_v2_auth.beans.xml b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/eidas_v2_auth.beans.xml index 6cc704ab..9c28bf07 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 @@ -87,4 +87,8 @@      class="at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.CreateIdentityLinkTask"      scope="prototype" /> +  <bean id="InitialSearchTask" +        class="at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.InitialSearchTask" +        scope="prototype" /> +  </beans>
\ No newline at end of file diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/EidasRequestPreProcessingSecondTest.java b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/EidasRequestPreProcessingSecondTest.java index da7e3d85..e7bacded 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/EidasRequestPreProcessingSecondTest.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/EidasRequestPreProcessingSecondTest.java @@ -107,7 +107,7 @@ public class EidasRequestPreProcessingSecondTest {      final LightRequest lightReq = authnRequestBuilder.build(); -    Assert.assertEquals("ProviderName is not Static", "myNode", lightReq.getProviderName()); +    Assert.assertEquals("ProviderName is not Static", "myNode", lightReq.getProviderName());//Fixme "myNode"      Assert.assertEquals("no PublicSP", "public", lightReq.getSpType());      Assert.assertEquals("Requested attribute size not match", 8, lightReq.getRequestedAttributes().size()); | 
