diff options
44 files changed, 3626 insertions, 387 deletions
| @@ -10,4 +10,5 @@ target  .directory  .checkstyle  .metadata +*.iml  notCommit diff --git a/basicConfig/default_config.properties b/basicConfig/default_config.properties index dda5144e..483e9c97 100644 --- a/basicConfig/default_config.properties +++ b/basicConfig/default_config.properties @@ -39,6 +39,7 @@ eidas.ms.auth.eIDAS.node_v2.loa.requested.minimum=http://eidas.europa.eu/LoA/hig  eidas.ms.auth.eIDAS.szrclient.useTestService=true  eidas.ms.auth.eIDAS.szrclient.endpoint.prod=  eidas.ms.auth.eIDAS.szrclient.endpoint.test=http://localhost:1234/demoszr +eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.type=pkcs12  eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.path=keys/.....  eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.password=  eidas.ms.auth.eIDAS.szrclient.ssl.trustStore.path= @@ -50,6 +51,15 @@ eidas.ms.auth.eIDAS.szrclient.params.vkz=  eidas.ms.auth.eIDAS.szrclient.params.useSZRForbPKCalculation=false +## E-AuthBlock configuration +eidas.ms.auth.eIDAS.authblock.keystore.type=jks +eidas.ms.auth.eIDAS.authblock.keystore.path=keys/teststore.jks +eidas.ms.auth.eIDAS.authblock.keystore.password=f/+saJBc3a}*/T^s +eidas.ms.auth.eIDAS.authblock.keystore.name= +eidas.ms.auth.eIDAS.authblock.key.alias=connectorkeypair +eidas.ms.auth.eIDAS.authblock.key.password=f/+saJBc3a}*/T^s + +  #Raw eIDAS Id data storage  eidas.ms.auth.eIDAS.szrclient.workarounds.eidmapping.revisionlog.active=true @@ -80,6 +90,7 @@ eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.5=LegalName,true  ## PVP2 S-Profile end-point configuration +eidas.ms.pvp2.keystore.type=jks  eidas.ms.pvp2.keystore.path=keys/.....  eidas.ms.pvp2.keystore.password=  eidas.ms.pvp2.key.metadata.alias= diff --git a/basicConfig/keys/teststore.jks b/basicConfig/keys/teststore.jksBinary files differ new file mode 100644 index 00000000..fcc6400c --- /dev/null +++ b/basicConfig/keys/teststore.jks diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/attributes/AuthBlockAttributeBuilder.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/attributes/AuthBlockAttributeBuilder.java new file mode 100644 index 00000000..be9f8862 --- /dev/null +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/attributes/AuthBlockAttributeBuilder.java @@ -0,0 +1,64 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, 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 "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * 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.connector.attributes; + +import static at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions.EID_AUTHBLOCK_SIGNED_FRIENDLY_NAME; +import static at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions.EID_AUTHBLOCK_SIGNED_NAME; + +import org.apache.commons.lang3.StringUtils; + +import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants; +import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.IPvpAttributeBuilder; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; +import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; +import at.gv.egiz.eaaf.core.impl.idp.builder.attributes.PvpMetadata; + + +@PvpMetadata +public class AuthBlockAttributeBuilder implements IPvpAttributeBuilder { + +  @Override +  public String getName() { +    return EID_AUTHBLOCK_SIGNED_NAME; +  } + +  @Override +  public <ATT> ATT build(final ISpConfiguration oaParam, final IAuthData authData, +                         final IAttributeGenerator<ATT> g) throws AttributeBuilderException { + +    String authBlock = authData.getGenericData(Constants.SZR_AUTHBLOCK, String.class); +    if (StringUtils.isNotEmpty(authBlock)) { +      return g.buildStringAttribute(EID_AUTHBLOCK_SIGNED_FRIENDLY_NAME, EID_AUTHBLOCK_SIGNED_NAME, authBlock); + +    } else { +      throw new UnavailableAttributeException(EID_AUTHBLOCK_SIGNED_NAME); +    } + +  } + +  @Override +  public <ATT> ATT buildEmpty(final IAttributeGenerator<ATT> g) { +    return g.buildEmptyAttribute(EID_AUTHBLOCK_SIGNED_FRIENDLY_NAME, EID_AUTHBLOCK_SIGNED_NAME); +  } + +} diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/attributes/EidasBindAttributeBuilder.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/attributes/EidasBindAttributeBuilder.java new file mode 100644 index 00000000..a4fe8c6c --- /dev/null +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/attributes/EidasBindAttributeBuilder.java @@ -0,0 +1,63 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, 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 "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * 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.connector.attributes; + +import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants; +import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.IPvpAttributeBuilder; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; +import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; +import at.gv.egiz.eaaf.core.impl.idp.builder.attributes.PvpMetadata; +import org.apache.commons.lang3.StringUtils; + +import static at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions.EID_EIDBIND_FRIENDLY_NAME; +import static at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions.EID_EIDBIND_NAME; + +@PvpMetadata +public class EidasBindAttributeBuilder implements IPvpAttributeBuilder { + + +  @Override +  public String getName() { +    return EID_EIDBIND_NAME; +  } + +  @Override +  public <ATT> ATT build(final ISpConfiguration oaParam, final IAuthData authData, +                         final IAttributeGenerator<ATT> g) throws AttributeBuilderException { + +    String eidasBind = authData.getGenericData(Constants.EIDAS_BIND, String.class); +    if (StringUtils.isNotEmpty(eidasBind)) { +      return g.buildStringAttribute(EID_EIDBIND_FRIENDLY_NAME, EID_EIDBIND_NAME, eidasBind); + +    } else { +      throw new UnavailableAttributeException(EID_EIDBIND_NAME); +    } + +  } + +  @Override +  public <ATT> ATT buildEmpty(final IAttributeGenerator<ATT> g) { +    return g.buildEmptyAttribute(EID_EIDBIND_FRIENDLY_NAME, EID_EIDBIND_NAME); +  } + +} diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/builder/AuthenticationDataBuilder.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/builder/AuthenticationDataBuilder.java index b14faa62..13cceafb 100644 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/builder/AuthenticationDataBuilder.java +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/builder/AuthenticationDataBuilder.java @@ -19,7 +19,7 @@   * 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.connector.builder; @@ -54,30 +54,35 @@ public class AuthenticationDataBuilder extends AbstractAuthenticationDataBuilder    public IAuthData buildAuthenticationData(IRequest pendingReq) throws EaafAuthenticationException {      final IAuthProcessDataContainer authProcessData = pendingReq.getSessionData(AuthProcessDataWrapper.class); -    final AuthenticationData authData = new AuthenticationData(); +    AuthenticationData authData = new AuthenticationData(); -    try { -      generateDeprecatedBasicAuthData(authData, pendingReq, authProcessData); +    boolean isEidModeNew = pendingReq.getServiceProviderConfiguration() +        .isConfigurationValue(MsEidasNodeConstants.PROP_CONFIG_SP_NEW_EID_MODE, false); -      // set specific informations -      authData.setSsoSessionValidTo(new Date(new Date().getTime() -          + MsEidasNodeConstants.DEFAULT_PVP_ASSERTION_VALIDITY * 60 * 1000)); +    if (isEidModeNew) { +      authData = (AuthenticationData) super.buildAuthenticationData(pendingReq); +    } else { +      try { +        generateDeprecatedBasicAuthData(authData, pendingReq, authProcessData); -    } catch (EaafBuilderException | EaafParserException | EaafConfigurationException -        | XPathException | DOMException e) { -      log.warn("Can not build authentication data from auth. process information"); -      throw new EaafAuthenticationException("builder.11", new Object[] { e.getMessage() }, e); +        // set specific informations +        authData.setSsoSessionValidTo( +            new Date(new Date().getTime() + MsEidasNodeConstants.DEFAULT_PVP_ASSERTION_VALIDITY * 60 * 1000)); -    } +      } catch (EaafBuilderException | EaafParserException +          | EaafConfigurationException | XPathException | DOMException e) { +        log.warn("Can not build authentication data from auth. process information"); +        throw new EaafAuthenticationException("builder.11", new Object[]{e.getMessage()}, e); +      } +    }      return authData; -    }    @Override    protected IAuthData buildDeprecatedAuthData(IRequest arg0) throws EaafException {      return new AuthenticationData(); -     +    }    @Override diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/provider/PvpMetadataProvider.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/provider/PvpMetadataProvider.java index 651b7b78..8dbb74c7 100644 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/provider/PvpMetadataProvider.java +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/provider/PvpMetadataProvider.java @@ -173,4 +173,11 @@ public class PvpMetadataProvider extends AbstractChainingMetadataProvider {      return "Service-provider chainging metadata provider";    } +   +  @Override +  public void doDestroy() { +    this.fullyDestroy(); +     +  } +  } diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/verification/AuthnRequestValidator.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/verification/AuthnRequestValidator.java index 26176c49..a9eb06be 100644 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/verification/AuthnRequestValidator.java +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/verification/AuthnRequestValidator.java @@ -46,11 +46,13 @@ import at.asitplus.eidas.specific.connector.MsEidasNodeConstants;  import at.asitplus.eidas.specific.connector.config.ServiceProviderConfiguration;  import at.gv.egiz.eaaf.core.api.IRequest;  import at.gv.egiz.eaaf.core.api.data.EaafConstants; +import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions;  import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions;  import at.gv.egiz.eaaf.core.api.idp.IConfiguration;  import at.gv.egiz.eaaf.core.exceptions.AuthnRequestValidatorException;  import at.gv.egiz.eaaf.core.exceptions.EaafException;  import at.gv.egiz.eaaf.core.exceptions.EaafStorageException; +import at.gv.egiz.eaaf.core.impl.idp.controller.protocols.RequestImpl;  import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute;  import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttributes;  import at.gv.egiz.eaaf.modules.pvp2.api.validation.IAuthnRequestPostProcessor; @@ -107,120 +109,179 @@ public class AuthnRequestValidator implements IAuthnRequestPostProcessor {        }        // post-process requested LoA -      final List<String> reqLoA = extractLoA(authnReq); -      log.trace("SP requests LoA with: {}", String.join(", ",reqLoA)); +      postprocessLoaLevel(pendingReq, authnReq); + +      // post-process requested LoA comparison-level +      pendingReq.getServiceProviderConfiguration(ServiceProviderConfiguration.class).setLoAMachtingMode( +          extractComparisonLevel(authnReq)); +       +      //extract information from requested attributes +      extractFromRequestedAttriutes(pendingReq, authnReq); -      LevelOfAssurance minimumLoAFromConfig = LevelOfAssurance.fromString(basicConfig.getBasicConfiguration( -          MsEidasNodeConstants.PROP_EIDAS_REQUEST_LOA_MINIMUM_LEVEL, -          EaafConstants.EIDAS_LOA_HIGH)); -      if (minimumLoAFromConfig == null) { -        log.warn("Can not load minimum LoA from configuration. Use LoA: {} as default", -            EaafConstants.EIDAS_LOA_HIGH); -        minimumLoAFromConfig = LevelOfAssurance.HIGH; +    } catch (final EaafStorageException e) { +      log.info("Can NOT store Authn. Req. data into pendingRequest.", e); +      throw new AuthnRequestValidatorException("internal.02", null, e); -      } -             -      log.trace("Validate requested LoA to connector configuration minimum LoA: {} ...", -          minimumLoAFromConfig);       -      final List<String> allowedLoA = new ArrayList<>(); -      for (final String loa : reqLoA) { -        try { -          final LevelOfAssurance intLoa = LevelOfAssurance.fromString(loa); -          String selectedLoA = EaafConstants.EIDAS_LOA_HIGH; -          if (intLoa != null  -              && intLoa.numericValue() <= minimumLoAFromConfig.numericValue()) { -            log.info("Client: {} requested LoA: {} will be upgraded to: {}", -                pendingReq.getServiceProviderConfiguration().getUniqueIdentifier(), -                loa, -                minimumLoAFromConfig); -            selectedLoA = minimumLoAFromConfig.getValue(); +    } -          } +  } -          if (!allowedLoA.contains(selectedLoA)) { -            log.debug("Allow LoA: {} for Client: {}", -                selectedLoA, -                pendingReq.getServiceProviderConfiguration().getUniqueIdentifier()); -            allowedLoA.add(selectedLoA); +  private void extractFromRequestedAttriutes(IRequest pendingReq, AuthnRequest authnReq)  +      throws AuthnRequestValidatorException { +    // validate and process requested attributes +    boolean sectorDetected = false; +     +    final ServiceProviderConfiguration spConfig = pendingReq.getServiceProviderConfiguration( +        ServiceProviderConfiguration.class); +     +    if (authnReq.getExtensions() != null) { +      final List<XMLObject> requestedAttributes = authnReq.getExtensions().getUnknownXMLObjects(); +      for (final XMLObject reqAttrObj : requestedAttributes) { +        if (reqAttrObj instanceof EaafRequestedAttributes) { +          final EaafRequestedAttributes reqAttr = (EaafRequestedAttributes) reqAttrObj; +          if (reqAttr.getAttributes() != null && reqAttr.getAttributes().size() != 0) { +            for (final EaafRequestedAttribute el : reqAttr.getAttributes()) { +              log.trace("Processing req. attribute '" + el.getName() + "' ... "); +              if (el.getName().equals(PvpAttributeDefinitions.EID_SECTOR_FOR_IDENTIFIER_NAME)) { +                sectorDetected = extractBpkTargetIdentifier(el, spConfig);  +                +              } else if (el.getName().equals(ExtendedPvpAttributeDefinitions.EID_TRANSACTION_ID_NAME)) { +                extractUniqueTransactionId(el, pendingReq); +                 +              } else { +                log.debug("Ignore req. attribute: " + el.getName()); +                 +              } +            } +          } else { +            log.debug("No requested Attributes in Authn. Request"); +                        } -        } catch (final IllegalArgumentException e) { -          log.warn("LoA: {} is currently NOT supported and it will be ignored.", loa); - +        } else { +          log.info("Ignore unknown requested attribute: " + reqAttrObj.getElementQName().toString()); +                    } -        } +    } +     +    if (!sectorDetected) { +      log.warn("Authn.Req validation FAILED. Reason: Contains NO or NO VALID target-sector information."); +      throw new AuthnRequestValidatorException("pvp2.22", new Object[] { +          "NO or NO VALID target-sector information" }); -      pendingReq.getServiceProviderConfiguration(ServiceProviderConfiguration.class).setRequiredLoA( -          allowedLoA); +    } +     +  } -      // post-process requested LoA comparison-level -      final String reqLoAComperison = extractComparisonLevel(authnReq); -      pendingReq.getServiceProviderConfiguration(ServiceProviderConfiguration.class).setLoAMachtingMode( -          reqLoAComperison); +  /** +   * Extract unique transactionId from AuthnRequest. +   *  +   * @param el Requested attribute from AuthnRequest +   * @param pendingReq Current pendingRequest object (has to be of type {@link RequestImpl}) +   * @return <code>true</code> if transactionId extraction was successful, otherwise <code>false</code> +   */ +  private boolean extractUniqueTransactionId(EaafRequestedAttribute el, IRequest pendingReq) { +    if (!(pendingReq instanceof RequestImpl)) { +      log.warn("Can NOT set unique transactionId from AuthnRequest,because 'PendingRequest' is NOT from Type: {}", +          RequestImpl.class.getName()); +       +    } else {         +      if (el.getAttributeValues() != null && el.getAttributeValues().size() == 1) { +        final String transactionId = el.getAttributeValues().get(0).getDOM().getTextContent();       +        ((RequestImpl)pendingReq).setUniqueTransactionIdentifier(transactionId);       +        return true; -      // validate and process requested attributes -      boolean sectorDetected = false; +      } else { +        log.warn("Req. attribute '{}' contains NO or MORE THEN ONE attribute-values. Ignore full req. attribute",  +            el.getName()); +         +      } -      if (authnReq.getExtensions() != null) { -        final List<XMLObject> requestedAttributes = authnReq.getExtensions().getUnknownXMLObjects(); -        for (final XMLObject reqAttrObj : requestedAttributes) { -          if (reqAttrObj instanceof EaafRequestedAttributes) { -            final EaafRequestedAttributes reqAttr = (EaafRequestedAttributes) reqAttrObj; -            if (reqAttr.getAttributes() != null && reqAttr.getAttributes().size() != 0) { -              for (final EaafRequestedAttribute el : reqAttr.getAttributes()) { -                log.trace("Processing req. attribute '" + el.getName() + "' ... "); -                if (el.getName().equals(PvpAttributeDefinitions.EID_SECTOR_FOR_IDENTIFIER_NAME)) { -                  if (el.getAttributeValues() != null && el.getAttributeValues().size() == 1) { -                    final String sectorId = el.getAttributeValues().get(0).getDOM().getTextContent(); -                    final ServiceProviderConfiguration spConfig = pendingReq.getServiceProviderConfiguration( -                        ServiceProviderConfiguration.class); -   -                    try { -                      spConfig.setBpkTargetIdentifier(sectorId); -                      sectorDetected = true; -   -                    } catch (final EaafException e) { -                      log.info("Requested sector: " + sectorId + " DOES NOT match to allowed sectors for SP: " -                          + spConfig.getUniqueIdentifier()); -                    } -   -                  } else { -                    log.info("Req. attribute '" + el.getName() -                        + "' contains NO or MORE THEN ONE attribute-values. Ignore full req. attribute"); -                  } -   -                } else { -                  log.debug("Ignore req. attribute: " + el.getName()); -                } -   -              } -   -            } else { -              log.debug("No requested Attributes in Authn. Request"); -            } -   -          } else { -            log.info("Ignore unknown requested attribute: " + reqAttrObj.getElementQName().toString()); -          } +    } +     +    return false; +  } + +  /** +   * Extract the bPK target from requested attribute. +   *  +   * @param el Requested attribute from AuthnRequest +   * @param spConfig Service-Provider configuration for current process +   * @return <code>true</code> if bPK target extraction was successful, otherwise <code>false</code> +   */ +  private boolean extractBpkTargetIdentifier(EaafRequestedAttribute el, ServiceProviderConfiguration spConfig) {         +    if (el.getAttributeValues() != null && el.getAttributeValues().size() == 1) { +      final String sectorId = el.getAttributeValues().get(0).getDOM().getTextContent();       +      try { +        spConfig.setBpkTargetIdentifier(sectorId); +        return true; + +      } catch (final EaafException e) { +        log.warn("Requested sector: " + sectorId + " DOES NOT match to allowed sectors for SP: " +            + spConfig.getUniqueIdentifier()); +      } + +    } else { +      log.warn("Req. attribute '" + el.getName() +          + "' contains NO or MORE THEN ONE attribute-values. Ignore full req. attribute"); +    } +     +    return false; +     +  } +  private void postprocessLoaLevel(IRequest pendingReq, AuthnRequest authnReq)  +      throws AuthnRequestValidatorException { +    final List<String> reqLoA = extractLoA(authnReq); +    log.trace("SP requests LoA with: {}", String.join(", ",reqLoA)); +     +    LevelOfAssurance minimumLoAFromConfig = LevelOfAssurance.fromString(basicConfig.getBasicConfiguration( +        MsEidasNodeConstants.PROP_EIDAS_REQUEST_LOA_MINIMUM_LEVEL, +        EaafConstants.EIDAS_LOA_HIGH)); +    if (minimumLoAFromConfig == null) { +      log.warn("Can not load minimum LoA from configuration. Use LoA: {} as default", +          EaafConstants.EIDAS_LOA_HIGH); +      minimumLoAFromConfig = LevelOfAssurance.HIGH; + +    } +           +    log.trace("Validate requested LoA to connector configuration minimum LoA: {} ...", +        minimumLoAFromConfig);       +    final List<String> allowedLoA = new ArrayList<>(); +    for (final String loa : reqLoA) { +      try { +        final LevelOfAssurance intLoa = LevelOfAssurance.fromString(loa); +        String selectedLoA = EaafConstants.EIDAS_LOA_HIGH; +        if (intLoa != null  +            && intLoa.numericValue() <= minimumLoAFromConfig.numericValue()) { +          log.info("Client: {} requested LoA: {} will be upgraded to: {}", +              pendingReq.getServiceProviderConfiguration().getUniqueIdentifier(), +              loa, +              minimumLoAFromConfig); +          selectedLoA = minimumLoAFromConfig.getValue(); +          } -      } -      if (!sectorDetected) { -        log.info("Authn.Req validation FAILED. Reason: Contains NO or NO VALID target-sector information."); -        throw new AuthnRequestValidatorException("pvp2.22", new Object[] { -            "NO or NO VALID target-sector information" }); +        if (!allowedLoA.contains(selectedLoA)) { +          log.debug("Allow LoA: {} for Client: {}", +              selectedLoA, +              pendingReq.getServiceProviderConfiguration().getUniqueIdentifier()); +          allowedLoA.add(selectedLoA); -      } +        } -    } catch (final EaafStorageException e) { -      log.info("Can NOT store Authn. Req. data into pendingRequest.", e); -      throw new AuthnRequestValidatorException("internal.02", null, e); +      } catch (final IllegalArgumentException e) { +        log.warn("LoA: {} is currently NOT supported and it will be ignored.", loa); + +      }      } +    pendingReq.getServiceProviderConfiguration(ServiceProviderConfiguration.class).setRequiredLoA( +        allowedLoA); +        }    private String extractComparisonLevel(AuthnRequest authnReq) { diff --git a/connector/src/main/resources/META-INF/services/at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder b/connector/src/main/resources/META-INF/services/at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder new file mode 100644 index 00000000..8508cc4b --- /dev/null +++ b/connector/src/main/resources/META-INF/services/at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder @@ -0,0 +1,2 @@ +at.asitplus.eidas.specific.connector.attributes.AuthBlockAttributeBuilder +at.asitplus.eidas.specific.connector.attributes.EidasBindAttributeBuilder diff --git a/connector/src/main/resources/SpringTest_connector.beans.xml b/connector/src/main/resources/SpringTest_connector.beans.xml new file mode 100644 index 00000000..5cf0d5b8 --- /dev/null +++ b/connector/src/main/resources/SpringTest_connector.beans.xml @@ -0,0 +1,129 @@ +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" +  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +  xmlns:context="http://www.springframework.org/schema/context" +  xmlns:tx="http://www.springframework.org/schema/tx" +  xmlns:aop="http://www.springframework.org/schema/aop" +  xmlns:mvc="http://www.springframework.org/schema/mvc" +  xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd +    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd +    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd +    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd +    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> + +  <context:annotation-config /> +  <mvc:annotation-driven /> +  <mvc:default-servlet-handler /> + +  <bean id="WebResourceConfiguration" +    class="at.asitplus.eidas.specific.connector.config.StaticResourceConfiguration" /> + +  <bean id="ProcessEngineSignalController" +    class="at.asitplus.eidas.specific.connector.controller.ProcessEngineSignalController" /> + +  <bean id="MonitoringController" +    class="at.asitplus.eidas.specific.connector.controller.MonitoringController"> +    <property name="pvpIdpCredentials"> +      <ref bean="PVPEndPointCredentialProvider" /> +    </property> +  </bean> + +  <bean id="AuthenticationManager" +    class="at.asitplus.eidas.specific.connector.auth.AuthenticationManager" /> + +  <bean id="AuthenticationDataBuilder" +    class="at.asitplus.eidas.specific.connector.builder.AuthenticationDataBuilder" /> + +  <bean id="PVPEndPointConfiguration" +    class="at.asitplus.eidas.specific.connector.config.PvpEndPointConfiguration" /> + +  <bean id="PVPEndPointCredentialProvider" +    class="at.asitplus.eidas.specific.connector.provider.PvpEndPointCredentialProvider" /> + +  <bean id="PVPMetadataConfigurationFactory" +    class="at.asitplus.eidas.specific.connector.provider.PvpMetadataConfigurationFactory" /> + +  <bean id="PVP2XProtocol" +    class="at.asitplus.eidas.specific.connector.controller.Pvp2SProfileEndpoint"> +    <property name="pvpIdpCredentials"> +      <ref bean="PVPEndPointCredentialProvider" /> +    </property> +  </bean> + +  <bean id="AuthnRequestValidator" +    class="at.asitplus.eidas.specific.connector.verification.AuthnRequestValidator" /> + +  <bean id="SAMLVerificationEngine" +    class="at.gv.egiz.eaaf.modules.pvp2.impl.verification.SamlVerificationEngine" /> + +  <bean id="pvpMetadataService" +    class="at.gv.egiz.eaaf.modules.pvp2.idp.impl.MetadataAction"> +    <property name="pvpIdpCredentials"> +      <ref bean="PVPEndPointCredentialProvider" /> +    </property> +  </bean> + +  <bean id="PVPAuthenticationRequestAction" +    class="at.gv.egiz.eaaf.modules.pvp2.idp.impl.AuthenticationAction"> +    <property name="pvpIdpCredentials"> +      <ref bean="PVPEndPointCredentialProvider" /> +    </property> +  </bean> + +  <bean id="eaafProtocolAuthenticationService" +    class="at.gv.egiz.eaaf.core.impl.idp.auth.services.ProtocolAuthenticationService"> +    <property name="guiBuilder" ref="mvcGUIBuilderImpl" /> +  </bean> + +  <bean id="securePendingRequestIdGeneration" +    class="at.gv.egiz.eaaf.core.impl.utils.SecurePendingRequestIdGenerationStrategy" /> + +  <bean id="PVPMetadataProvider" +    class="at.asitplus.eidas.specific.connector.provider.PvpMetadataProvider" /> + +  <bean id="PVPSubjectNameGenerator" +    class="at.asitplus.eidas.specific.connector.builder.PvpSubjectNameGenerator" /> + +  <bean id="LoALevelMapper" +    class="at.asitplus.eidas.specific.connector.mapper.LoALevelMapper" /> + +  <bean id="GUIBuilderConfigurationFactory" +    class="at.asitplus.eidas.specific.connector.gui.GuiBuilderConfigurationFactory" /> + +  <bean id="velocityGUIBuilderImpl" +    class="at.asitplus.eidas.specific.connector.gui.DefaultVelocityGuiBuilderImpl" /> + +  <bean id="mvcGUIBuilderImpl" +    class="at.asitplus.eidas.specific.connector.gui.SpringMvcGuiFormBuilderImpl" /> + +  <bean id="templateEngine" +    class="org.thymeleaf.spring5.SpringTemplateEngine"> +    <property name="templateResolver" ref="templateResolver" /> +  </bean> + +  <bean class="org.thymeleaf.spring5.view.ThymeleafViewResolver"> +    <property name="order" value="2" /> +    <property name="templateEngine" ref="templateEngine" /> +    <property name="characterEncoding" value="UTF-8" /> +  </bean> + +  <bean id="StatusMessageProvider" +    class="at.asitplus.eidas.specific.connector.provider.StatusMessageProvider" /> + +  <bean id="eidasRevisionLogger" +    class="at.asitplus.eidas.specific.connector.logger.RevisionLogger" /> + +  <bean id="eidasStatisticLogger" +    class="at.asitplus.eidas.specific.connector.logger.StatisticLogger" /> + + +  <!-- Tasks --> +  <bean id="GenerateCountrySelectionFrameTask" +    class="at.asitplus.eidas.specific.connector.processes.tasks.GenerateCountrySelectionFrameTask" +    scope="prototype" /> + +  <bean id="EvaluateCountrySelectionTask" +    class="at.asitplus.eidas.specific.connector.processes.tasks.EvaluateCountrySelectionTask" +    scope="prototype" /> + +</beans>
\ No newline at end of file diff --git a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/AuthenticationDataBuilderTest.java b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/AuthenticationDataBuilderTest.java new file mode 100644 index 00000000..1721fe61 --- /dev/null +++ b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/AuthenticationDataBuilderTest.java @@ -0,0 +1,107 @@ +package at.asitplus.eidas.specific.connector.test; + + +import at.asitplus.eidas.specific.connector.builder.AuthenticationDataBuilder; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants; +import at.gv.egiz.eaaf.core.api.data.EaafConfigConstants; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EaafAuthenticationException; +import at.gv.egiz.eaaf.core.exceptions.EaafStorageException; +import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper; +import at.gv.egiz.eaaf.core.impl.idp.module.test.DummySpConfiguration; +import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; +import net.shibboleth.utilities.java.support.component.ComponentInitializationException; +import org.apache.commons.lang3.RandomStringUtils; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.opensaml.core.config.InitializationException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import java.util.HashMap; +import java.util.Map; + +import static at.asitplus.eidas.specific.connector.MsEidasNodeConstants.PROP_CONFIG_SP_NEW_EID_MODE; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({"/applicationContext.xml", "/SpringTest_connector.beans.xml", "/eaaf_core.beans.xml", "/eaaf_pvp.beans.xml", "/eaaf_pvp_idp.beans.xml", "/spring/SpringTest-context_simple_storage.xml"}) +@WebAppConfiguration +public class AuthenticationDataBuilderTest { + +  @Autowired +  private AuthenticationDataBuilder authenticationDataBuilder; + +  @Autowired(required = true) +  private IConfiguration basicConfig; + +  private MockHttpServletRequest httpReq; +  private MockHttpServletResponse httpResp; +  private TestRequestImpl pendingReq; + +  private DummySpConfiguration oaParam; + +  private String eidasBind; +  private String authBlock; + + +  @BeforeClass +  public static void classInitializer() throws InitializationException, ComponentInitializationException { +    final String current = new java.io.File(".").toURI().toString(); +    System.setProperty("eidas.ms.configuration", current + "src/test/resources/config/junit_config_3.properties"); + +    EaafOpenSaml3xInitializer.eaafInitialize(); +  } + +  @Before +  public void initialize() throws EaafStorageException { +    httpReq = new MockHttpServletRequest("POST", "https://localhost/ms_connector"); +    httpResp = new MockHttpServletResponse(); +    RequestContextHolder.resetRequestAttributes(); +    RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpReq, httpResp)); + +    final Map<String, String> spConfig = new HashMap<>(); +    spConfig.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, "testSp"); +    spConfig.put("target", "urn:publicid:gv.at:cdid+XX"); +    spConfig.put(PROP_CONFIG_SP_NEW_EID_MODE, "true"); +    oaParam = new DummySpConfiguration(spConfig, basicConfig); + +    pendingReq = new TestRequestImpl(); +    pendingReq.setAuthUrl("https://localhost/ms_connector"); +    pendingReq.setPendingReqId(RandomStringUtils.randomAlphanumeric(10)); +    pendingReq.setSpConfig(oaParam); +    pendingReq.getSessionData(AuthProcessDataWrapper.class).setEidProcess(true); +    authBlock = RandomStringUtils.randomAlphanumeric(20); +    eidasBind = RandomStringUtils.randomAlphanumeric(20); +    pendingReq.getSessionData(AuthProcessDataWrapper.class).setGenericDataToSession(Constants.SZR_AUTHBLOCK, authBlock); +    pendingReq.getSessionData(AuthProcessDataWrapper.class).setGenericDataToSession(Constants.EIDAS_BIND, eidasBind); +    LocaleContextHolder.resetLocaleContext(); +  } + +  @Test +  public void first() throws EaafAuthenticationException { +    IAuthData authData = authenticationDataBuilder.buildAuthenticationData(pendingReq); + +    Assert.assertNotNull("AuthData null", authData); +    Assert.assertNotNull("authBlock null", authData.getGenericData(Constants.SZR_AUTHBLOCK, String.class)); +    Assert.assertNotNull("eidasBind null", authData.getGenericData(Constants.EIDAS_BIND, String.class)); +    Assert.assertNotNull("eidasBind null", authData.getEidasQaaLevel()); +    String authBlock = authData.getGenericData(Constants.SZR_AUTHBLOCK, String.class); +    String eidasBind = authData.getGenericData(Constants.EIDAS_BIND, String.class); + +    Assert.assertEquals("authBlock not equal", authBlock, this.authBlock); +    Assert.assertEquals("eidasBind not equal", eidasBind, this.eidasBind); +  } + +} diff --git a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/AuthnRequestValidatorTest.java b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/AuthnRequestValidatorTest.java index e34c8036..389f561e 100644 --- a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/AuthnRequestValidatorTest.java +++ b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/AuthnRequestValidatorTest.java @@ -33,11 +33,14 @@ import org.xml.sax.SAXException;  import at.asitplus.eidas.specific.connector.MsEidasNodeConstants;  import at.asitplus.eidas.specific.connector.config.ServiceProviderConfiguration;  import at.gv.egiz.eaaf.core.api.data.EaafConfigConstants; -import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.api.idp.IConfigurationWithSP;  import at.gv.egiz.eaaf.core.exceptions.AuthnRequestValidatorException; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.impl.idp.controller.protocols.RequestImpl;  import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl;  import at.gv.egiz.eaaf.core.impl.utils.DomUtils;  import at.gv.egiz.eaaf.modules.pvp2.api.validation.IAuthnRequestPostProcessor; +import at.gv.egiz.eaaf.modules.pvp2.idp.impl.PvpSProfilePendingRequest;  import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer;  import net.shibboleth.utilities.java.support.component.ComponentInitializationException; @@ -53,12 +56,12 @@ import net.shibboleth.utilities.java.support.component.ComponentInitializationEx  @DirtiesContext(classMode = ClassMode.BEFORE_CLASS)  public class AuthnRequestValidatorTest { -  @Autowired private IConfiguration basicConfig; +  @Autowired private IConfigurationWithSP basicConfig;    @Autowired protected IAuthnRequestPostProcessor authRequestValidator;    private MockHttpServletRequest httpReq;    private MockHttpServletResponse httpResp; -  private TestRequestImpl pendingReq; +  private PvpSProfilePendingRequest pendingReq;    /**     * jUnit class initializer. @@ -76,10 +79,11 @@ public class AuthnRequestValidatorTest {    /**     * jUnit test set-up. +   * @throws EaafException      *      */    @Before -  public void initialize() { +  public void initialize() throws EaafException {      httpReq = new MockHttpServletRequest("POST", "https://localhost/ms_connector");      httpResp = new MockHttpServletResponse();      RequestContextHolder.resetRequestAttributes(); @@ -88,10 +92,12 @@ public class AuthnRequestValidatorTest {      Map<String, String> spConfig = new HashMap<>();      spConfig.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, RandomStringUtils.randomAlphabetic(10)); -    pendingReq = new TestRequestImpl(); -    pendingReq.setAuthUrl("https://localhost/ms_connector"); -    pendingReq.setPendingReqId(RandomStringUtils.randomAlphanumeric(10)); -    pendingReq.setSpConfig(new ServiceProviderConfiguration(spConfig, basicConfig)); +    pendingReq = new PvpSProfilePendingRequest(); +    pendingReq.initialize(httpReq, basicConfig); +    pendingReq.setPendingRequestId(RandomStringUtils.randomAlphanumeric(10)); +    pendingReq.setOnlineApplicationConfiguration(new ServiceProviderConfiguration(spConfig, basicConfig));     +    ((RequestImpl)pendingReq).setUniqueTransactionIdentifier(null); +        }    @Test @@ -128,6 +134,8 @@ public class AuthnRequestValidatorTest {      Assert.assertEquals("bPK target not match", "urn:publicid:gv.at:cdid+BF",           pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier()); +    Assert.assertNull("wrong transactionId", pendingReq.getUniqueTransactionIdentifier()); +        }    @Test @@ -164,6 +172,8 @@ public class AuthnRequestValidatorTest {      Assert.assertEquals("bPK target not match", "urn:publicid:gv.at:cdid+BF",           pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier()); +    Assert.assertNull("wrong transactionId", pendingReq.getUniqueTransactionIdentifier()); +        }    @Test @@ -200,6 +210,30 @@ public class AuthnRequestValidatorTest {      Assert.assertEquals("bPK target not match", "urn:publicid:gv.at:cdid+XX",           pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier()); +    Assert.assertEquals("wrong transactionId", "transId_11223344556677aabbcc",  +        pendingReq.getUniqueTransactionIdentifier()); +     +  } +   +  @Test +  public void transactionIdWrongPendingReqType() throws AuthnRequestValidatorException, ParserConfigurationException,  +      SAXException, IOException, UnmarshallingException { +     +    Map<String, String> spConfig = new HashMap<>(); +    spConfig.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, RandomStringUtils.randomAlphabetic(10)); +     +    TestRequestImpl pendingReqLocal = new TestRequestImpl(); +    pendingReqLocal.setPendingReqId(RandomStringUtils.randomAlphanumeric(10)); +    pendingReqLocal.setSpConfig(new ServiceProviderConfiguration(spConfig, basicConfig));     +     +    AuthnRequest authReq = getAuthRequest("/data/pvp2_authn_3.xml"); +     +    //test +    authRequestValidator.process(httpReq, pendingReqLocal, authReq, null); +         +    //validate +    Assert.assertNull("wrong transactionId", pendingReqLocal.getUniqueTransactionIdentifier()); +        }    @Test @@ -214,7 +248,7 @@ public class AuthnRequestValidatorTest {      } catch (AuthnRequestValidatorException e) {        Assert.assertEquals("Wrong errorCode", "pvp2.22", e.getErrorId()); -       +                  }                  } diff --git a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/attributes/AuthBlockAttributeBuilderTest.java b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/attributes/AuthBlockAttributeBuilderTest.java new file mode 100644 index 00000000..b7c6cd44 --- /dev/null +++ b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/attributes/AuthBlockAttributeBuilderTest.java @@ -0,0 +1,97 @@ +package at.asitplus.eidas.specific.connector.test.attributes; + +import static at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions.EID_AUTHBLOCK_SIGNED_NAME; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import at.asitplus.eidas.specific.connector.attributes.AuthBlockAttributeBuilder; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants; +import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; +import at.gv.egiz.eaaf.core.impl.idp.AuthenticationData; +import at.gv.egiz.eaaf.core.impl.idp.auth.attributes.AbstractAttributeBuilderTest; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("/SpringTest-context_eaaf_core.xml") +public class AuthBlockAttributeBuilderTest extends AbstractAttributeBuilderTest { + +  private final String JSW = +      "eyJhbGciOiJQUzI1NiIsIng1dCNTMjU2IjoiTjBDZUJRdzlMX1BleEt6SlhVM2w2dkF1aExGb3hkWFlIUjNSX01ubTZnRSJ9.ImF2YWFz" + +          "YmF2Ig.dpzCcHFlISXyKEZaXgvRj0ja1cenfMuy0VKwK_rmHZLkUCb58V4X5balpQduDTyRfTyFE0zmBjm8_cmDVNOYTIG4NsEtvY" + +          "qW4ee9JH-VpkU0w5-7HTH81R3JOd9g7XaHGPXYyUuqceZQRmkl1Vw4HSsnIAT3bb0Di0us6zmFkOPmRtbXQAym_ygGFwTVGLskUTm" + +          "epCxmDQC7OJoIV9oqDavLySP7Ram4NHfi043uF_DmBf6csTjmQu3g2vKJWwlkD8RXDzqksozO8fLDFyVWjA8G1IcvnuHDW1nTTkuG" + +          "_fBIU6yBZ7kQe9vtjqKiGhGa1zD-F_Lem2zsY7d7dVUvyQ"; +  private final IAttributeBuilder attrBuilde = new AuthBlockAttributeBuilder(); + +  @Rule +  public TestName mTestName = new TestName(); + +  @Before +  public void init() { +    log.info("setting up"); +  } + +  @Test +  public void okTest() { +    log.info("starting: " + mTestName); +    try { +      final IAuthData authData = buildAuthData(); +      ((AuthenticationData) authData).setGenericData(Constants.SZR_AUTHBLOCK, JSW); + +      final String value = attrBuilde.build(spConfig, authData, gen); + +      Assert.assertEquals("Authblock build wrong", JSW, value); + +    } catch (final Exception e) { +      Assert.assertNull("Attr. builder has an exception", e); +    } +  } + + +  @Test +  public void nullTest() { +    log.info("starting: " + mTestName); +    try { +      final IAuthData authData = buildAuthData(); +      ((AuthenticationData) authData).setGenericData(Constants.SZR_AUTHBLOCK, null); + +      final String value = attrBuilde.build(spConfig, authData, gen); +      Assert.fail("Attr. Builder provide no 'UnavailableAttributeException'"); + +    } catch (final Exception e) { +      Assert.assertTrue("Attr. builder provide wrong exception", +                        e instanceof UnavailableAttributeException); +      Assert.assertEquals("Attr. name in exception does NOT match", +                          EID_AUTHBLOCK_SIGNED_NAME, +                          ((UnavailableAttributeException) e).getAttributeName()); +    } +  } + +  @Test +  public void emptyTest() { +    log.info("starting: " + mTestName); +    try { +      final IAuthData authData = buildAuthData(); +      ((AuthenticationData) authData).setGenericData(Constants.SZR_AUTHBLOCK, ""); + +      final String value = attrBuilde.build(spConfig, authData, gen); +      Assert.fail("Attr. Builder provide no 'UnavailableAttributeException'"); + +    } catch (final Exception e) { +      Assert.assertTrue("Attr. builder provide wrong exception", +                        e instanceof UnavailableAttributeException); +      Assert.assertEquals("Attr. name in exception does NOT match", +                          EID_AUTHBLOCK_SIGNED_NAME, +                          ((UnavailableAttributeException) e).getAttributeName());    } +  } +} diff --git a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/attributes/EidasBindAttributeBuilderTest.java b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/attributes/EidasBindAttributeBuilderTest.java new file mode 100644 index 00000000..254efb59 --- /dev/null +++ b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/attributes/EidasBindAttributeBuilderTest.java @@ -0,0 +1,92 @@ +package at.asitplus.eidas.specific.connector.test.attributes; + +import at.asitplus.eidas.specific.connector.attributes.EidasBindAttributeBuilder; +import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions; +import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; +import at.gv.egiz.eaaf.core.impl.idp.AuthenticationData; +import at.gv.egiz.eaaf.core.impl.idp.auth.attributes.AbstractAttributeBuilderTest; +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import static at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants.EIDAS_BIND; + + +@Slf4j +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("/SpringTest-context_eaaf_core.xml") +public class EidasBindAttributeBuilderTest extends AbstractAttributeBuilderTest { + +  private final IAttributeBuilder attrBuilde = new EidasBindAttributeBuilder(); + +  @Rule +  public TestName mTestName = new TestName(); + +  @Before +  public void init() { +    log.info("setting up"); +  } + +  @Test +  public void okTest() { +    log.info("starting: " + mTestName); +    try { +      final IAuthData authData = buildAuthData(); +      ((AuthenticationData) authData).setGenericData(EIDAS_BIND, "vuG8w29GT0"); + +      final String value = attrBuilde.build(spConfig, authData, gen); + +      Assert.assertEquals("eDIAS bind build wrong", "vuG8w29GT0", value); + +    } catch (final Exception e) { +      Assert.assertNull("Attr. builder has an exception", e); +    } +  } + +  @Test +  public void nullTest() { +    log.info("starting: " + mTestName); +    try { +      final IAuthData authData = buildAuthData(); +      ((AuthenticationData) authData).setGenericData(EIDAS_BIND, null); + +      final String value = attrBuilde.build(spConfig, authData, gen); +      Assert.fail("Attr. Builder provide no 'UnavailableAttributeException'"); + +    } catch (final Exception e) { +      Assert.assertTrue("Attr. builder provide wrong exception", +                        e instanceof UnavailableAttributeException); +      Assert.assertEquals("Attr. name in exception does NOT match", +                          ExtendedPvpAttributeDefinitions.EID_EIDBIND_NAME, +                          ((UnavailableAttributeException) e).getAttributeName()); +    } +  } + +  @Test +  public void emptyTest() { +    log.info("starting: " + mTestName); +    try { +      final IAuthData authData = buildAuthData(); +      ((AuthenticationData) authData).setGenericData(EIDAS_BIND, ""); + +      final String value = attrBuilde.build(spConfig, authData, gen); +      Assert.fail("Attr. Builder provide no 'UnavailableAttributeException'"); + +    } catch (final Exception e) { +      Assert.assertTrue("Attr. builder provide wrong exception", +                        e instanceof UnavailableAttributeException); +      Assert.assertEquals("Attr. name in exception does NOT match", +                          ExtendedPvpAttributeDefinitions.EID_EIDBIND_NAME, +                          ((UnavailableAttributeException) e).getAttributeName());    } +  } + + +} diff --git a/connector/src/test/resources/config/junit_config_1.properties b/connector/src/test/resources/config/junit_config_1.properties index 8bff74a9..3350f947 100644 --- a/connector/src/test/resources/config/junit_config_1.properties +++ b/connector/src/test/resources/config/junit_config_1.properties @@ -1,5 +1,5 @@  ## Basic service configuration -eidas.ms.context.url.prefix= +eidas.ms.context.url.prefix=http://localhost  eidas.ms.context.url.request.validation=false  eidas.ms.context.use.clustermode=true @@ -80,12 +80,13 @@ eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.5=LegalName,true  ## PVP2 S-Profile end-point configuration +eidas.ms.pvp2.keystore.type=jks  eidas.ms.pvp2.keystore.path=keys/junit.jks  eidas.ms.pvp2.keystore.password=password -eidas.ms.pvp2.key.metadata.alias= -eidas.ms.pvp2.key.metadata.password= -eidas.ms.pvp2.key.signing.alias= -eidas.ms.pvp2.key.signing.password= +eidas.ms.pvp2.key.metadata.alias=meta +eidas.ms.pvp2.key.metadata.password=password +eidas.ms.pvp2.key.signing.alias=sig +eidas.ms.pvp2.key.signing.password=password  eidas.ms.pvp2.metadata.validity=24  eidas.ms.pvp2.metadata.organisation.name=JUnit diff --git a/connector/src/test/resources/config/junit_config_3.properties b/connector/src/test/resources/config/junit_config_3.properties new file mode 100644 index 00000000..32e30790 --- /dev/null +++ b/connector/src/test/resources/config/junit_config_3.properties @@ -0,0 +1,116 @@ +## Basic service configuration +eidas.ms.context.url.prefix= +eidas.ms.context.url.request.validation=false + +eidas.ms.context.use.clustermode=true + +##Monitoring +eidas.ms.monitoring.eIDASNode.metadata.url= + + +##Specific logger configuration +eidas.ms.technicallog.write.MDS.into.techlog=true +eidas.ms.revisionlog.write.MDS.into.revisionlog=true +eidas.ms.revisionlog.logIPAddressOfUser=true + +##Directory for static Web content +eidas.ms.webcontent.static.directory=webcontent/ +eidas.ms.webcontent.templates=templates/ +eidas.ms.webcontent.properties=properties/messages +eidas.ms.webcontent.templates.countryselection=countrySelection.html + +## extended validation of pending-request Id's +eidas.ms.core.pendingrequestid.maxlifetime=300 +eidas.ms.core.pendingrequestid.digist.algorithm=HmacSHA256 +eidas.ms.core.pendingrequestid.digist.secret=pendingReqIdSecret + +## eIDAS Ref. Implementation connector ### +eidas.ms.auth.eIDAS.node_v2.entityId=ownSpecificConnector +eidas.ms.auth.eIDAS.node_v2.forward.endpoint= +eidas.ms.auth.eIDAS.node_v2.forward.method=POST +eidas.ms.auth.eIDAS.node_v2.countrycode=AT +eidas.ms.auth.eIDAS.node_v2.publicSectorTargets=.* +eidas.ms.auth.eIDAS.node_v2.workarounds.addAlwaysProviderName=true +eidas.ms.auth.eIDAS.node_v2.workarounds.useRequestIdAsTransactionIdentifier=true +eidas.ms.auth.eIDAS.node_v2.workarounds.useStaticProviderNameForPublicSPs=true + +eidas.ms.auth.eIDAS.node_v2.loa.requested.minimum=http://eidas.europa.eu/LoA/substantial + +eidas.ms.auth.eIDAS.szrclient.useTestService=true +eidas.ms.auth.eIDAS.szrclient.endpoint.prod= +eidas.ms.auth.eIDAS.szrclient.endpoint.test=http://localhost:1234/demoszr +eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.path=keys/junit.jks +eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.password=password +eidas.ms.auth.eIDAS.szrclient.ssl.trustStore.path= +eidas.ms.auth.eIDAS.szrclient.ssl.trustStore.password= +eidas.ms.auth.eIDAS.szrclient.timeout.connection=15 +eidas.ms.auth.eIDAS.szrclient.timeout.response=30 +eidas.ms.auth.eIDAS.szrclient.params.vkz= + +eidas.ms.auth.eIDAS.szrclient.params.useSZRForbPKCalculation=false + + +#Raw eIDAS Id data storage +eidas.ms.auth.eIDAS.szrclient.workarounds.eidmapping.revisionlog.active=true + +eidas.ms.auth.eIDAS.szrclient.params.setPlaceOfBirthIfAvailable=true +eidas.ms.auth.eIDAS.szrclient.params.setBirthNameIfAvailable=true + +eidas.ms.auth.eIDAS.szrclient.debug.logfullmessages=true +eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution=true + +##without mandates +eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.0=PersonIdentifier,true +eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.1=FamilyName,true +eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.2=FirstName,true +eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.3=DateOfBirth,true + +eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.4=PlaceOfBirth,false +eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.5=BirthName,false +eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.6=Gender,false +eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.7=CurrentAddress,false + +##with mandates ---- NOT FULLY SUPPORTED AT THE MOMENT ----- +eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.0=PersonIdentifier,true +eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.1=FamilyName,true +eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.2=FirstName,true +eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.3=DateOfBirth,true +eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.4=LegalPerson,true +eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.5=LegalName,true + + +## PVP2 S-Profile end-point configuration +eidas.ms.pvp2.keystore.type=jks +eidas.ms.pvp2.keystore.path=keys/junit.jks +eidas.ms.pvp2.keystore.password=password +eidas.ms.pvp2.key.metadata.alias= +eidas.ms.pvp2.key.metadata.password= +eidas.ms.pvp2.key.signing.alias= +eidas.ms.pvp2.key.signing.password= +eidas.ms.pvp2.metadata.validity=24 + +eidas.ms.pvp2.metadata.organisation.name=JUnit +eidas.ms.pvp2.metadata.organisation.friendyname=For testing with jUnit +eidas.ms.pvp2.metadata.organisation.url=http://junit.test +eidas.ms.pvp2.metadata.contact.givenname=Max +eidas.ms.pvp2.metadata.contact.surname=Mustermann +eidas.ms.pvp2.metadata.contact.email=max@junit.test + +## Service Provider configuration +eidas.ms.sp.0.uniqueID= +eidas.ms.sp.0.pvp2.metadata.truststore=keys/junit.jks +eidas.ms.sp.0.pvp2.metadata.truststore.password=password +eidas.ms.sp.0.newEidMode=true + +#eidas.ms.sp.0.friendlyName= +#eidas.ms.sp.0.pvp2.metadata.url= +#eidas.ms.sp.0.policy.allowed.requested.targets=.* +#eidas.ms.sp.0.policy.hasBaseIdTransferRestriction=false + + +##only for advanced config +eidas.ms.configuration.sp.disableRegistrationRequirement= +eidas.ms.configuration.restrictions.baseID.spTransmission= +eidas.ms.configuration.auth.default.countrycode= +eidas.ms.configuration.pvp.scheme.validation= +eidas.ms.configuration.pvp.enable.entitycategories=
\ No newline at end of file diff --git a/connector/src/test/resources/data/pvp2_authn_2.xml b/connector/src/test/resources/data/pvp2_authn_2.xml index 5f21af05..dbf46622 100644 --- a/connector/src/test/resources/data/pvp2_authn_2.xml +++ b/connector/src/test/resources/data/pvp2_authn_2.xml @@ -28,6 +28,10 @@        <eid:RequestedAttribute FriendlyName="EID-SECTOR-FOR-IDENTIFIER" Name="urn:oid:1.2.40.0.10.2.1.1.261.34" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true">          <eid:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">urn:publicid:gv.at:cdid+BF</eid:AttributeValue>        </eid:RequestedAttribute> +      <eid:RequestedAttribute FriendlyName="transactionId" Name="urn:eidgvat:attributes.transactionId" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"> +        <eid:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">transId_11223344556677aabbcc</eid:AttributeValue> +        <eid:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">transId_second</eid:AttributeValue> +      </eid:RequestedAttribute>      </eid:RequestedAttributes>    </saml2p:Extensions>    <saml2p:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"/> diff --git a/connector/src/test/resources/data/pvp2_authn_3.xml b/connector/src/test/resources/data/pvp2_authn_3.xml index bf356da7..35e49b0f 100644 --- a/connector/src/test/resources/data/pvp2_authn_3.xml +++ b/connector/src/test/resources/data/pvp2_authn_3.xml @@ -28,6 +28,9 @@        <eid:RequestedAttribute FriendlyName="EID-SECTOR-FOR-IDENTIFIER" Name="urn:oid:1.2.40.0.10.2.1.1.261.34" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true">          <eid:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">urn:publicid:gv.at:cdid+XX</eid:AttributeValue>        </eid:RequestedAttribute> +      <eid:RequestedAttribute FriendlyName="transactionId" Name="urn:eidgvat:attributes.transactionId" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"> +        <eid:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">transId_11223344556677aabbcc</eid:AttributeValue> +      </eid:RequestedAttribute>      </eid:RequestedAttributes>    </saml2p:Extensions>    <saml2p:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"/> diff --git a/connector_lib/src/main/java/at/asitplus/eidas/specific/connector/MsEidasNodeConstants.java b/connector_lib/src/main/java/at/asitplus/eidas/specific/connector/MsEidasNodeConstants.java index c28e753a..b1ef799f 100644 --- a/connector_lib/src/main/java/at/asitplus/eidas/specific/connector/MsEidasNodeConstants.java +++ b/connector_lib/src/main/java/at/asitplus/eidas/specific/connector/MsEidasNodeConstants.java @@ -87,6 +87,22 @@ public class MsEidasNodeConstants {    public static final String PROP_EIDAS_REQUEST_LOA_MINIMUM_LEVEL =        "auth.eIDAS.node_v2.loa.requested.minimum"; +  public static final String PROP_CONFIG_AUTHBLOCK_KEYSTORE_TYPE = +      "auth.eIDAS.authblock.keystore.type"; +  public static final String PROP_CONFIG_AUTHBLOCK_KEYSTORE_PATH = +      "auth.eIDAS.authblock.keystore.path"; +  public static final String PROP_CONFIG_AUTHBLOCK_KEYSTORE_PASSWORD = +      "auth.eIDAS.authblock.keystore.password"; +  public static final String PROP_CONFIG_AUTHBLOCK_KEYSTORE_NAME = +      "auth.eIDAS.authblock.keystore.name";   +  public static final String PROP_CONFIG_AUTHBLOCK_KEY_ALIAS = +      "auth.eIDAS.authblock.key.alias"; +  public static final String PROP_CONFIG_AUTHBLOCK_KEY_PASSWORD = +      "auth.eIDAS.authblock.key.password"; +   +   +   +    public static final String PROP_CONFIG_SP_LIST_PREFIX = "sp.";    public static final String PROP_CONFIG_SP_UNIQUEIDENTIFIER = EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER;    public static final String PROP_CONFIG_SP_FRIENDLYNAME = "friendlyName"; @@ -94,6 +110,9 @@ public class MsEidasNodeConstants {    public static final String PROP_CONFIG_SP_PVP2_METADATA_TRUSTSTORE = "pvp2.metadata.truststore";    public static final String PROP_CONFIG_SP_PVP2_METADATA_TRUSTSTORE_PASSWORD =        "pvp2.metadata.truststore.password"; +  public static final String PROP_CONFIG_SP_NEW_EID_MODE = +      "newEidMode"; +    public static final String PROP_CONFIG_SP_POLICY_ALLOWED_TARGETS = "policy.allowed.requested.targets";    public static final String PROP_CONFIG_SP_POLICY_BASEIDTRANSFER_RESTRICTION =        "policy.hasBaseIdTransferRestriction"; diff --git a/eidas_modules/authmodule-eIDAS-v2/pom.xml b/eidas_modules/authmodule-eIDAS-v2/pom.xml index e64aefc7..b2e841fb 100644 --- a/eidas_modules/authmodule-eIDAS-v2/pom.xml +++ b/eidas_modules/authmodule-eIDAS-v2/pom.xml @@ -123,8 +123,10 @@        <groupId>org.apache.cxf</groupId>        <artifactId>cxf-rt-transports-http</artifactId>      </dependency> -    <!-- <dependency> <groupId>org.xerial</groupId> <artifactId>sqlite-jdbc</artifactId>  -      <version>${org.xerial.sqlite-jdbc.version}</version> </dependency> --> +    <dependency> +      <groupId>com.fasterxml.jackson.datatype</groupId> +      <artifactId>jackson-datatype-jsr310</artifactId> +    </dependency>      <dependency>        <groupId>javax.servlet</groupId> @@ -149,6 +151,18 @@        <scope>test</scope>      </dependency>      <dependency> +      <groupId>org.powermock</groupId> +      <artifactId>powermock-module-junit4</artifactId> +      <version>2.0.7</version> +      <scope>test</scope> +    </dependency> +    <dependency> +      <groupId>org.powermock</groupId> +      <artifactId>powermock-api-mockito2</artifactId> +      <version>2.0.7</version> +      <scope>test</scope> +    </dependency> +    <dependency>        <groupId>at.gv.egiz.eaaf</groupId>        <artifactId>eaaf_core_utils</artifactId>        <scope>test</scope> @@ -160,6 +174,17 @@        <scope>test</scope>        <type>test-jar</type>      </dependency> +    <dependency> +      <groupId>com.fasterxml.jackson.core</groupId> +      <artifactId>jackson-databind</artifactId> +      <version>2.11.2</version> +      <scope>compile</scope> +    </dependency> +    <dependency> +      <groupId>org.bitbucket.b_c</groupId> +      <artifactId>jose4j</artifactId> +      <version>0.7.2</version> +    </dependency>    </dependencies>    <build> @@ -168,7 +193,7 @@          <directory>src/main/resources</directory>        </resource>        <resource> -        <directory>target/generated/cxf</directory> +        <directory>target/generated-sources/cxf</directory>        </resource>      </resources> @@ -209,7 +234,7 @@                <sourceRoot>${project.build.directory}/generated/cxf</sourceRoot>                <wsdlOptions>                  <wsdlOption> -                  <wsdl>${basedir}/src/main/resources/szr_client/SZR-1.1.WSDL</wsdl> +                  <wsdl>${basedir}/src/main/resources/szr_client/SZR_v4.0.wsdl</wsdl>                    <extraargs>                      <extraarg>-verbose </extraarg>                    </extraargs> 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 3eec12bd..83a2afa6 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 @@ -156,6 +156,11 @@ public class Constants {    // Default values for SZR communication    public static final String SZR_CONSTANTS_DEFAULT_DOCUMENT_TYPE = "ELEKTR_DOKUMENT"; +  // AuthBlock +  public static final String SZR_AUTHBLOCK = "authData_AUTHBLOCK"; +  public static final String EIDAS_BIND = "authData_EIDAS_BIND"; + +    // TODO remove!!!    public static final String SZR_CONSTANTS_DEFAULT_ISSUING_DATE = "2014-01-01";    public static final String SZR_CONSTANTS_DEFAULT_ISSUING_AUTHORITY = "ms-specific eIDAS-Node for AT"; diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/AuthBlockSigningService.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/AuthBlockSigningService.java new file mode 100644 index 00000000..cfaecfbb --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/service/AuthBlockSigningService.java @@ -0,0 +1,192 @@ +package at.asitplus.eidas.specific.modules.auth.eidas.v2.service; + +import java.security.Key; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.Provider; +import java.security.cert.X509Certificate; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.Base64; +import java.util.UUID; + +import javax.annotation.PostConstruct; + +import org.apache.commons.lang3.StringUtils; +import org.jose4j.lang.JoseException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; + +import at.asitplus.eidas.specific.connector.MsEidasNodeConstants; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.JoseUtils; +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.exception.EaafKeyAccessException; +import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory; +import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreUtils; +import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration; +import at.gv.egiz.eaaf.core.impl.data.Pair; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +/** + * Service to build and sign AuthBlock's for E-ID system. + *  + * @author tlenz + * + */ +@Slf4j +@Service("authBlockSigningService") +public class AuthBlockSigningService { + +  private static final String KEYSTORE_FRIENDLYNAME = "AuthBlock_Signing"; + +  private static ObjectMapper mapper = new ObjectMapper(); +   +  @Autowired +  IConfiguration basicConfig; +   +  @Autowired +  EaafKeyStoreFactory keyStoreFactory; + +   +  private Pair<KeyStore, Provider> keyStore; +   +  /** +   * Build and sign an AuthBlock for E-ID system.  +   *  +   * @param pendingReq data that should be added into AuthBlock +   * @return serialized JWS +   * @throws JsonProcessingException In case of a AuthBlock generation error  +   * @throws JoseException  In case of a JWS signing error +   * @throws EaafException  In case of a KeyStore or Key error +   */ +  public String buildSignedAuthBlock(IRequest pendingReq)  +      throws JsonProcessingException, EaafException, JoseException { +     +    // build AuthBlock +    EidasAuchBlock authBlock = new EidasAuchBlock(); +    authBlock.setChallenge(UUID.randomUUID().toString()); +    authBlock.setTimestamp(LocalDateTime.now().truncatedTo(ChronoUnit.SECONDS)); +    authBlock.setUniqueId(pendingReq.getRawData(MsEidasNodeConstants.DATA_REQUESTERID, String.class));     +    String jwsPayload = mapper.writeValueAsString(authBlock); +    log.debug("Building and sign authBlock with data: {}", jwsPayload); +     +    //sign JWS +    return JoseUtils +        .createSignature(keyStore, getKeyAlias(), getKeyPassword(), jwsPayload, false, +                         KEYSTORE_FRIENDLYNAME);     +  } +   + +  /** +   * Get the Base64 encoded PublicKey that is used to sign the AuthBlock. +   *  +   * @return Base64 encoded PublicKey +   * @throws EaafKeyAccessException In case of an unknown or invalid key +   */ +  public String getBase64EncodedPublicKey() throws EaafKeyAccessException {        +    Pair<Key, X509Certificate[]> keyPair = EaafKeyStoreUtils.getPrivateKeyAndCertificates( +        keyStore.getFirst(), getKeyAlias(), getKeyPassword(), true, KEYSTORE_FRIENDLYNAME);        +    return Base64.getEncoder().encodeToString(keyPair.getSecond()[0].getPublicKey().getEncoded()); +     +  } + +  @PostConstruct +  private void initialize() throws KeyStoreException, EaafException {    +    log.debug("Initializing AuthBlock signing service ... "); +    // read Connector wide config data TODO connector wide!    +    String keyStoreName = basicConfig +        .getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEYSTORE_NAME); +    String keyStorePw = basicConfig +        .getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEYSTORE_PASSWORD); +    String keyStorePath = basicConfig +        .getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEYSTORE_PATH); +    String keyStoreType = basicConfig +        .getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEYSTORE_TYPE); + +     +    //build new KeyStore configuration +    KeyStoreConfiguration keyStoreConfiguration = new KeyStoreConfiguration(); +    keyStoreConfiguration.setFriendlyName(KEYSTORE_FRIENDLYNAME); +     +    keyStoreConfiguration.setSoftKeyStoreFilePath(keyStorePath); +    keyStoreConfiguration.setSoftKeyStorePassword(keyStorePw); +    keyStoreConfiguration.setKeyStoreType(KeyStoreConfiguration.KeyStoreType.fromString(keyStoreType));     +    keyStoreConfiguration.setKeyStoreName(keyStoreName); +     +    //validate KeyStore configuration +    keyStoreConfiguration.validate(); +         +    //validate key alias +    if (StringUtils.isEmpty(getKeyAlias())) { +      throw new EaafConfigurationException("config.08",  +          new Object[] {MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEY_ALIAS}); +       +    } +         +    //build new KeyStore based on configuration +    keyStore =  keyStoreFactory.buildNewKeyStore(keyStoreConfiguration); +     +    //check if Key is accessible +    EaafKeyStoreUtils.getPrivateKeyAndCertificates( +        keyStore.getFirst(), getKeyAlias(), getKeyPassword(), true, KEYSTORE_FRIENDLYNAME); +     +    log.info("AuthBlock signing-service successful initialized"); +     +  }    +   +  private char[] getKeyPassword() { +    final String value = basicConfig.getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEY_PASSWORD); +    if (value != null) { +      return value.trim().toCharArray(); +    } + +    return null; +     +  } + + +  private String getKeyAlias() { +    return basicConfig +        .getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEY_ALIAS); +     +  } +   +  /** +   * Technical AuthBlock for eIDAS Authentication. +   *  +   * @author tlenz +   * +   */ +  @Data +  private static class EidasAuchBlock { + +    @JsonProperty("challenge") +    private String challenge; +     +    @JsonProperty("timestamp") +    @JsonSerialize(using = LocalDateTimeSerializer.class) +    @JsonDeserialize(using = LocalDateTimeDeserializer.class) +    @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") +    private LocalDateTime timestamp; +     +    @JsonProperty("appId") +    private String uniqueId; +     +     +  } + +   +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/szr/SzrClient.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/szr/SzrClient.java index 763d8dab..69b993a4 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/szr/SzrClient.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/szr/SzrClient.java @@ -34,6 +34,8 @@ import java.security.NoSuchAlgorithmException;  import java.security.SecureRandom;  import java.security.UnrecoverableKeyException;  import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap;  import java.util.List;  import java.util.Map; @@ -56,6 +58,8 @@ import javax.xml.ws.BindingProvider;  import javax.xml.ws.Dispatch;  import javax.xml.ws.handler.Handler; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper;  import org.apache.commons.lang3.StringUtils;  import org.apache.cxf.configuration.jsse.TLSClientParameters;  import org.apache.cxf.endpoint.Client; @@ -84,10 +88,15 @@ import szrservices.GetBPKResponse;  import szrservices.GetIdentityLinkEidas;  import szrservices.GetIdentityLinkEidasResponse;  import szrservices.IdentityLinkType; +import szrservices.JwsHeaderParam;  import szrservices.ObjectFactory;  import szrservices.PersonInfoType;  import szrservices.SZR;  import szrservices.SZRException_Exception; +import szrservices.SignContent; +import szrservices.SignContentEntry; +import szrservices.SignContentResponseType; +  @Service("SZRClientForeIDAS")  public class SzrClient { @@ -96,6 +105,13 @@ public class SzrClient {    private static final String CLIENT_DEFAULT = "DefaultClient";    private static final String CLIENT_RAW = "RawClient"; +  private static final String ATTR_NAME_VSZ = "urn:eidgvat:attributes.vsz.value"; +  private static final String ATTR_NAME_PUBKEYS = "urn:eidgvat:attributes.user.pubkeys"; +  private static final String ATTR_NAME_STATUS = "urn:eidgvat:attributes.eid.status"; +  private static final String KEY_BC_BIND = "bcBindReq"; +  private static final String JOSE_HEADER_USERCERTPINNING_TYPE = "urn:at.gv.eid:bindtype"; +  private static final String JOSE_HEADER_USERCERTPINNING_EIDASBIND = "urn:at.gv.eid:eidasBind"; +    @Autowired    private IConfiguration basicConfig; @@ -109,9 +125,11 @@ public class SzrClient {    private String szrUrl = null;    private QName qname = null; +  final ObjectMapper mapper = new ObjectMapper(); +    /**     * Get IdentityLink of a person. -   *  +   *     * @param personInfo Person identification information     * @return IdentityLink     * @throws SzrCommunicationException In case of a SZR error @@ -165,7 +183,7 @@ public class SzrClient {      } catch (final Exception e) {        log.warn("SZR communication FAILED. Reason: " + e.getMessage(), e); -      throw new SzrCommunicationException("ernb.02", new Object[] { e.getMessage() }, e); +      throw new SzrCommunicationException("ernb.02", new Object[]{e.getMessage()}, e);      } @@ -173,19 +191,19 @@ public class SzrClient {    /**     * Get bPK of person. -   *  +   *     * @param personInfo Person identification information -   * @param target requested bPK target -   * @param vkz Verfahrenskennzeichen +   * @param target     requested bPK target +   * @param vkz        Verfahrenskennzeichen     * @return bPK for this person     * @throws SzrCommunicationException In case of a SZR error     */ -  public String getBpk(PersonInfoType personInfo, String target, String vkz) +  public List<String> getBpk(PersonInfoType personInfo, String target, String vkz)        throws SzrCommunicationException {      try {        final GetBPK parameters = new GetBPK();        parameters.setPersonInfo(personInfo); -      parameters.setBereichsKennung(target); +      parameters.getBereichsKennung().add(target);        parameters.setVKZ(vkz);        final GetBPKResponse result = this.szr.getBPK(parameters); @@ -193,16 +211,91 @@ public class SzrClient {      } catch (final SZRException_Exception e) {        log.warn("SZR communication FAILED. Reason: " + e.getMessage(), e); -      throw new SzrCommunicationException("ernb.02", new Object[] { e.getMessage() }, e); +      throw new SzrCommunicationException("ernb.02", new Object[]{e.getMessage()}, e);      }    } +  /** +   * Request a encryped baseId from SRZ. +   * +   * @param personInfo Minimum dataset of person +   * @return encrypted baseId +   * @throws SzrCommunicationException    In case of a SZR error +   */ +  public String getEncryptedStammzahl(final PersonInfoType personInfo) +      throws SzrCommunicationException { + +    final String resp; +    try { +      resp = this.szr.getStammzahlEncrypted(personInfo, 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; + +  } + + +  /** +   * Signs content. +   * +   * @param vsz ? TODO +   * @param bindingPubKey  binding PublikKey as PKCS1# (ASN.1) container +   * @param eidStatus Status of the E-ID +   * @return bPK for this person +   * @throws SzrCommunicationException In case of a SZR error +   */ +  public String getBcBind(final String vsz, final String bindingPubKey, final String eidStatus) +      throws SzrCommunicationException { + +    final Map<String, Object> bcBindMap = new HashMap<>(); +    bcBindMap.put(ATTR_NAME_VSZ, vsz); +    bcBindMap.put(ATTR_NAME_STATUS, eidStatus); +    bcBindMap.put(ATTR_NAME_PUBKEYS, Arrays.asList(bindingPubKey)); + +    try { +      final String serializedBcBind = mapper.writeValueAsString(bcBindMap); +      final SignContent req = new SignContent(); +      final SignContentEntry bcBindInfo = new SignContentEntry(); +      bcBindInfo.setKey(KEY_BC_BIND); +      bcBindInfo.setValue(serializedBcBind); +      req.getIn().add(bcBindInfo); +      req.setAppendCert(false); +      final JwsHeaderParam bcBindJoseHeader = new JwsHeaderParam(); +      bcBindJoseHeader.setKey(JOSE_HEADER_USERCERTPINNING_TYPE); +      bcBindJoseHeader.setValue(JOSE_HEADER_USERCERTPINNING_EIDASBIND); +      req.getJWSHeaderParam().add(bcBindJoseHeader); + +      log.trace("Requesting SZR to sign bcBind datastructure ... "); +      final SignContentResponseType resp = szr.signContent(req.isAppendCert(), req.getJWSHeaderParam(), req.getIn()); +      log.trace("Receive SZR response on bcBind siging operation "); + +      if (resp == null || resp.getOut() == null +          || resp.getOut().isEmpty() +          || StringUtils.isEmpty(resp.getOut().get(0).getValue())) { +        throw new SzrCommunicationException("ernb.01", new Object[]{"BcBind response empty"}); +      } + +      return resp.getOut().get(0).getValue(); + +    } catch (final JsonProcessingException | SZRException_Exception e) { +      log.warn("Requesting bcBind by using SZR FAILED. Reason: {}", e.getMessage(), null, e); +      throw new SzrCommunicationException("ernb.02", +          new Object[]{e.getMessage()}, e); +    } +  } +    @PostConstruct    private void initialize() {      log.info("Starting SZR-Client initialization .... "); -    final URL url = SzrClient.class.getResource("/szr_client/SZR-1.1.WSDL"); +    final URL url = SzrClient.class.getResource("/szr_client/SZR_v4.0.wsdl");      final boolean useTestSzr = basicConfig.getBasicConfigurationBoolean(          Constants.CONIG_PROPS_EIDAS_SZRCLIENT_USETESTSERVICE, 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 88c3515b..f9142f8e 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 @@ -19,10 +19,11 @@   * 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 java.io.IOException;  import java.io.InputStream;  import java.util.HashMap;  import java.util.List; @@ -30,6 +31,7 @@ import java.util.Map;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse; +import javax.xml.parsers.ParserConfigurationException;  import org.apache.commons.lang3.StringUtils;  import org.joda.time.DateTime; @@ -37,6 +39,7 @@ 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.google.common.collect.ImmutableMap;  import com.google.common.collect.ImmutableSet; @@ -47,6 +50,7 @@ import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.ErnbEidData;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.EidasAttributeException;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.SzrCommunicationException; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.AuthBlockSigningService;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.ICcSpecificEidProcessingService;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.szr.SzrClient;  import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.EidasResponseUtils; @@ -71,6 +75,7 @@ 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.Data;  import lombok.extern.slf4j.Slf4j;  import szrservices.IdentityLinkType;  import szrservices.PersonInfoType; @@ -78,9 +83,8 @@ import szrservices.TravelDocumentType;  /**   * Task that creates the IdentityLink for an eIDAS authenticated person. - *  - * @author tlenz   * + * @author tlenz   */  @Slf4j  @Component("CreateIdentityLinkTask") @@ -92,29 +96,30 @@ public class CreateIdentityLinkTask extends AbstractAuthServletTask {    private SzrClient szrClient;    @Autowired    private ICcSpecificEidProcessingService eidPostProcessor; +   +  @Autowired +  private AuthBlockSigningService authBlockSigner; +  private static final String EID_STATUS = "urn:eidgvat:eid.status.eidas"; +      /*     * (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) +  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 ILightResponse eidasResponse = authProcessData +          .getGenericDataFromSession(Constants.DATA_FULL_EIDAS_RESPONSE, ILightResponse.class); -      final Map<String, Object> simpleAttrMap = convertEidasAttrToSimpleMap(eidasResponse.getAttributes() -          .getAttributeMap()); - -      IIdentityLink identityLink = null; -      String bpk = null; +      final Map<String, Object> simpleAttrMap = convertEidasAttrToSimpleMap( +          eidasResponse.getAttributes().getAttributeMap());        // post-process eIDAS attributes        final ErnbEidData eidData = eidPostProcessor.postProcess(simpleAttrMap); @@ -122,178 +127,83 @@ public class CreateIdentityLinkTask extends AbstractAuthServletTask {        // write MDS into technical log and revision log        writeMdsLogInformation(eidData); -      // connect SZR-Gateway -      if (basicConfig.getBasicConfigurationBoolean( -          Constants.CONIG_PROPS_EIDAS_SZRCLIENT_DEBUG_USEDUMMY, false)) { -        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); - -        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.getFormatedDateOfBirth()); - -        identityLink = new SimpleIdentityLinkAssertionParser(idlassertion).parseIdentityLink(); - -        new BpkBuilder(); -        final Pair<String, String> bpkCalc = BpkBuilder.generateAreaSpecificPersonIdentifier( -            identityLink.getIdentificationValue(), -            identityLink.getIdentificationType(), -            pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier()); -        bpk = bpkCalc.getFirst(); - +      //build IdentityLink or VSZ and eidasBind +      if (basicConfig.getBasicConfigurationBoolean(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_DEBUG_USEDUMMY, false)) { +        SzrResultHolder idlResult = createDummyIdentityLinkForTestDeployment(eidData); +        //inject personal-data into session +        authProcessData.setIdentityLink(idlResult.getIdentityLink());   +         +        // set bPK and bPKType into auth session +        authProcessData.setGenericDataToSession(PvpAttributeDefinitions.BPK_NAME, extendBpkByPrefix( +            idlResult.getBpK(), pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier())); +        authProcessData.setGenericDataToSession(PvpAttributeDefinitions.EID_SECTOR_FOR_IDENTIFIER_NAME, +                                                pendingReq.getServiceProviderConfiguration() +                                                          .getAreaSpecificTargetIdentifier()); +                         } else { -        // contact SZR Gateway -        log.debug("Starting connecting SZR Gateway"); -        final PersonInfoType personInfo = new PersonInfoType(); -        final PersonNameType personName = new PersonNameType(); -        final PhysicalPersonType naturalPerson = new PhysicalPersonType(); -        final TravelDocumentType eDocument = new TravelDocumentType(); - -        naturalPerson.setName(personName); -        personInfo.setPerson(naturalPerson); -        personInfo.setTravelDocument(eDocument); - -        // person information -        personName.setFamilyName(eidData.getFamilyName()); -        personName.setGivenName(eidData.getGivenName()); -        naturalPerson.setDateOfBirth(eidData.getFormatedDateOfBirth()); -        eDocument.setIssuingCountry(eidData.getCitizenCountryCode()); -        eDocument.setDocumentNumber(eidData.getPseudonym()); - -        // eID document information -        eDocument.setDocumentType(basicConfig.getBasicConfiguration( -            Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_EDOCUMENTTYPE, -            Constants.SZR_CONSTANTS_DEFAULT_DOCUMENT_TYPE)); - -        // set PlaceOfBirth if available -        if (eidData.getPlaceOfBirth() != null) { -          log.trace("Find 'PlaceOfBirth' attribute: " + eidData.getPlaceOfBirth()); -          if (basicConfig.getBasicConfigurationBoolean( -              Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_SETPLACEOFBIRTHIFAVAILABLE, -              true)) { -            naturalPerson.setPlaceOfBirth(eidData.getPlaceOfBirth()); -            log.trace("Adding 'PlaceOfBirth' to ERnB request ... "); - -          } -        } - -        // set BirthName if available -        if (eidData.getBirthName() != null) { -          log.trace("Find 'BirthName' attribute: " + eidData.getBirthName()); +        //build SZR request from eIDAS data         +        final PersonInfoType personInfo = generateSzrRequest(eidData); +         +        //request SZR based on IDL or E-ID mode +        if (pendingReq.getServiceProviderConfiguration() +            .isConfigurationValue(MsEidasNodeConstants.PROP_CONFIG_SP_NEW_EID_MODE, false)) { + +          // get encrypted baseId +          String vsz = szrClient.getEncryptedStammzahl(personInfo); +                             +          // get eIDAS bind +          String signedEidasBind = szrClient.getBcBind(vsz,  +              authBlockSigner.getBase64EncodedPublicKey(),  +              EID_STATUS); + +          //get signed AuthBlock +          String jwsSignature = authBlockSigner.buildSignedAuthBlock(pendingReq); +        +          //inject personal-data into session +          authProcessData.setGenericDataToSession(Constants.SZR_AUTHBLOCK, jwsSignature); +          authProcessData.setGenericDataToSession(Constants.EIDAS_BIND, signedEidasBind); +                +        } else { +          //request SZR +          SzrResultHolder idlResult = requestSzrForIdentityLink(personInfo); +           +          // write ERnB input-data into revision-log            if (basicConfig.getBasicConfigurationBoolean( -              Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_SETBIRTHNAMEIFAVAILABLE, -              true)) { -            final AlternativeNameType alternativeName = new AlternativeNameType(); -            naturalPerson.setAlternativeName(alternativeName); -            alternativeName.setFamilyName(eidData.getBirthName()); -            log.trace("Adding 'BirthName' to ERnB request ... "); +              Constants.CONIG_PROPS_EIDAS_SZRCLIENT_WORKAROUND_REVISIONLOGDATASTORE_ACTIVE, false)) { +            revisionsLogger.logEvent(pendingReq, MsConnectorEventCodes.SZR_ERNB_EIDAS_RAW_ID, +                                     (String) simpleAttrMap.get(Constants.eIDAS_ATTR_PERSONALIDENTIFIER)); +            revisionsLogger.logEvent(pendingReq, MsConnectorEventCodes.SZR_ERNB_EIDAS_ERNB_ID, eidData.getPseudonym());            } +           +          //check result-data and write revision-log based on current state +          checkStateAndWriteRevisionLog(idlResult); +           + +          //inject personal-data into session +          authProcessData.setIdentityLink(idlResult.getIdentityLink());   +           +          // set bPK and bPKType into auth session +          authProcessData.setGenericDataToSession(PvpAttributeDefinitions.BPK_NAME, extendBpkByPrefix( +              idlResult.getBpK(), pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier())); +          authProcessData.setGenericDataToSession(PvpAttributeDefinitions.EID_SECTOR_FOR_IDENTIFIER_NAME, +                                                  pendingReq.getServiceProviderConfiguration() +                                                            .getAreaSpecificTargetIdentifier()); +                    } - -        final IdentityLinkType result = szrClient.getIdentityLinkInRawMode(personInfo); - -        final Element idlFromSzr = (Element) result.getAssertion(); -        identityLink = new SimpleIdentityLinkAssertionParser(idlFromSzr).parseIdentityLink(); - -        // write ERnB inputdata into revisionlog -        if (basicConfig.getBasicConfigurationBoolean( -            Constants.CONIG_PROPS_EIDAS_SZRCLIENT_WORKAROUND_REVISIONLOGDATASTORE_ACTIVE, false)) { -          revisionsLogger.logEvent(pendingReq, -              MsConnectorEventCodes.SZR_ERNB_EIDAS_RAW_ID, -              (String) simpleAttrMap.get(Constants.eIDAS_ATTR_PERSONALIDENTIFIER)); -          revisionsLogger.logEvent(pendingReq, -              MsConnectorEventCodes.SZR_ERNB_EIDAS_ERNB_ID, eidData.getPseudonym()); - -        } - -        // get bPK from SZR -        if (basicConfig.getBasicConfigurationBoolean( -            Constants.CONIG_PROPS_EIDAS_SZRCLIENT_DEBUG_USESRZFORBPKGENERATION, true)) { -          bpk = szrClient.getBpk( -              personInfo, -              pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier(), -              basicConfig.getBasicConfiguration( -                  Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_VKZ, -                  "no VKZ defined")); - -        } else { -          log.debug("Calculating bPK from baseId ... "); -          new BpkBuilder(); -          final Pair<String, String> bpkCalc = BpkBuilder.generateAreaSpecificPersonIdentifier( -              identityLink.getIdentificationValue(), -              identityLink.getIdentificationType(), -              pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier()); -          bpk = bpkCalc.getFirst(); - -        } - -      } - -      if (identityLink == null) { -        log.error("ERnB did not return an identity link."); -        throw new SzrCommunicationException("ernb.00", null); - -      } -      revisionsLogger.logEvent(pendingReq, MsConnectorEventCodes.SZR_IDL_RECEIVED, -          identityLink.getSamlAssertion().getAttribute(SimpleIdentityLinkAssertionParser.ASSERTIONID)); - -      if (bpk == null) { -        log.error("ERnB did not return a bPK for target: " + pendingReq.getServiceProviderConfiguration() -            .getAreaSpecificTargetIdentifier()); -        throw new SzrCommunicationException("ernb.01", null); -        } -      revisionsLogger.logEvent(pendingReq, MsConnectorEventCodes.SZR_BPK_RECEIVED); - -      log.debug("ERnB communication was successfull"); - +       +      //add generic info's into session        authProcessData.setForeigner(true); -      authProcessData.setIdentityLink(identityLink); -      authProcessData.setGenericDataToSession( -          PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, -          EidasResponseUtils.parseEidasPersonalIdentifier((String) simpleAttrMap.get( -              Constants.eIDAS_ATTR_PERSONALIDENTIFIER)).getFirst()); - -      // set bPK and bPKType into auth session -      authProcessData.setGenericDataToSession( -          PvpAttributeDefinitions.BPK_NAME, -          extendBpkByPrefix( -              bpk, -              pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier())); -      authProcessData.setGenericDataToSession( -          PvpAttributeDefinitions.EID_SECTOR_FOR_IDENTIFIER_NAME, -          pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier()); - +      authProcessData.setGenericDataToSession(PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, EidasResponseUtils +          .parseEidasPersonalIdentifier((String) simpleAttrMap.get(Constants.eIDAS_ATTR_PERSONALIDENTIFIER)) +          .getFirst()); +      authProcessData.setQaaLevel(eidasResponse.getLevelOfAssurance()); +                   // store pending-request        requestStoreage.storePendingRequest(pendingReq); - +       +            } catch (final EidasAttributeException e) {        throw new TaskExecutionException(pendingReq, "Minimum required eIDAS attributeset not found.", e); @@ -307,6 +217,116 @@ public class CreateIdentityLinkTask extends AbstractAuthServletTask {      }    } +  private PersonInfoType generateSzrRequest(ErnbEidData eidData) { +    log.debug("Starting connecting SZR Gateway"); +    final PersonInfoType personInfo = new PersonInfoType(); +    final PersonNameType personName = new PersonNameType(); +    final PhysicalPersonType naturalPerson = new PhysicalPersonType(); +    final TravelDocumentType eDocument = new TravelDocumentType(); + +    naturalPerson.setName(personName); +    personInfo.setPerson(naturalPerson); +    personInfo.setTravelDocument(eDocument); + +    // person information +    personName.setFamilyName(eidData.getFamilyName()); +    personName.setGivenName(eidData.getGivenName()); +    naturalPerson.setDateOfBirth(eidData.getFormatedDateOfBirth()); +    eDocument.setIssuingCountry(eidData.getCitizenCountryCode()); +    eDocument.setDocumentNumber(eidData.getPseudonym()); + +    // eID document information +    eDocument.setDocumentType(basicConfig +                                  .getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_EDOCUMENTTYPE, +                                                         Constants.SZR_CONSTANTS_DEFAULT_DOCUMENT_TYPE)); + +    // set PlaceOfBirth if available +    if (eidData.getPlaceOfBirth() != null) { +      log.trace("Find 'PlaceOfBirth' attribute: " + eidData.getPlaceOfBirth()); +      if (basicConfig +          .getBasicConfigurationBoolean(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_SETPLACEOFBIRTHIFAVAILABLE, +                                        true)) { +        naturalPerson.setPlaceOfBirth(eidData.getPlaceOfBirth()); +        log.trace("Adding 'PlaceOfBirth' to ERnB request ... "); + +      } +    } + +    // set BirthName if available +    if (eidData.getBirthName() != null) { +      log.trace("Find 'BirthName' attribute: " + eidData.getBirthName()); +      if (basicConfig +          .getBasicConfigurationBoolean(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_SETBIRTHNAMEIFAVAILABLE, +                                        true)) { +        final AlternativeNameType alternativeName = new AlternativeNameType(); +        naturalPerson.setAlternativeName(alternativeName); +        alternativeName.setFamilyName(eidData.getBirthName()); +        log.trace("Adding 'BirthName' to ERnB request ... "); + +      } +    } +     +    return personInfo; +     +  } + +  private SzrResultHolder requestSzrForIdentityLink(PersonInfoType personInfo)  +      throws SzrCommunicationException, EaafException { +    //request IdentityLink from SZR +    final IdentityLinkType result = szrClient.getIdentityLinkInRawMode(personInfo); +     +    final Element idlFromSzr = (Element) result.getAssertion(); +    IIdentityLink identityLink = new SimpleIdentityLinkAssertionParser(idlFromSzr).parseIdentityLink(); + +    // get bPK from SZR +    String bpk; +    if (basicConfig +        .getBasicConfigurationBoolean(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_DEBUG_USESRZFORBPKGENERATION, true)) { +      bpk = szrClient +          .getBpk(personInfo, pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier(), +                  basicConfig +                      .getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_VKZ, "no VKZ defined")) +          .get(0); + +    } else { +      log.debug("Calculating bPK from baseId ... "); +      new BpkBuilder(); +      final Pair<String, String> bpkCalc = BpkBuilder +          .generateAreaSpecificPersonIdentifier(identityLink.getIdentificationValue(), +                                                identityLink.getIdentificationType(), +                                                pendingReq.getServiceProviderConfiguration() +                                                          .getAreaSpecificTargetIdentifier()); +      bpk = bpkCalc.getFirst(); + +    } +     +    return new SzrResultHolder(identityLink, bpk); +     +  } +   +  private void checkStateAndWriteRevisionLog(SzrResultHolder idlResult) throws SzrCommunicationException { +    // write some infos into revision log +    if (idlResult.getIdentityLink() == null) { +      log.error("ERnB did not return an identity link."); +      throw new SzrCommunicationException("ernb.00", null); + +    } +    revisionsLogger.logEvent(pendingReq, +                             MsConnectorEventCodes.SZR_IDL_RECEIVED, +                             idlResult.getIdentityLink().getSamlAssertion() +                                         .getAttribute(SimpleIdentityLinkAssertionParser.ASSERTIONID)); + +    if (idlResult.getBpK() == null) { +      log.error("ERnB did not return a bPK for target: " + pendingReq.getServiceProviderConfiguration() +                                                                     .getAreaSpecificTargetIdentifier()); +      throw new SzrCommunicationException("ernb.01", null); + +    } +    revisionsLogger.logEvent(pendingReq, MsConnectorEventCodes.SZR_BPK_RECEIVED); +    log.debug("ERnB communication was successfull"); +         +  } +      private String extendBpkByPrefix(String bpk, String type) {      String bpkType = null; @@ -336,10 +356,9 @@ public class CreateIdentityLinkTask extends AbstractAuthServletTask {      for (final AttributeDefinition<?> el : attributeMap.keySet()) { -      final Class parameterizedType = el.getParameterizedType(); +      final Class<?> parameterizedType = el.getParameterizedType();        if (DateTime.class.equals(parameterizedType)) { -        final DateTime attribute = EidasResponseUtils.translateDateAttribute(el, attributeMap.get(el) -            .asList()); +        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()); @@ -349,8 +368,8 @@ public class CreateIdentityLinkTask extends AbstractAuthServletTask {          }        } else if (PostalAddress.class.equals(parameterizedType)) { -        final PostalAddress addressAttribute = EidasResponseUtils.translateAddressAttribute(el, attributeMap -            .get(el).asList()); +        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()); @@ -360,8 +379,8 @@ public class CreateIdentityLinkTask extends AbstractAuthServletTask {          }        } else { -        final List<String> natPersonIdObj = EidasResponseUtils.translateStringListAttribute(el, attributeMap -            .get(el).asList()); +        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); @@ -381,25 +400,87 @@ public class CreateIdentityLinkTask extends AbstractAuthServletTask {    private void writeMdsLogInformation(ErnbEidData eidData) {      // log MDS and country code into technical log -    if (basicConfig.getBasicConfigurationBoolean( -        MsEidasNodeConstants.PROP_CONFIG_TECHNICALLOG_WRITE_MDS_INTO_TECH_LOG, false)) { -      log.info("eIDAS Auth. for user: " -          + eidData.getGivenName() + " " -          + eidData.getFamilyName() + " " -          + eidData.getFormatedDateOfBirth() + " " -          + "from " + eidData.getCitizenCountryCode()); +    if (basicConfig +        .getBasicConfigurationBoolean(MsEidasNodeConstants.PROP_CONFIG_TECHNICALLOG_WRITE_MDS_INTO_TECH_LOG, false)) { +      log.info("eIDAS Auth. for user: " + eidData.getGivenName() + " " + eidData.getFamilyName() + " " + eidData +          .getFormatedDateOfBirth() + " " + "from " + eidData.getCitizenCountryCode());      }      // log MDS and country code into revision log -    if (basicConfig.getBasicConfigurationBoolean( -        MsEidasNodeConstants.PROP_CONFIG_REVISIONLOG_WRITE_MDS_INTO_REVISION_LOG, false)) { +    if (basicConfig +        .getBasicConfigurationBoolean(MsEidasNodeConstants.PROP_CONFIG_REVISIONLOG_WRITE_MDS_INTO_REVISION_LOG, +                                      false)) {        revisionsLogger.logEvent(pendingReq, MsConnectorEventCodes.RESPONSE_FROM_EIDAS_MDSDATA, -          "{" + eidData.getGivenName() + "," -              + eidData.getFamilyName() + "," -              + eidData.getFormatedDateOfBirth() + "," -              + eidData.getCitizenCountryCode() + "}"); +                               "{" + eidData.getGivenName() + "," + eidData.getFamilyName() + "," + eidData +                                   .getFormatedDateOfBirth() + "," + eidData.getCitizenCountryCode() + "}");      }    } +   +  @Data +  private static class SzrResultHolder {     +    final IIdentityLink identityLink; +    final String bpK; +     +  } +     +  /** +   * Build a dummy IdentityLink and a dummy bPK based on eIDAS information. +   *  +   * <br><br> +   * <b>FOR LOCAL TESTING ONLY!!!</b> +   *  +   * @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(ErnbEidData 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.getFormatedDateOfBirth()); + +    identityLink = new SimpleIdentityLinkAssertionParser(idlassertion).parseIdentityLink(); + +    final Pair<String, String> bpkCalc = BpkBuilder +        .generateAreaSpecificPersonIdentifier(identityLink.getIdentificationValue(), +                                              identityLink.getIdentificationType(), +                                              pendingReq.getServiceProviderConfiguration() +                                                        .getAreaSpecificTargetIdentifier());    +    return new SzrResultHolder(identityLink, bpkCalc.getFirst()); +     +  }  } diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/utils/JoseUtils.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/utils/JoseUtils.java new file mode 100644 index 00000000..e81c4c92 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/utils/JoseUtils.java @@ -0,0 +1,305 @@ +package at.asitplus.eidas.specific.modules.auth.eidas.v2.utils; + +import at.gv.egiz.eaaf.core.exception.EaafKeyUsageException; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreUtils; +import at.gv.egiz.eaaf.core.impl.data.Pair; +import at.gv.egiz.eaaf.core.impl.utils.X509Utils; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.jose4j.jca.ProviderContext; +import org.jose4j.jwa.AlgorithmConstraints; +import org.jose4j.jws.AlgorithmIdentifiers; +import org.jose4j.jws.JsonWebSignature; +import org.jose4j.jwx.Headers; +import org.jose4j.jwx.JsonWebStructure; +import org.jose4j.keys.resolvers.X509VerificationKeyResolver; +import org.jose4j.lang.JoseException; +import org.springframework.util.Base64Utils; + +import javax.annotation.Nonnull; +import java.io.IOException; +import java.security.Key; +import java.security.KeyStore; +import java.security.Provider; +import java.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.RSAPrivateKey; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +/** + * {@link JoseUtils} provides static methods JWS and JWE processing. + * + * @author tlenz + * + */ +@Slf4j +public class JoseUtils { + +  /** +   * Create a JWS signature. +   * +   * <p> +   * Use {@link AlgorithmIdentifiers.RSA_PSS_USING_SHA256} in case +   * of a RSA based key and +   * {@link AlgorithmIdentifiers.ECDSA_USING_P256_CURVE_AND_SHA256} +   * in case of an ECC based key. +   * </p> +   * +   * @param keyStore               KeyStore that should be used +   * @param keyAlias               Alias of the private key +   * @param keyPassword            Password to access the key +   * @param payLoad                PayLoad to sign +   * @param addFullCertChain       If true the full certificate chain will be +   *                               added, otherwise only the +   *                               X509CertSha256Fingerprint is added into JOSE +   *                               header +   * @param friendlyNameForLogging FriendlyName for the used KeyStore for logging +   *                               purposes only +   * @return Signed PayLoad in serialized form +   * @throws EaafException In case of a key-access or key-usage error +   * @throws JoseException In case of a JOSE error +   */ +  public static String createSignature(@Nonnull Pair<KeyStore, Provider> keyStore, +      @Nonnull final String keyAlias, @Nonnull final char[] keyPassword, +      @Nonnull final String payLoad, boolean addFullCertChain, +      @Nonnull String friendlyNameForLogging) throws EaafException, JoseException { +    return createSignature(keyStore, keyAlias, keyPassword, payLoad, addFullCertChain, Collections.emptyMap(), +        AlgorithmIdentifiers.RSA_PSS_USING_SHA256, AlgorithmIdentifiers.ECDSA_USING_P256_CURVE_AND_SHA256, +        friendlyNameForLogging); + +  } + +  /** +   * Create a JWS signature. +   * +   * <p> +   * Use {@link AlgorithmIdentifiers.RSA_PSS_USING_SHA256} in case +   * of a RSA based key and +   * {@link AlgorithmIdentifiers.ECDSA_USING_P256_CURVE_AND_SHA256} +   * in case of an ECC based key. +   * </p> +   * +   * @param keyStore               KeyStore that should be used +   * @param keyAlias               Alias of the private key +   * @param keyPassword            Password to access the key +   * @param payLoad                PayLoad to sign +   * @param addFullCertChain       If true the full certificate chain will be +   *                               added, otherwise only the +   *                               X509CertSha256Fingerprint is added into JOSE +   *                               header +   * @param joseHeaders            HeaderName and HeaderValue that should be set +   *                               into JOSE header +   * @param friendlyNameForLogging FriendlyName for the used KeyStore for logging +   *                               purposes only +   * @return Signed PayLoad in serialized form +   * @throws EaafException In case of a key-access or key-usage error +   * @throws JoseException In case of a JOSE error +   */ +  public static String createSignature(@Nonnull Pair<KeyStore, Provider> keyStore, +      @Nonnull final String keyAlias, @Nonnull final char[] keyPassword, +      @Nonnull final String payLoad, boolean addFullCertChain, +      @Nonnull final Map<String, String> joseHeaders, +      @Nonnull String friendlyNameForLogging) throws EaafException, JoseException { +    return createSignature(keyStore, keyAlias, keyPassword, payLoad, addFullCertChain, joseHeaders, +        AlgorithmIdentifiers.RSA_PSS_USING_SHA256, AlgorithmIdentifiers.ECDSA_USING_P256_CURVE_AND_SHA256, +        friendlyNameForLogging); + +  } + +  /** +   * Create a JWS signature. +   * +   * @param keyStore               KeyStore that should be used +   * @param keyAlias               Alias of the private key +   * @param keyPassword            Password to access the key +   * @param payLoad                PayLoad to sign +   * @param addFullCertChain       If true the full certificate chain will be +   *                               added, otherwise only the +   *                               X509CertSha256Fingerprint is added into JOSE +   *                               header +   * @param joseHeaders            HeaderName and HeaderValue that should be set +   *                               into JOSE header +   * @param rsaAlgToUse            Signing algorithm that should be used in case +   *                               of a signing key based on RSA +   * @param eccAlgToUse            Signing algorithm that should be used in case +   *                               of a signing key based on ECC +   * @param friendlyNameForLogging FriendlyName for the used KeyStore for logging +   *                               purposes only +   * @return Signed PayLoad in serialized form +   * @throws EaafException In case of a key-access or key-usage error +   * @throws JoseException In case of a JOSE error +   */ +  public static String createSignature(@Nonnull Pair<KeyStore, Provider> keyStore, +      @Nonnull final String keyAlias, @Nonnull final char[] keyPassword, +      @Nonnull final String payLoad, boolean addFullCertChain, +      @Nonnull final Map<String, String> joseHeaders, +      @Nonnull final String rsaAlgToUse, @Nonnull final String eccAlgToUse, +      @Nonnull String friendlyNameForLogging) throws EaafException, JoseException { + +    final JsonWebSignature jws = new JsonWebSignature(); + +    // set payload +    jws.setPayload(payLoad); + +    // set JOSE headers +    for (final Entry<String, String> el : joseHeaders.entrySet()) { +      log.trace("Set JOSE header: {} with value: {} into JWS", el.getKey(), el.getValue()); +      jws.setHeader(el.getKey(), el.getValue()); + +    } + +    // set signing information +    final Pair<Key, X509Certificate[]> signingCred = EaafKeyStoreUtils.getPrivateKeyAndCertificates( +        keyStore.getFirst(), keyAlias, keyPassword, true, friendlyNameForLogging); +    jws.setKey(signingCred.getFirst()); +    jws.setAlgorithmHeaderValue(getKeyOperationAlgorithmFromCredential( +        jws.getKey(), rsaAlgToUse, eccAlgToUse, friendlyNameForLogging)); + +    // set special provider if required +    if (keyStore.getSecond() != null) { +      log.trace("Injecting special Java Security Provider: {}", keyStore.getSecond().getName()); +      final ProviderContext providerCtx = new ProviderContext(); +      providerCtx.getSuppliedKeyProviderContext().setSignatureProvider( +          keyStore.getSecond().getName()); +      jws.setProviderContext(providerCtx); + +    } + +    if (addFullCertChain) { +      jws.setCertificateChainHeaderValue(signingCred.getSecond()); + +    } + +    jws.setX509CertSha256ThumbprintHeaderValue(signingCred.getSecond()[0]); + +    return jws.getCompactSerialization(); + +  } + +  /** +   * Verify a JOSE signature. +   * +   * @param serializedContent Serialized content that should be verified +   * @param trustedCerts      Trusted certificates that should be used for +   *                          verification +   * @param constraints       {@link AlgorithmConstraints} for verification +   * @return {@link JwsResult} object +   * @throws JoseException In case of a signature verification error +   * @throws IOException   In case of a general error +   */ +  public static JwsResult validateSignature(@Nonnull final String serializedContent, +      @Nonnull final List<X509Certificate> trustedCerts, @Nonnull final AlgorithmConstraints constraints) +      throws JoseException, IOException { +    final JsonWebSignature jws = new JsonWebSignature(); +    // set payload +    jws.setCompactSerialization(serializedContent); + +    // set security constrains +    jws.setAlgorithmConstraints(constraints); + +    // load signinc certs +    Key selectedKey = null; +    final List<X509Certificate> x5cCerts = jws.getCertificateChainHeaderValue(); +    final String x5t256 = jws.getX509CertSha256ThumbprintHeaderValue(); +    if (x5cCerts != null) { +      log.debug("Found x509 certificate in JOSE header ... "); +      log.trace("Sorting received X509 certificates ... "); +      final List<X509Certificate> sortedX5cCerts = X509Utils.sortCertificates(x5cCerts); + +      if (trustedCerts.contains(sortedX5cCerts.get(0))) { +        selectedKey = sortedX5cCerts.get(0).getPublicKey(); + +      } else { +        log.info("Can NOT find JOSE certificate in truststore."); +        if (log.isDebugEnabled()) { +          try { +            log.debug("Cert: {}", Base64Utils.encodeToString(sortedX5cCerts.get(0).getEncoded())); + +          } catch (final CertificateEncodingException e) { +            log.warn("Can not create DEBUG output", e); + +          } +        } +      } + +    } else if (StringUtils.isNotEmpty(x5t256)) { +      log.debug("Found x5t256 fingerprint in JOSE header .... "); +      final X509VerificationKeyResolver x509VerificationKeyResolver = new X509VerificationKeyResolver( +          trustedCerts); +      selectedKey = x509VerificationKeyResolver.resolveKey(jws, Collections.<JsonWebStructure>emptyList()); + +    } else { +      throw new JoseException("JWS contains NO signature certificate or NO certificate fingerprint"); + +    } + +    if (selectedKey == null) { +      throw new JoseException("Can NOT select verification key for JWS. Signature verification FAILED"); + +    } + +    // set verification key +    jws.setKey(selectedKey); + +    // load payLoad +    return new JwsResult( +        jws.verifySignature(), +        jws.getUnverifiedPayload(), +        jws.getHeaders(), +        x5cCerts); + +  } + +  /** +   * Select signature algorithm for a given credential. +   * +   * @param key                    {@link X509Credential} that will be used for +   *                               key operations +   * @param rsaSigAlgorithm        RSA based algorithm that should be used in case +   *                               of RSA credential +   * @param ecSigAlgorithm         EC based algorithm that should be used in case +   *                               of RSA credential +   * @param friendlyNameForLogging KeyStore friendlyName for logging purposes +   * @return either the RSA based algorithm or the EC based algorithm +   * @throws EaafKeyUsageException In case of an unsupported private-key type +   */ +  private static String getKeyOperationAlgorithmFromCredential(Key key, +      String rsaSigAlgorithm, String ecSigAlgorithm, String friendlyNameForLogging) +      throws EaafKeyUsageException { +    if (key instanceof RSAPrivateKey) { +      return rsaSigAlgorithm; + +    } else if (key instanceof ECPrivateKey) { +      return ecSigAlgorithm; + +    } else { +      log.warn("Could NOT select the cryptographic algorithm from Private-Key type"); +      throw new EaafKeyUsageException(EaafKeyUsageException.ERROR_CODE_01, +          friendlyNameForLogging, +          "Can not select cryptographic algorithm"); + +    } + +  } + +  private JoseUtils() { + +  } + +  @Getter +  @AllArgsConstructor +  public static class JwsResult { +    final boolean valid; +    final String payLoad; +    final Headers fullJoseHeader; +    final List<X509Certificate> x5cCerts; + +  } +} 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 fbb48229..6cc704ab 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 @@ -58,6 +58,9 @@    <!-- <bean id="eIDASDataStore" class="at.asitplus.eidas.specific.modules.auth.eidas.v2.service.eIDASDataStore"       /> --> +  <bean id="authBlockSigningService" +        class="at.asitplus.eidas.specific.modules.auth.eidas.v2.service.AuthBlockSigningService" /> +    <bean id="EIDPostProcessingService"      class="at.asitplus.eidas.specific.modules.auth.eidas.v2.service.CcSpecificEidProcessingService" /> diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/resources/szr_client/SZR_v4.0.wsdl b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/szr_client/SZR_v4.0.wsdl new file mode 100644 index 00000000..e7f296bd --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/szr_client/SZR_v4.0.wsdl @@ -0,0 +1,441 @@ +<?xml version="1.0" encoding="UTF-8"?> +<definitions targetNamespace="urn:SZRServices" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:ecdsa="http://www.w3.org/2001/04/xmldsig-more#" xmlns:pd="http://reference.e-government.gv.at/namespace/persondata/20020228#" xmlns:pvp="http://egov.gv.at/pvp1.xsd" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:szr="urn:SZRServices" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext" xmlns:xs="http://www.w3.org/2001/XMLSchema"> +    <types> +			<xs:schema> +				<xs:import namespace="urn:SZRServices" schemaLocation="szr_v4.0.xsd"/> +			</xs:schema> +		</types> +	<message name="Header"> +		<part name="SecurityHeader" element="wsse:Security" /> +	</message> +	<message name="GetIdentityLinkRequest"> +		<part element="szr:GetIdentityLink" name="parameters" /> +	</message> +	<message name="GetIdentityLinkResponse"> +		<part element="szr:GetIdentityLinkResponse" name="parameters" /> +	</message> +	<message name="GetIdentityLinkEidasRequest"> +		<part element="szr:GetIdentityLinkEidas" name="parameters" /> +	</message> +	<message name="GetIdentityLinkEidasResponse"> +		<part element="szr:GetIdentityLinkEidasResponse" name="parameters" /> +	</message> +	<message name="GetBPKRequest"> +		<part element="szr:GetBPK" name="parameters" /> +	</message> +	<message name="GetBPKResponse"> +		<part element="szr:GetBPKResponse" name="parameters" /> +	</message> +	<message name="GetBPKsRequest"> +		<part element="szr:GetBPKs" name="parameters" /> +	</message> +	<message name="GetBPKsResponse"> +		<part element="szr:GetBPKsResponse" name="parameters" /> +	</message> +	<message name="GetBPKKombiRequest"> +		<part element="szr:GetBPKKombi" name="parameters" /> +	</message> +	<message name="GetBPKKombiResponse"> +		<part element="szr:GetBPKKombiResponse" name="parameters" /> +	</message> +	<message name="GetBPKZPVRequest"> +		<part element="szr:GetBPKZPV" name="parameters" /> +	</message> +	<message name="GetBPKZPVResponse"> +		<part element="szr:GetBPKZPVResponse" name="parameters" /> +	</message> +	<message name="GetBPKFromStammzahlEncryptedRequest"> +		<part element="szr:GetBPKFromStammzahlEncrypted" name="parameters" /> +	</message> +	<message name="GetBPKFromStammzahlEncryptedResponse"> +		<part element="szr:GetBPKFromStammzahlEncryptedResponse" name="parameters" /> +	</message> +	<message name="SignContentRequest"> +		<part element="szr:SignContent" name="parameters" /> +	</message> +	<message name="SignContentResponse"> +		<part element="szr:SignContentResponse" name="parameters" /> +	</message> +	<message name="BPKzuBasiszahlRequest"> +		<part element="szr:BPKzuBasiszahl" name="parameters" /> +	</message> +	<message name="BPKzuBasiszahlResponse"> +		<part element="szr:BPKzuBasiszahlResponse" name="parameters" /> +	</message> +	<message name="BasiszahlZuBPKRequest"> +		<part element="szr:BasiszahlZuBPK" name="parameters" /> +	</message> +	<message name="BasiszahlZuBPKResponse"> +		<part element="szr:BasiszahlZuBPKResponse" name="parameters" /> +	</message> +	<message name="ValidateIdentityLinkRequest"> +		<part element="szr:ValidateIdentityLink" name="parameters" /> +	</message> +	<message name="ValidateIdentityLinkResponse"> +		<part element="szr:ValidateIdentityLinkResponse" name="parameters" /> +	</message> +	<message name="TransformBPKRequest"> +		<part element="szr:TransformBPK" name="parameters" /> +	</message> +	<message name="TransformBPKResponse"> +		<part element="szr:TransformBPKResponse" name="parameters" /> +	</message> +	<message name="GetVKZPermissionRequest"> +		<part element="szr:GetVKZPermission" name="parameters" /> +	</message> +	<message name="GetVKZPermissionResponse"> +		<part element="szr:GetVKZPermissionResponse" name="parameters" /> +	</message> +	<message name="ZMRAnwendungsIntegrationRequest"> +		<part element="szr:ZMRAnwendungsIntegration" name="parameters" /> +	</message> +	<message name="ZMRAnwendungsIntegrationResponse"> +		<part element="szr:ZMRAnwendungsIntegrationResponse" name="parameters" /> +	</message> +	<message name="GetStammzahlRequest"> +		<part element="szr:GetStammzahl" name="parameters" /> +	</message> +	<message name="GetStammzahlResponse"> +		<part element="szr:GetStammzahlResponse" name="parameters" /> +	</message> +	<message name="GetStammzahlEncryptedRequest"> +		<part element="szr:GetStammzahlEncrypted" name="parameters" /> +	</message> +	<message name="GetStammzahlEncryptedResponse"> +		<part element="szr:GetStammzahlEncryptedResponse" name="parameters" /> +	</message> +	<message name="GetVersionRequest"> +		<part element="szr:GetVersion" name="parameters" /> +	</message> +	<message name="GetVersionResponse"> +		<part element="szr:GetVersionResponse" name="parameters" /> +	</message> +	<message name="SZRException"> +		<part element="szr:SZRException" name="fault" /> +	</message> +	<portType name="SZR"> +		<operation name="GetIdentityLink"> +			<input message="szr:GetIdentityLinkRequest" name="GetIdentityLinkRequest" /> +			<output message="szr:GetIdentityLinkResponse" name="GetIdentityLinkResponse" /> +			<fault message="szr:SZRException" name="SZRException" /> +		</operation> +		<operation name="GetIdentityLinkEidas"> +			<input message="szr:GetIdentityLinkEidasRequest" name="GetIdentityLinkEidasRequest" /> +			<output message="szr:GetIdentityLinkEidasResponse" name="GetIdentityLinkEidasResponse" /> +			<fault message="szr:SZRException" name="SZRException" /> +		</operation> +		<operation name="GetBPK"> +			<jaxws:bindings xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"> +				<jaxws:enableWrapperStyle>false</jaxws:enableWrapperStyle> +			</jaxws:bindings> +			<input message="szr:GetBPKRequest" name="GetBPKRequest" /> +			<output message="szr:GetBPKResponse" name="GetBPKResponse" /> +			<fault message="szr:SZRException" name="SZRException" /> +		</operation> +		<operation name="GetBPKs"> +			<input message="szr:GetBPKsRequest" name="GetBPKsRequest" /> +			<output message="szr:GetBPKsResponse" name="GetBPKsResponse" /> +			<fault message="szr:SZRException" name="SZRException" /> +		</operation> +		<operation name="GetBPKKombi"> +			<input message="szr:GetBPKKombiRequest" name="GetBPKKombiRequest" /> +			<output message="szr:GetBPKKombiResponse" name="GetBPKKombiResponse" /> +			<fault message="szr:SZRException" name="SZRException" /> +		</operation> +		<operation name="GetBPKZPV"> +			<input message="szr:GetBPKZPVRequest" name="GetBPKZPVRequest" /> +			<output message="szr:GetBPKZPVResponse" name="GetBPKZPVResponse" /> +			<fault message="szr:SZRException" name="SZRException" /> +		</operation> +		<operation name="GetBPKFromStammzahlEncrypted"> +			<input message="szr:GetBPKFromStammzahlEncryptedRequest" name="GetBPKFromStammzahlEncryptedRequest" /> +			<output message="szr:GetBPKFromStammzahlEncryptedResponse" name="GetBPKFromStammzahlEncryptedResponse" /> +			<fault message="szr:SZRException" name="SZRException" /> +		</operation> +		<operation name="SignContent"> +			<input message="szr:SignContentRequest" name="SignContentRequest" /> +			<output message="szr:SignContentResponse" name="SignContentResponse" /> +			<fault message="szr:SZRException" name="SZRException" /> +		</operation> +		<operation name="ValidateIdentityLink"> +			<input message="szr:ValidateIdentityLinkRequest" name="ValidateIdentityLinkRequest" /> +			<output message="szr:ValidateIdentityLinkResponse" name="ValidateIdentityLinkResponse" /> +			<fault message="szr:SZRException" name="SZRException" /> +		</operation> +		<operation name="TransformBPK"> +			<input message="szr:TransformBPKRequest" name="TransformBPKRequest" /> +			<output message="szr:TransformBPKResponse" name="TransformBPKResponse" /> +			<fault message="szr:SZRException" name="SZRException" /> +		</operation> +		<operation name="GetVKZPermission"> +			<input message="szr:GetVKZPermissionRequest" name="GetVKZPermissionRequest" /> +			<output message="szr:GetVKZPermissionResponse" name="GetVKZPermissionResponse" /> +			<fault message="szr:SZRException" name="SZRException" /> +		</operation> +		<operation name="BPKzuBasiszahl"> +			<input message="szr:BPKzuBasiszahlRequest" name="BPKzuBasiszahlRequest" /> +			<output message="szr:BPKzuBasiszahlResponse" name="BPKzuBasiszahlResponse" /> +			<fault message="szr:SZRException" name="SZRException" /> +		</operation> +		<operation name="BasiszahlZuBPK"> +			<input message="szr:BasiszahlZuBPKRequest" name="BasiszahlZuBPKRequest" /> +			<output message="szr:BasiszahlZuBPKResponse" name="BasiszahlZuBPKResponse" /> +			<fault message="szr:SZRException" name="SZRException" /> +		</operation> +		<operation name="ZMRAnwendungsIntegration"> +			<input message="szr:ZMRAnwendungsIntegrationRequest" name="ZMRAnwendungsIntegrationRequest" /> +			<output message="szr:ZMRAnwendungsIntegrationResponse" name="ZMRAnwendungsIntegrationResponse" /> +			<fault message="szr:SZRException" name="SZRException" /> +		</operation> +		<operation name="GetStammzahl"> +			<input message="szr:GetStammzahlRequest" name="GetStammzahlRequest" /> +			<output message="szr:GetStammzahlResponse" name="GetStammzahlResponse" /> +			<fault message="szr:SZRException" name="SZRException" /> +		</operation> +		<operation name="GetStammzahlEncrypted"> +			<input message="szr:GetStammzahlEncryptedRequest" name="GetStammzahlEncryptedRequest" /> +			<output message="szr:GetStammzahlEncryptedResponse" name="GetStammzahlEncryptedResponse" /> +			<fault message="szr:SZRException" name="SZRException" /> +		</operation> +		<operation name="GetVersion"> +			<input message="szr:GetVersionRequest" name="GetVersionRequest" /> +			<output message="szr:GetVersionResponse" name="GetVersionResponse" /> +			<fault message="szr:SZRException" name="SZRException" /> +		</operation> +	</portType> +	<binding name="SZRSoapBinding" type="szr:SZR"> +		<wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> +		<operation name="GetIdentityLink"> +			<wsdlsoap:operation soapAction="" /> +			<input name="GetIdentityLinkRequest"> +				<wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" /> +				<wsdlsoap:body use="literal" /> +			</input> +			<output name="GetIdentityLinkResponse"> +				<wsdlsoap:body use="literal" /> +			</output> +			<fault name="SZRException"> +				<wsdlsoap:fault name="SZRException" use="literal" /> +			</fault> +		</operation> +		<operation name="GetIdentityLinkEidas"> +			<wsdlsoap:operation soapAction="" /> +			<input name="GetIdentityLinkEidasRequest"> +				<wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" /> +				<wsdlsoap:body use="literal" /> +			</input> +			<output name="GetIdentityLinkEidasResponse"> +				<wsdlsoap:body use="literal" /> +			</output> +			<fault name="SZRException"> +				<wsdlsoap:fault name="SZRException" use="literal" /> +			</fault> +		</operation> +		<operation name="GetBPK"> +			<wsdlsoap:operation soapAction="" /> +			<input name="GetBPKRequest"> +				<wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" /> +				<wsdlsoap:body use="literal" /> +			</input> +			<output name="GetBPKResponse"> +				<wsdlsoap:body use="literal" /> +			</output> +			<fault name="SZRException"> +				<wsdlsoap:fault name="SZRException" use="literal" /> +			</fault> +		</operation> +		<operation name="GetBPKs"> +			<wsdlsoap:operation soapAction="" /> +			<input name="GetBPKsRequest"> +				<wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" /> +				<wsdlsoap:body use="literal" /> +			</input> +			<output name="GetBPKsResponse"> +				<wsdlsoap:body use="literal" /> +			</output> +			<fault name="SZRException"> +				<wsdlsoap:fault name="SZRException" use="literal" /> +			</fault> +		</operation> +		<operation name="GetBPKKombi"> +			<wsdlsoap:operation soapAction="" /> +			<input name="GetBPKKombiRequest"> +				<wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" /> +				<wsdlsoap:body use="literal" /> +			</input> +			<output name="GetBPKKombiResponse"> +				<wsdlsoap:body use="literal" /> +			</output> +			<fault name="SZRException"> +				<wsdlsoap:fault name="SZRException" use="literal" /> +			</fault> +		</operation> +		<operation name="GetBPKZPV"> +			<wsdlsoap:operation soapAction="" /> +			<input name="GetBPKZPVRequest"> +				<wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" /> +				<wsdlsoap:body use="literal" /> +			</input> +			<output name="GetBPKZPVResponse"> +				<wsdlsoap:body use="literal" /> +			</output> +			<fault name="SZRException"> +				<wsdlsoap:fault name="SZRException" use="literal" /> +			</fault> +		</operation> +		<operation name="GetBPKFromStammzahlEncrypted"> +			<wsdlsoap:operation soapAction="" /> +			<input name="GetBPKFromStammzahlEncryptedRequest"> +				<wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" /> +				<wsdlsoap:body use="literal" /> +			</input> +			<output name="GetBPKFromStammzahlEncryptedResponse"> +				<wsdlsoap:body use="literal" /> +			</output> +			<fault name="SZRException"> +				<wsdlsoap:fault name="SZRException" use="literal" /> +			</fault> +		</operation> +		<operation name="SignContent"> +			<wsdlsoap:operation soapAction="" /> +			<input name="SignContentRequest"> +				<wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" /> +				<wsdlsoap:body use="literal" /> +			</input> +			<output name="SignContentResponse"> +				<wsdlsoap:body use="literal" /> +			</output> +			<fault name="SZRException"> +				<wsdlsoap:fault name="SZRException" use="literal" /> +			</fault> +		</operation> +		<operation name="GetVKZPermission"> +			<wsdlsoap:operation soapAction="" /> +			<input name="GetVKZPermissionRequest"> +				<wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" /> +				<wsdlsoap:body use="literal" /> +			</input> +			<output name="GetVKZPermissionResponse"> +				<wsdlsoap:body use="literal" /> +			</output> +			<fault name="SZRException"> +				<wsdlsoap:fault name="SZRException" use="literal" /> +			</fault> +		</operation> +		<operation name="ValidateIdentityLink"> +			<wsdlsoap:operation soapAction="" /> +			<input name="ValidateIdentityLinkRequest"> +				<wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" /> +				<wsdlsoap:body use="literal" /> +			</input> +			<output name="ValidateIdentityLinkResponse"> +				<wsdlsoap:body use="literal" /> +			</output> +			<fault name="SZRException"> +				<wsdlsoap:fault name="SZRException" use="literal" /> +			</fault> +		</operation> +		<operation name="TransformBPK"> +			<wsdlsoap:operation soapAction="" /> +			<input name="TransformBPKRequest"> +				<wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" /> +				<wsdlsoap:body use="literal" /> +			</input> +			<output name="TransformBPKResponse"> +				<wsdlsoap:body use="literal" /> +			</output> +			<fault name="SZRException"> +				<wsdlsoap:fault name="SZRException" use="literal" /> +			</fault> +		</operation> +		<operation name="BPKzuBasiszahl"> +			<wsdlsoap:operation soapAction="" /> +			<input name="BPKzuBasiszahlRequest"> +				<wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" /> +				<wsdlsoap:body use="literal" /> +			</input> +			<output name="BPKzuBasiszahlResponse"> +				<wsdlsoap:body use="literal" /> +			</output> +			<fault name="SZRException"> +				<wsdlsoap:fault name="SZRException" use="literal" /> +			</fault> +		</operation> +		<operation name="BasiszahlZuBPK"> +			<wsdlsoap:operation soapAction="" /> +			<input name="BasiszahlZuBPKRequest"> +				<wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" /> +				<wsdlsoap:body use="literal" /> +			</input> +			<output name="BasiszahlZuBPKResponse"> +				<wsdlsoap:body use="literal" /> +			</output> +			<fault name="SZRException"> +				<wsdlsoap:fault name="SZRException" use="literal" /> +			</fault> +		</operation> +		<operation name="ZMRAnwendungsIntegration"> +			<wsdlsoap:operation soapAction="" /> +			<input name="ZMRAnwendungsIntegrationRequest"> +				<wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" /> +				<wsdlsoap:body use="literal" /> +			</input> +			<output name="ZMRAnwendungsIntegrationResponse"> +				<wsdlsoap:body use="literal" /> +			</output> +			<fault name="SZRException"> +				<wsdlsoap:fault name="SZRException" use="literal" /> +			</fault> +		</operation> +		<operation name="GetStammzahl"> +			<wsdlsoap:operation soapAction="" /> +			<input name="GetStammzahlRequest"> +				<wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" /> +				<wsdlsoap:body use="literal" /> +			</input> +			<output name="GetStammzahlResponse"> +				<wsdlsoap:body use="literal" /> +			</output> +			<fault name="SZRException"> +				<wsdlsoap:fault name="SZRException" use="literal" /> +			</fault> +		</operation> +		<operation name="GetStammzahlEncrypted"> +			<wsdlsoap:operation soapAction="" /> +			<input name="GetStammzahlEncryptedRequest"> +				<wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" /> +				<wsdlsoap:body use="literal" /> +			</input> +			<output name="GetStammzahlEncryptedResponse"> +				<wsdlsoap:body use="literal" /> +			</output> +			<fault name="SZRException"> +				<wsdlsoap:fault name="SZRException" use="literal" /> +			</fault> +		</operation> +		<operation name="GetVersion"> +			<wsdlsoap:operation soapAction="" /> +			<input name="GetVersionRequest"> +				<wsdlsoap:header message="szr:Header" part="SecurityHeader" use="literal" /> +				<wsdlsoap:body use="literal" /> +			</input> +			<output name="GetVersionResponse"> +				<wsdlsoap:body use="literal" /> +			</output> +			<fault name="SZRException"> +				<wsdlsoap:fault name="SZRException" use="literal" /> +			</fault> +		</operation> +	</binding> +	<service name="SZRService"> +		<port binding="szr:SZRSoapBinding" name="SZRBusinesspartnerTestumgebung"> +			<wsdlsoap:address location="https://pvawp.bmi.gv.at/at.gv.bmi.szrsrv-b/services/SZR" /> +		</port> +		<port binding="szr:SZRSoapBinding" name="SZRTestumgebung"> +			<wsdlsoap:address location="https://pvawp.bmi.gv.at/bmi.gv.at/soap/SZ2Services-T/services/SZR" /> +		</port> +		<port binding="szr:SZRSoapBinding" name="SZRProduktionsumgebung"> +			<wsdlsoap:address location="https://pvawp.bmi.gv.at/bmi.gv.at/soap/SZ2Services/services/SZR" /> +		</port> +	</service> +</definitions>
\ No newline at end of file diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/resources/szr_client/pvp19.xsd b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/szr_client/pvp19.xsd new file mode 100644 index 00000000..596a2b99 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/szr_client/pvp19.xsd @@ -0,0 +1,133 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- edited with XMLSPY v2004 rel. 2 U (http://www.xmlspy.com) by BM (Bundeskanzleramt) --> +<!-- PVP Schema 1.8.10 --> +<!-- pvpToken wird über das Element <Security> aus der Spezifikation WS-Security in den SOAP-Header eingebunden --> +<!--erstellt: rainer.hoerbe@bmi.gv.at 2004-04-30 --> +<!--geändert: rainer.hoerbe@beko.at 2007-04-04: Extensions Points definiert --> +<xs:schema targetNamespace="http://egov.gv.at/pvp1.xsd" xmlns="http://egov.gv.at/pvp1.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified"> +	<xs:element name="pvpToken"> +		<xs:complexType> +			<xs:complexContent> +				<xs:extension base="pvpTokenType" /> +			</xs:complexContent> +		</xs:complexType> +	</xs:element> +	<xs:complexType name="pvpTokenType"> +		<xs:sequence> +			<xs:element name="authenticate"> +				<xs:complexType> +					<xs:sequence> +						<xs:element name="participantId" type="xs:string" /> +						<xs:element name="gvOuDomain" type="xs:string" minOccurs="0" maxOccurs="1" /> +						<xs:choice> +							<xs:element name="userPrincipal"> +								<xs:complexType> +									<xs:complexContent> +										<xs:extension base="pvpPrincipalType"> +											<xs:sequence> +												<xs:element name="gvGid" type="xs:string" /> +												<xs:element name="mail" type="xs:string" minOccurs="0" maxOccurs="1" /> +												<xs:element name="tel" type="xs:string" minOccurs="0" maxOccurs="1" /> +												<xs:element name="bpk" type="xs:string" minOccurs="0" maxOccurs="1" /> +												<xs:element name="gvFunction" type="xs:string" minOccurs="0" maxOccurs="1" /> +											</xs:sequence> +										</xs:extension> +									</xs:complexContent> +								</xs:complexType> +							</xs:element> +							<xs:element name="systemPrincipal" type="pvpPrincipalType" /> +						</xs:choice> +						<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"> +							<xs:annotation> +								<xs:documentation>additional authentication properties</xs:documentation> +							</xs:annotation> +						</xs:any> +					</xs:sequence> +				</xs:complexType> +			</xs:element> +			<xs:element name="authorize" minOccurs="0" maxOccurs="1"> +				<xs:complexType> +					<xs:sequence> +						<xs:sequence minOccurs="0"> +							<xs:element name="gvOuId" type="xs:string" /> +							<xs:element name="ou" type="xs:string" /> +						</xs:sequence> +						<xs:element name="role" maxOccurs="unbounded"> +							<xs:complexType> +								<xs:sequence> +									<xs:any namespace="##any" processContents="skip" minOccurs="0" maxOccurs="unbounded" /> +								</xs:sequence> +								<xs:attribute name="value" type="xs:string" use="required" /> +							</xs:complexType> +						</xs:element> +						<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"> +							<xs:annotation> +								<xs:documentation>additional authorization properties</xs:documentation> +							</xs:annotation> +						</xs:any> +					</xs:sequence> +				</xs:complexType> +			</xs:element> +			<xs:element name="accounting" minOccurs="0"> +				<xs:complexType> +					<xs:sequence> +						<xs:any processContents="skip" minOccurs="0" maxOccurs="unbounded" /> +					</xs:sequence> +				</xs:complexType> +			</xs:element> +			<xs:element name="pvpChainedToken" type="pvpTokenType" minOccurs="0" /> +			<xs:element name="pvpExtension" block="extension" minOccurs="0"> +				<xs:complexType> +					<xs:sequence> +						<xs:any namespace="##any" processContents="skip" minOccurs="0" maxOccurs="unbounded" /> +					</xs:sequence> +				</xs:complexType> +			</xs:element> +		</xs:sequence> +		<xs:attribute name="version" type="gvVersionType" use="required" /> +		<xs:anyAttribute namespace="##any" processContents="lax" /> +	</xs:complexType> +	<xs:complexType name="pvpPrincipalType"> +		<xs:sequence> +			<xs:element name="userId" type="xs:string" /> +			<xs:element name="cn" type="xs:string" /> +			<xs:element name="gvOuId" type="xs:string" /> +			<xs:element name="ou" type="xs:string" /> +			<xs:element name="gvOuOKZ" type="xs:string" minOccurs="0" /> +			<xs:element name="gvSecClass" type="gvSecClassType" minOccurs="0" /> +			<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"> +				<xs:annotation> +					<xs:documentation>additional principal attributes</xs:documentation> +				</xs:annotation> +			</xs:any> +		</xs:sequence> +		<xs:anyAttribute namespace="##any" processContents="lax" /> +	</xs:complexType> +	<xs:simpleType name="gvSecClassType"> +		<xs:restriction base="xs:integer"> +			<xs:enumeration value="0" /> +			<xs:enumeration value="1" /> +			<xs:enumeration value="2" /> +			<xs:enumeration value="3" /> +		</xs:restriction> +	</xs:simpleType> +	<xs:simpleType name="gvVersionType"> +		<xs:restriction base="xs:string"> +			<xs:enumeration value="1.0" /> +			<xs:enumeration value="1.1" /> +			<xs:enumeration value="1.2" /> +			<xs:enumeration value="1.8" /> +			<xs:enumeration value="1.9" /> +		</xs:restriction> +	</xs:simpleType> +	<xs:simpleType name="logLevelType"> +		<xs:restriction base="xs:integer"> +			<xs:enumeration value="0" /> +			<xs:enumeration value="1" /> +			<xs:enumeration value="2" /> +			<xs:enumeration value="3" /> +			<xs:enumeration value="4" /> +			<xs:enumeration value="5" /> +		</xs:restriction> +	</xs:simpleType> +</xs:schema> diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_ecdsa.xsd b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_ecdsa.xsd new file mode 100644 index 00000000..87ee80be --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_ecdsa.xsd @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" +           targetNamespace="http://www.w3.org/2001/04/xmldsig-more#" xmlns:ecdsa="http://www.w3.org/2001/04/xmldsig-more#"> +    <xs:element name="ECDSAKeyValue" type="ecdsa:ECDSAKeyValueType" /> +    <xs:complexType name="ECDSAKeyValueType"> +        <xs:sequence> +            <xs:element name="DomainParameters" type="ecdsa:DomainParamsType" +                        minOccurs="0" /> +            <xs:element name="PublicKey" type="ecdsa:ECPointType" /> +        </xs:sequence> +    </xs:complexType> +    <xs:complexType name="DomainParamsType"> +        <xs:sequence> +            <xs:element name="NamedCurve" minOccurs="0" +                        type="ecdsa:NamedCurveType" /> +        </xs:sequence> +    </xs:complexType> +    <xs:complexType name="NamedCurveType"> +        <xs:attribute name="URN" type="xs:string" use="required" /> +    </xs:complexType> +    <xs:complexType name="ECPointType"> +        <xs:sequence minOccurs="0"> +            <xs:element name="X" type="ecdsa:PrimeFieldElemType" /> +            <xs:element name="Y" type="ecdsa:PrimeFieldElemType" /> +        </xs:sequence> +    </xs:complexType> +    <xs:complexType name="PrimeFieldElemType"> +        <xs:attribute name="Value" type="xs:string" use="required" /> +    </xs:complexType> +</xs:schema>
\ No newline at end of file diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_persondata.xsd b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_persondata.xsd new file mode 100644 index 00000000..3c9ac932 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_persondata.xsd @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xs:schema elementFormDefault="qualified" xmlns:pd="http://reference.e-government.gv.at/namespace/persondata/20020228#" +	targetNamespace="http://reference.e-government.gv.at/namespace/persondata/20020228#" xmlns:xs="http://www.w3.org/2001/XMLSchema"> +  <xs:complexType name="PhysicalPersonType"> +    <xs:sequence> +      <xs:element minOccurs="0" name="Identification" type="pd:IdentificationType" /> +      <xs:element minOccurs="1" name="Name" type="pd:PersonNameType" /> +      <xs:element minOccurs="0" name="AlternativeName" type="pd:AlternativeNameType" /> +      <xs:element minOccurs="0" name="Sex" type="xs:string" /> +      <xs:element minOccurs="0" name="DateOfBirth" type="xs:string" /> +      <xs:element minOccurs="0" name="PlaceOfBirth" type="xs:string" /> +      <xs:element minOccurs="0" name="CountryOfBirth" type="xs:string" /> +      <xs:element minOccurs="0" name="Nationality" type="xs:string" /> +    </xs:sequence> +  </xs:complexType> +  <xs:complexType name="IdentificationType"> +    <xs:sequence> +      <xs:element minOccurs="0" name="Value" type="xs:string" /> +      <xs:element minOccurs="0" name="Type" type="xs:string" /> +    </xs:sequence> +  </xs:complexType> +  <xs:complexType name="PersonNameType"> +    <xs:sequence> +      <xs:element minOccurs="0" name="PrefixedDegree" type="xs:string" /> +      <xs:element name="GivenName" type="xs:string" nillable="true" /> +      <xs:element name="FamilyName" type="xs:string" nillable="true" /> +      <xs:element minOccurs="0" name="SuffixedDegree" type="xs:string" /> +    </xs:sequence> +  </xs:complexType> +  <xs:complexType name="AlternativeNameType"> +    <xs:sequence> +      <xs:element name="FamilyName" type="xs:string" nillable="true" /> +    </xs:sequence> +  </xs:complexType> +  <xs:complexType name="PostalAddressType"> +    <xs:sequence> +      <xs:element minOccurs="0" name="PostalCode" type="xs:string" /> +      <xs:element minOccurs="0" name="Municipality" type="xs:string" /> +      <xs:element minOccurs="0" name="Locality" type="xs:string" /> +      <xs:element minOccurs="0" name="StateCode3" type="xs:string" /> +      <xs:element minOccurs="0" name="DeliveryAddress" type="pd:DeliveryAddressType" /> +      <xs:element minOccurs="0" name="HistoricRecord" type="xs:boolean" /> +    </xs:sequence> +  </xs:complexType> +  <xs:complexType name="DeliveryAddressType"> +    <xs:sequence> +      <xs:element minOccurs="0" name="AddressLine" type="xs:string" /> +      <xs:element minOccurs="0" name="StreetName" type="xs:string" /> +      <xs:element minOccurs="0" name="BuildingNumber" type="xs:string" /> +      <xs:element minOccurs="0" name="Unit" type="xs:string" /> +      <xs:element minOccurs="0" name="DoorNumber" type="xs:string" /> +    </xs:sequence> +  </xs:complexType> +</xs:schema>
\ No newline at end of file diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_pvp_sec.xsd b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_pvp_sec.xsd new file mode 100644 index 00000000..5001c1b8 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_pvp_sec.xsd @@ -0,0 +1,10 @@ +<xs:schema xmlns:pvp="http://egov.gv.at/pvp1.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://schemas.xmlsoap.org/ws/2002/04/secext" elementFormDefault="qualified"> +	<xs:import namespace="http://egov.gv.at/pvp1.xsd" schemaLocation="pvp19.xsd"/> +	<xs:element name="Security"> +		<xs:complexType> +			<xs:sequence> +				<xs:element ref="pvp:pvpToken"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element>  +</xs:schema> diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_v4.0-schemas.xml b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_v4.0-schemas.xml new file mode 100644 index 00000000..d40efa45 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_v4.0-schemas.xml @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="UTF-8"?> +<bindings version="2.0" xmlns="http://java.sun.com/xml/ns/jaxb" +	xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" +	xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"> + +  <bindings schemaLocation="../szr_v4/szr_v4.0.xsd"> +		<bindings node="/xsd:schema"> +			<schemaBindings> +				<package name="at.gv.util.xsd.szr_v4" /> +			</schemaBindings> +		</bindings> +	</bindings> +   +	<bindings schemaLocation="../szr/szr_ecdsa.xsd"> +		<bindings node="/xsd:schema"> +			<schemaBindings> +				<package name="at.gv.util.xsd.szr.ecdsa" /> +			</schemaBindings> +		</bindings> +	</bindings> + +	<bindings schemaLocation="../szr_v4/szr_persondata.xsd"> +		<bindings node="/xsd:schema"> +			<schemaBindings> +				<package name="at.gv.util.xsd.szr.persondata" /> +			</schemaBindings> +		</bindings> +	</bindings> + +	<bindings schemaLocation="../szr_v4/szr_pvp_sec.xsd"> +		<bindings node="/xsd:schema"> +			<schemaBindings> +				<package name="at.gv.util.xsd.szr.pvp19.sec" /> +			</schemaBindings> +		</bindings> +	</bindings> + +	<bindings schemaLocation="../szr_v4/pvp19.xsd"> +		<bindings node="/xsd:schema"> +			<schemaBindings> +				<package name="at.gv.util.xsd.szr.pvp19" /> +			</schemaBindings> +		</bindings> +	</bindings> + +  <bindings schemaLocation="../szr/szr_xmldsig.xsd"> +		<bindings node="/xsd:schema"> +			<schemaBindings> +				<package name="at.gv.util.xsd.szr.xmldsig" /> +			</schemaBindings> +		</bindings> +	</bindings> + +</bindings>
\ No newline at end of file diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_v4.0-wsdl.xml b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_v4.0-wsdl.xml new file mode 100644 index 00000000..f95c35f0 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_v4.0-wsdl.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<bindings xmlns="http://java.sun.com/xml/ns/jaxws" +               xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" +               xmlns:xsd="http://www.w3.org/2001/XMLSchema" +               xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"> + +  <enableWrapperStyle>false</enableWrapperStyle> +  <package name="at.gv.util.wsdl.szr_v4"/>  +      +</bindings>
\ No newline at end of file diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_v4.0.xsd b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_v4.0.xsd new file mode 100644 index 00000000..2d25f2dc --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_v4.0.xsd @@ -0,0 +1,443 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:szr="urn:SZRServices" xmlns:pd="http://reference.e-government.gv.at/namespace/persondata/20020228#" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" targetNamespace="urn:SZRServices" elementFormDefault="qualified"> +	<xs:import namespace="http://reference.e-government.gv.at/namespace/persondata/20020228#" schemaLocation="szr_persondata.xsd"/> +	<xs:import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="szr_xmldsig.xsd"/> +	<xs:element name="SZRException" type="szr:SZRException"/> +	<xs:complexType name="SZRException"/> +	<xs:complexType name="PersonInfoType"> +		<xs:sequence> +			<xs:element name="Person" type="pd:PhysicalPersonType"/> +			<xs:element name="RegularDomicile" type="pd:PostalAddressType" minOccurs="0"/> +			<xs:element name="AddressCodes" type="szr:AddressCodesType" minOccurs="0"/> +			<xs:element name="TravelDocument" type="szr:TravelDocumentType" minOccurs="0"/> +			<xs:element name="DateOfBirthWildcard" type="xs:boolean" minOccurs="0"/> +			<xs:element name="AuskunftssperreGesetzt" type="xs:boolean" minOccurs="0"/> +		</xs:sequence> +	</xs:complexType> +	<xs:complexType name="TravelDocumentType"> +		<xs:sequence> +			<xs:element name="DocumentNumber" type="xs:string" minOccurs="0"/> +			<xs:element name="DocumentType" type="xs:string" minOccurs="0"/> +			<xs:element name="IssueDate" type="xs:string" minOccurs="0"/> +			<xs:element name="IssuingAuthority" type="xs:string" minOccurs="0"/> +			<xs:element name="IssuingCountry" type="xs:string" minOccurs="0"/> +		</xs:sequence> +	</xs:complexType> +	<xs:complexType name="AddressCodesType"> +		<xs:sequence> +			<xs:element name="GKZ" type="xs:string" minOccurs="0"/> +			<xs:element name="OKZ" type="xs:string" minOccurs="0"/> +			<xs:element name="SKZ" type="xs:string" minOccurs="0"/> +			<xs:element name="ADRCD" type="xs:string" minOccurs="0"/> +			<xs:element name="SUBCD" type="xs:string" minOccurs="0"/> +			<xs:element name="OBJNR" type="xs:string" minOccurs="0"/> +			<xs:element name="NTZLNR" type="xs:string" minOccurs="0"/> +		</xs:sequence> +	</xs:complexType> +	<xs:element name="TransformBPK"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="PersonInfo" type="szr:PersonInfoType"/> +				<xs:element name="InputBPK" type="xs:string"/> +				<xs:element name="InputBereichsKennung" type="xs:string"/> +				<xs:element name="Begruendung" type="xs:string"/> +				<xs:element name="Target" type="szr:FremdBPKRequestType" maxOccurs="unbounded"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +	<xs:element name="TransformBPKResponse"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="TransformBPKReturn" type="szr:FremdBPKType" maxOccurs="unbounded"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +	<xs:element name="GetVKZPermission"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="VKZ" type="xs:string"/> +				<xs:element name="BereichsKennung" type="xs:string"/> +				<xs:element name="ParticipantId" type="xs:string" minOccurs="0"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +	<xs:element name="GetVKZPermissionResponse"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="GetVKZPermissionReturn" type="szr:GetVKZPermissionResponseType"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +	<xs:complexType name="IdentityLinkType"> +		<xs:sequence> +			<xs:element name="PersonInfo" type="szr:PersonInfoType"/> +			<xs:element name="Assertion" type="xs:anyType"/> +			<xs:element name="AdditionalInfo" type="xs:string" minOccurs="0"/> +		</xs:sequence> +	</xs:complexType> +	<xs:complexType name="ResultRecord"> +		<xs:sequence> +			<xs:element name="PersonInfo" type="szr:PersonInfoType"/> +			<xs:element name="Register" type="xs:string"/> +			<xs:element name="bPK" type="xs:string"/> +			<xs:element name="FremdBPK" type="szr:FremdBPKType" minOccurs="0" maxOccurs="unbounded"/> +		</xs:sequence> +	</xs:complexType> +	<xs:complexType name="GetBPKKombiRequestType"> +		<xs:sequence> +			<xs:element name="PersonInfo" type="szr:PersonInfoType"/> +			<xs:element name="InsertERnP" minOccurs="0"> +				<xs:simpleType> +					<xs:restriction base="xs:string"> +						<xs:enumeration value="NoInsert"/> +						<xs:enumeration value="InsertOnNoMatch"/> +						<xs:enumeration value="ForceInsert"/> +					</xs:restriction> +				</xs:simpleType> +			</xs:element> +			<xs:element name="Suchwizard" type="xs:boolean" minOccurs="0"/> +			<xs:element name="VKZ" type="xs:string" nillable="true"/> +			<xs:element name="BehoerdenKennzeichen" type="xs:string" minOccurs="0"/> +			<xs:element name="BereichsKennung" type="xs:string" minOccurs="0"/> +			<xs:element name="Target" type="szr:FremdBPKRequestType" minOccurs="0" maxOccurs="unbounded"/> +			<xs:element name="Sessionid" type="xs:string" minOccurs="0"/> +		</xs:sequence> +	</xs:complexType> +	<xs:complexType name="GetBPKKombiResponseType"> +		<xs:complexContent> +			<xs:extension base="szr:GetBPKZPVResponseType"> +				<xs:sequence> +					<xs:element name="FoundWithSuchwizard" type="xs:boolean"/> +					<xs:element name="Sessionid" type="xs:string"/> +				</xs:sequence> +			</xs:extension> +		</xs:complexContent> +	</xs:complexType> +	<xs:complexType name="GetBPKZPVRequestType"> +		<xs:sequence> +			<xs:element name="PersonInfo" type="szr:PersonInfoType"/> +			<xs:element name="InsertERnP" type="xs:boolean" default="false" minOccurs="0"/> +			<xs:element name="VKZ" type="xs:string" minOccurs="1"/> +			<xs:element name="BehoerdenKennzeichen" type="xs:string" minOccurs="0"/> +			<xs:element name="BereichsKennung" type="xs:string" minOccurs="0"/> +			<xs:element name="Target" type="szr:FremdBPKRequestType" minOccurs="0" maxOccurs="unbounded"/> +		</xs:sequence> +	</xs:complexType> +	<xs:complexType name="GetBPKZPVResponseType"> +		<xs:sequence> +			<xs:element name="ResultRecord" type="szr:ResultRecord" maxOccurs="unbounded"/> +			<xs:element name="InsertERnPResult" type="xs:boolean"/> +		</xs:sequence> +	</xs:complexType> +	<xs:complexType name="GetBPKFromStammzahlEncryptedRequestType"> +		<xs:sequence> +			<xs:element name="StammzahlEncrypted" type="xs:string" minOccurs="1"/> +			<xs:element name="PersonInfo" type="szr:PersonInfoType" minOccurs="0"/> +			<xs:element name="VKZ" type="xs:string" minOccurs="1"/> +			<xs:element name="BereichsKennung" type="xs:string" minOccurs="0" maxOccurs="unbounded"/> +			<xs:element name="Target" type="szr:FremdBPKRequestType" minOccurs="0" maxOccurs="unbounded"/> +		</xs:sequence> +		<xs:attribute name="key"/> +	</xs:complexType> +	<xs:complexType name="GetBPKFromStammzahlEncryptedResponseType"> +		<xs:sequence> +			<xs:element name="bPK" type="xs:string" minOccurs="0" maxOccurs="unbounded"/> +			<xs:element name="FremdBPK" type="szr:FremdBPKType" minOccurs="0" maxOccurs="unbounded"/> +			<xs:element name="Fault" type="szr:Fault" minOccurs="0"/> +		</xs:sequence> +		<xs:attribute name="key"/> +	</xs:complexType> +	<xs:complexType name="Fault"> +		<xs:attribute name="Code" type="xs:string"/> +		<xs:attribute name="String" type="xs:string"/> +	</xs:complexType> +	<xs:complexType name="SignContentResponseType"> +		<xs:sequence> +			<xs:element name="JwsAlg" type="xs:string" minOccurs="0"/> +			<xs:element name="Out" type="szr:SignContentEntry" minOccurs="0" maxOccurs="unbounded"/> +		</xs:sequence> +	</xs:complexType> +	<xs:complexType name="SignContentEntry"> +		<xs:simpleContent> +			<xs:extension base="xs:string"> +				<xs:attribute name="key"/> +			</xs:extension> +		</xs:simpleContent> +	</xs:complexType> +	<xs:element name="GetIdentityLink"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="PersonInfo" type="szr:PersonInfoType"/> +				<xs:element name="KeyValue" type="dsig:KeyValueType" minOccurs="0" maxOccurs="unbounded"/> +				<xs:element name="InsertERnP" type="xs:boolean" minOccurs="0"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +	<xs:element name="GetIdentityLinkResponse"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="GetIdentityLinkReturn" type="szr:IdentityLinkType"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +	<xs:element name="GetIdentityLinkEidas"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="PersonInfo" type="szr:PersonInfoType"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +	<xs:element name="GetIdentityLinkEidasResponse"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="GetIdentityLinkReturn" type="szr:IdentityLinkType"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +	<xs:element name="GetBPK"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="PersonInfo" type="szr:PersonInfoType"/> +				<xs:element name="BereichsKennung" type="xs:string" minOccurs="0" maxOccurs="unbounded"/> +				<xs:element name="VKZ" type="xs:string" minOccurs="0"/> +				<xs:element name="Target" type="szr:FremdBPKRequestType" minOccurs="0" maxOccurs="unbounded"/> +				<xs:element name="ListMultiplePersons" type="xs:boolean" minOccurs="0"/> +				<xs:element name="InsertERnP" type="xs:boolean" minOccurs="0"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +	<xs:element name="GetBPKResponse"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="GetBPKReturn" type="xs:string" minOccurs="0" maxOccurs="unbounded"/> +				<xs:element name="FremdBPK" type="szr:FremdBPKType" minOccurs="0" maxOccurs="unbounded"/> +				<xs:element name="PersonInfo" type="szr:PersonInfoType" minOccurs="0" maxOccurs="5"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +	<xs:element name="GetBPKs"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="PersonInfo" type="szr:PersonInfoType" maxOccurs="unbounded"/> +				<xs:element name="BereichsKennung" type="xs:string" minOccurs="0" maxOccurs="unbounded"/> +				<xs:element name="VKZ" type="xs:string"/> +				<xs:element name="Target" type="szr:FremdBPKRequestType" minOccurs="0" maxOccurs="unbounded"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +	<xs:element name="GetBPKsResponse"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="ResultRecord" type="szr:GetBPKsResponseType" maxOccurs="unbounded"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +	<xs:complexType name="GetBPKsResponseType"> +		<xs:sequence> +			<xs:element name="BPK" type="xs:string" minOccurs="0" maxOccurs="unbounded"/> +			<xs:element name="FremdBPK" type="szr:FremdBPKType" minOccurs="0" maxOccurs="unbounded"/> +			<xs:element name="Fault" minOccurs="0"> +				<xs:complexType> +					<xs:attribute name="Code" type="xs:string"/> +					<xs:attribute name="String" type="xs:string"/> +				</xs:complexType> +			</xs:element> +		</xs:sequence> +	</xs:complexType> +	<xs:element name="GetBPKKombi"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="GetBPKKombiRequest" type="szr:GetBPKKombiRequestType"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +	<xs:element name="GetBPKKombiResponse"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="GetBPKKombiResponse" type="szr:GetBPKKombiResponseType"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +	<xs:element name="GetBPKZPV"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="GetBPKZPVRequest" type="szr:GetBPKZPVRequestType"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +	<xs:element name="GetBPKZPVResponse"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="GetBPKZPVResponse" type="szr:GetBPKZPVResponseType"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +	<xs:element name="GetBPKFromStammzahlEncrypted"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="In" type="szr:GetBPKFromStammzahlEncryptedRequestType" maxOccurs="unbounded"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +	<xs:element name="GetBPKFromStammzahlEncryptedResponse"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="Out" type="szr:GetBPKFromStammzahlEncryptedResponseType" maxOccurs="unbounded"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +	<xs:element name="SignContent"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="AppendCert" type="xs:boolean" default="false" minOccurs="0"/> +				<xs:element name="JWSHeaderParam" type="szr:JwsHeaderParam" minOccurs="0" maxOccurs="unbounded"/> +				<xs:element name="In" type="szr:SignContentEntry" minOccurs="0" maxOccurs="unbounded"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +	<xs:complexType name="JwsHeaderParam"> +		<xs:attribute name="key" type="xs:string" use="required"/> +		<xs:attribute name="value" type="xs:string" use="required"/> +	</xs:complexType> +	<xs:element name="SignContentResponse"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="SignContentResponse" type="szr:SignContentResponseType"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +	<xs:element name="ValidateIdentityLink"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="IdentityLink" type="szr:IdentityLinkType"/> +				<xs:element name="BereichsKennung" type="xs:string"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +	<xs:element name="ValidateIdentityLinkResponse"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="ValidateIdentityLinkReturn" type="xs:string"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +	<xs:element name="BPKzuBasiszahl"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="Bereich" type="xs:string"/> +				<xs:element name="BPK" type="xs:string"/> +				<xs:element name="BasisZahl" type="xs:string" maxOccurs="unbounded"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +	<xs:element name="BPKzuBasiszahlResponse"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="BPKzuBasiszahlReturn" type="xs:string"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +	<xs:complexType name="FremdBPKRequestType"> +		<xs:sequence> +			<xs:element name="BereichsKennung" type="xs:string"/> +			<xs:element name="VKZ" type="xs:string"/> +		</xs:sequence> +	</xs:complexType> +	<xs:complexType name="FremdBPKType"> +		<xs:sequence> +			<xs:element name="BereichsKennung" type="xs:string"/> +			<xs:element name="FremdBPK" type="xs:string"/> +		</xs:sequence> +	</xs:complexType> +	<xs:complexType name="GetVKZPermissionResponseType"> +		<xs:sequence> +			<xs:element name="isAllowed" type="xs:boolean"/> +			<xs:element name="behSchluessel" type="xs:string" minOccurs="0"/> +		</xs:sequence> +	</xs:complexType> +	<xs:element name="BasiszahlZuBPK"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="VKZ" type="xs:string" minOccurs="0"/> +				<xs:element name="BasisZahl" type="xs:string" maxOccurs="unbounded"/> +				<xs:element name="Bereich" type="xs:string" minOccurs="0" maxOccurs="unbounded"/> +				<xs:element name="FremdBPKTargets" type="szr:FremdBPKRequestType" minOccurs="0" maxOccurs="unbounded"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +	<xs:complexType name="BasiszahlZuBPKReturnType"> +		<xs:sequence> +			<xs:element name="BPK" type="xs:string" minOccurs="0" maxOccurs="unbounded"/> +			<xs:element name="FremdBPKs" type="szr:FremdBPKType" minOccurs="0" maxOccurs="unbounded"/> +		</xs:sequence> +	</xs:complexType> +	<xs:element name="BasiszahlZuBPKResponse"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="BasiszahlZuBPKReturn" type="szr:BasiszahlZuBPKReturnType" maxOccurs="unbounded"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +	<xs:element name="ZMRAnwendungsIntegration"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="Bereich" type="xs:string"/> +				<xs:element name="FremdBPKTargets" type="szr:FremdBPKRequestType" minOccurs="0" maxOccurs="unbounded"/> +				<xs:element name="ZMRfremdbPK" type="xs:string" maxOccurs="unbounded"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +	<xs:complexType name="ZMRAnwendungsIntegrationReturnType"> +		<xs:sequence> +			<xs:element name="BPK" type="xs:string"/> +			<xs:element name="FremdBPKs" type="szr:FremdBPKType" minOccurs="0" maxOccurs="unbounded"/> +		</xs:sequence> +	</xs:complexType> +	<xs:element name="ZMRAnwendungsIntegrationResponse"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="ZMRAnwendungsIntegrationReturn" type="szr:ZMRAnwendungsIntegrationReturnType" maxOccurs="unbounded"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +	<xs:element name="GetStammzahl"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="PersonInfo" type="szr:PersonInfoType"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +	<xs:element name="GetStammzahlResponse"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="Stammzahl" type="xs:string"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +	<xs:element name="GetStammzahlEncrypted"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="PersonInfo" type="szr:PersonInfoType"/> +				<xs:element name="InsertERnP" type="xs:boolean" minOccurs="0"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +	<xs:element name="GetStammzahlEncryptedResponse"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="Stammzahl" type="xs:string"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +	<xs:element name="GetVersion" nillable="true"/> +	<xs:element name="GetVersionResponse"> +		<xs:complexType> +			<xs:sequence> +				<xs:element name="Version" type="xs:string"/> +				<xs:element name="Revision" type="xs:string"/> +				<xs:element name="Time" type="xs:string"/> +				<xs:element name="IdentityLinkNotAfter" type="xs:string"/> +			</xs:sequence> +		</xs:complexType> +	</xs:element> +</xs:schema> diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_xmldsig.xsd b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_xmldsig.xsd new file mode 100644 index 00000000..96b50b40 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/resources/szr_client/szr_xmldsig.xsd @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ecdsa="http://www.w3.org/2001/04/xmldsig-more#" +           targetNamespace="http://www.w3.org/2000/09/xmldsig#" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"> +    <xs:import namespace="http://www.w3.org/2001/04/xmldsig-more#" schemaLocation="szr_ecdsa.xsd"/> +    <xs:complexType name="KeyValueType"> +        <xs:sequence> +            <xs:element name="DSAKeyValue" minOccurs="0" +                        type="dsig:DSAKeyValueType" /> +            <xs:element name="RSAKeyValue" minOccurs="0" +                        type="dsig:RSAKeyValueType" /> +            <xs:element ref="ecdsa:ECDSAKeyValue" /> +        </xs:sequence> +    </xs:complexType> +    <xs:complexType name="DSAKeyValueType"> +        <xs:sequence> +            <xs:element name="P" minOccurs="0" type="xs:string" /> +            <xs:element name="Q" minOccurs="0" type="xs:string" /> +            <xs:element name="J" minOccurs="0" type="xs:string" /> +            <xs:element name="G" minOccurs="0" type="xs:string" /> +            <xs:element name="Y" minOccurs="0" type="xs:string" /> +            <xs:element name="PgenCounter" minOccurs="0" type="xs:string" /> +            <xs:element name="Seed" minOccurs="0" type="xs:string" /> +        </xs:sequence> +    </xs:complexType> +    <xs:complexType name="RSAKeyValueType"> +        <xs:sequence> +            <xs:element name="Modulus" minOccurs="0" type="xs:string" /> +            <xs:element name="Exponent" minOccurs="0" type="xs:string" /> +        </xs:sequence> +    </xs:complexType> +</xs:schema> diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/SzrClientTest.java b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/SzrClientTest.java index fca548b7..9709aeb9 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/SzrClientTest.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/SzrClientTest.java @@ -19,17 +19,20 @@   * file for details on the various modules and licenses.   * The "NOTICE" text file is part of the distribution. Any derivative works   * that you distribute must include a readable copy of the "NOTICE" text file. -*/ + */  package at.asitplus.eidas.specific.modules.auth.eidas.v2.test;  import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyList;  import static org.mockito.Mockito.when;  import java.io.IOException;  import java.security.InvalidKeyException;  import java.security.MessageDigest;  import java.security.NoSuchProviderException; +import java.util.Arrays; +import java.util.List;  import javax.xml.bind.JAXBContext;  import javax.xml.bind.JAXBException; @@ -37,9 +40,11 @@ import javax.xml.bind.Unmarshaller;  import javax.xml.parsers.ParserConfigurationException;  import javax.xml.ws.soap.SOAPFaultException; +import org.apache.commons.lang3.RandomStringUtils;  import org.apache.commons.lang3.StringUtils;  import org.apache.cxf.binding.soap.SoapFault;  import org.junit.Assert; +import org.junit.Before;  import org.junit.BeforeClass;  import org.junit.Ignore;  import org.junit.Rule; @@ -70,11 +75,16 @@ import at.gv.egiz.eaaf.core.exceptions.EaafParserException;  import at.gv.egiz.eaaf.core.impl.data.Triple;  import at.gv.egiz.eaaf.core.impl.idp.auth.data.SimpleIdentityLinkAssertionParser;  import at.gv.egiz.eaaf.core.impl.utils.DomUtils; +import szrservices.GetBPKFromStammzahlEncryptedResponse; +import szrservices.GetBPKFromStammzahlEncryptedResponseType;  import szrservices.GetIdentityLinkEidasResponse;  import szrservices.IdentityLinkType;  import szrservices.PersonInfoType;  import szrservices.SZR;  import szrservices.SZRException_Exception; +import szrservices.SignContentEntry; +import szrservices.SignContentResponse; +import szrservices.SignContentResponseType;  import szrservices.TravelDocumentType;  @RunWith(SpringJUnit4ClassRunner.class) @@ -91,12 +101,17 @@ public class SzrClientTest {    private static final String familyName = "Mustermann";    private static final String dateOfBirth = "1989-05-05";    private static final String eIDASeID = "IS/AT/1234sdgsdfg56789ABCDEF"; -    private static final String DUMMY_TARGET = EaafConstants.URN_PREFIX_CDID + "ZP"; +  private SZR szrMock = null; + + +  @Rule +  public SoapServiceRule soap = SoapServiceRule.newInstance(); +    /**     * jUnit class initializer. -   *  +   *     * @throws IOException In case of an error     */    @BeforeClass @@ -106,24 +121,110 @@ public class SzrClientTest {    } -  @Rule -  public SoapServiceRule soap = SoapServiceRule.newInstance(); +  /** +   * Initialize jUnit test. +   */ +  @Before +  public void initializer() { +    if (szrMock == null) { +      szrMock = soap.mock(SZR.class, "http://localhost:1234/demoszr"); + +    } +  } +    @Test -  public void getIdentityLinkRawModeValidResponse() throws SZRException_Exception, EaafParserException, -      NoSuchProviderException, IOException, InvalidKeyException, EidasSAuthenticationException, JAXBException { -    setSzrResponseIdentityLink("/data/szr/szr_resp_valid_1.xml", "http://localhost:1234/demoszr"); +  public void getStammzahlenEcryptedTest() throws JAXBException, SZRException_Exception, SzrCommunicationException { +    final GetBPKFromStammzahlEncryptedResponse szrResponse = new GetBPKFromStammzahlEncryptedResponse(); +    final GetBPKFromStammzahlEncryptedResponseType result1 = new GetBPKFromStammzahlEncryptedResponseType(); +    szrResponse.getOut().add(result1); + +    result1.setKey(RandomStringUtils.randomAlphanumeric(20)); + +    //    when(szrMock.getBPKFromStammzahlEncrypted(anyList())) +    //        .thenReturn(Arrays.asList(result1)); +    when(szrMock.getStammzahlEncrypted(any(), any())).thenReturn(result1.getKey()); + +    String stammzahlEncrypted = szrClient.getEncryptedStammzahl(new PersonInfoType()); + +    Assert.assertEquals("bcBind not match", result1.getKey(), stammzahlEncrypted); + +    when(szrMock.getStammzahlEncrypted(any(), any())).thenReturn(null); +    try { +      stammzahlEncrypted = szrClient.getEncryptedStammzahl(new PersonInfoType()); +    } catch (SzrCommunicationException e) { +      Assert.assertTrue("Not correct error", e.getMessage().contains("ernb.01")); +    } +  } + +  @Test +  public void getBcBindValid() throws SZRException_Exception, SzrCommunicationException { +    final SignContentResponse szrResponse = new SignContentResponse(); +    final SignContentEntry result1 = new SignContentEntry(); +    final SignContentResponseType content = new SignContentResponseType(); +    content.getOut().add(result1); +    szrResponse.setSignContentResponse(content); + +    result1.setKey("bcBindReq"); +    result1.setValue(RandomStringUtils.randomAlphanumeric(100)); + +    when(szrMock.signContent(any(), anyList(), anyList())).thenReturn(content); + +    final String bcBind = szrClient +        .getBcBind(RandomStringUtils.randomAlphabetic(10), RandomStringUtils.randomAlphabetic(10), +                   RandomStringUtils.randomAlphabetic(10)); + +    Assert.assertNotNull("bcBind is null", bcBind); +    Assert.assertEquals("bcBind not match", result1.getValue(), bcBind); + +    when(szrMock.signContent(any(), anyList(), anyList())).thenReturn(null); +    try { +      szrClient +          .getBcBind(RandomStringUtils.randomAlphabetic(10), RandomStringUtils.randomAlphabetic(10), +                     RandomStringUtils.randomAlphabetic(10)); +    } catch (SzrCommunicationException e) { +      Assert.assertTrue("Not correct error", e.getMessage().contains("ernb.01")); +    } + +    final SignContentEntry result2 = new SignContentEntry(); +    final SignContentResponseType content1 = new SignContentResponseType(); +    content1.getOut().add(result2); +    when(szrMock.signContent(any(), anyList(), anyList())).thenReturn(content1); +    try { +      szrClient +          .getBcBind(RandomStringUtils.randomAlphabetic(10), RandomStringUtils.randomAlphabetic(10), +                     RandomStringUtils.randomAlphabetic(10)); +    } catch (SzrCommunicationException e) { +      Assert.assertTrue("Not correct error", e.getMessage().contains("ernb.01")); +    } + +    result2.setKey("bcBindReq"); +    result2.setValue(""); +    when(szrMock.signContent(any(), anyList(), anyList())).thenReturn(content1); +    try { +      szrClient +          .getBcBind(RandomStringUtils.randomAlphabetic(10), RandomStringUtils.randomAlphabetic(10), +                     RandomStringUtils.randomAlphabetic(10)); +    } catch (SzrCommunicationException e) { +      Assert.assertTrue("Not correct error", e.getMessage().contains("ernb.01")); +    } +  } + +  @Test +  public void getIdentityLinkRawModeValidResponse() +      throws SZRException_Exception, EaafParserException, NoSuchProviderException, IOException, InvalidKeyException, +      EidasSAuthenticationException, JAXBException { +    setSzrResponseIdentityLink("/data/szr/szr_resp_valid_1.xml");      try {        log.debug("Starting connecting SZR Gateway"); -      final IdentityLinkType result = szrClient.getIdentityLinkInRawMode( -          getPersonInfo()); +      final IdentityLinkType result = szrClient.getIdentityLinkInRawMode(getPersonInfo());        Assert.assertNotNull(result);        Assert.assertNotNull(result.getAssertion()); -      final IIdentityLink identityLink = new SimpleIdentityLinkAssertionParser((Element) result -          .getAssertion()).parseIdentityLink(); +      final IIdentityLink identityLink = new SimpleIdentityLinkAssertionParser((Element) result.getAssertion()) +          .parseIdentityLink();        Assert.assertNotNull(identityLink);        System.out.println(identityLink.getSerializedSamlAssertion()); @@ -144,16 +245,14 @@ public class SzrClientTest {    }    @Test -  public void getIdentityLinkRawModeErrorTravelerDocExists() throws SZRException_Exception, -      EaafParserException, NoSuchProviderException, IOException, InvalidKeyException, +  public void getIdentityLinkRawModeErrorTravelerDocExists() +      throws SZRException_Exception, EaafParserException, NoSuchProviderException, IOException, InvalidKeyException,        EidasSAuthenticationException, JAXBException, ParserConfigurationException, SAXException { -    setSzrExceptionIdentityLink("/data/szr/szr_resp_error_travelerdocexists.xml", -        "http://localhost:1234/demoszr"); +    setSzrExceptionIdentityLink("/data/szr/szr_resp_error_travelerdocexists.xml");      try {        log.debug("Starting connecting SZR Gateway"); -      szrClient.getIdentityLinkInRawMode( -          getPersonInfo()); +      szrClient.getIdentityLinkInRawMode(getPersonInfo());        Assert.fail();      } catch (final SzrCommunicationException e) { @@ -163,8 +262,7 @@ public class SzrClientTest {        Assert.assertNotNull(((SOAPFaultException) e.getCause()).getFault());        checkElement("p344:F455", ((SOAPFaultException) e.getCause()).getFault().getFaultCode());        checkElement( -          "The travel document you sent to insert a person already exists for another person. " -          + "Either check the document or have the person altered accordingly", +          "The travel document you sent to insert a person already exists for another person. " + "Either check the document or have the person altered accordingly",            ((SOAPFaultException) e.getCause()).getFault().getFaultString());      } @@ -174,13 +272,16 @@ public class SzrClientTest {    @Ignore    @Test    public void getBpkTest() throws SZRException_Exception, EidasSAuthenticationException { -    final String bPK = szrClient.getBpk(getPersonInfo(), DUMMY_TARGET, -        basicConfig.getBasicConfiguration( -            Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_VKZ, -            "no VKZ defined")); +    final List<String> bPK = szrClient.getBpk(getPersonInfo(), DUMMY_TARGET, basicConfig +        .getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_VKZ, "no VKZ defined")); -    if (StringUtils.isEmpty(bPK)) { -      throw new SzrCommunicationException("ernb.01", new Object[] { "bPK is null or empty" }); +    if (bPK.isEmpty()) { +      throw new SzrCommunicationException("ernb.01", new Object[]{"bPK list is empty"}); +    } +    for (final String b : bPK) { +      if (StringUtils.isEmpty(b)) { +        throw new SzrCommunicationException("ernb.01", new Object[]{"bPK is null or empty"}); +      }      }    } @@ -191,37 +292,28 @@ public class SzrClientTest {    } -  private void setSzrResponseIdentityLink(String responseXmlPath, String serviceUrl) throws JAXBException, -      SZRException_Exception { -    final SZR szrServiceMock = soap.mock(SZR.class, serviceUrl); -    final JAXBContext jaxbContext = JAXBContext.newInstance( -        szrservices.ObjectFactory.class, -        org.xmlsoap.schemas.ws._2002._04.secext.ObjectFactory.class, -        org.w3._2001._04.xmldsig_more.ObjectFactory.class, -        org.w3._2000._09.xmldsig.ObjectFactory.class, -        at.gv.egov.pvp1.ObjectFactory.class, -        at.gv.e_government.reference.namespace.persondata._20020228.ObjectFactory.class); +  private void setSzrResponseIdentityLink(String responseXmlPath) throws JAXBException, SZRException_Exception { +    final JAXBContext jaxbContext = JAXBContext +        .newInstance(szrservices.ObjectFactory.class, org.w3._2001._04.xmldsig_more.ObjectFactory.class, +                     org.w3._2000._09.xmldsig.ObjectFactory.class, +                     at.gv.e_government.reference.namespace.persondata._20020228.ObjectFactory.class);      final Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();      final GetIdentityLinkEidasResponse szrResponse = (GetIdentityLinkEidasResponse) jaxbUnmarshaller          .unmarshal(this.getClass().getResourceAsStream(responseXmlPath)); -    when(szrServiceMock.getIdentityLinkEidas(any(PersonInfoType.class))).thenReturn(szrResponse -        .getGetIdentityLinkReturn()); +    when(szrMock.getIdentityLinkEidas(any(PersonInfoType.class))).thenReturn(szrResponse.getGetIdentityLinkReturn());    } -  private void setSzrExceptionIdentityLink(String responseXmlPath, String serviceUrl) throws JAXBException, -      ParserConfigurationException, SAXException, IOException, SZRException_Exception { -    final SZR szrServiceMock = soap.mock(SZR.class, serviceUrl); -    final Element detailerror = DomUtils.parseXmlNonValidating(this.getClass().getResourceAsStream( -        responseXmlPath)); +  private void setSzrExceptionIdentityLink(String responseXmlPath) +      throws JAXBException, ParserConfigurationException, SAXException, IOException, SZRException_Exception { +    final Element detailerror = DomUtils.parseXmlNonValidating(this.getClass().getResourceAsStream(responseXmlPath));      final javax.xml.namespace.QName qName = new javax.xml.namespace.QName("urn:SZRServices", "F455", "p344");      final SoapFault fault = new SoapFault( -        "The travel document you sent to insert a person already exists for another person. " -        + "Either check the document or have the person altered accordingly", +        "The travel document you sent to insert a person already exists for another person. " + "Either check the document or have the person altered accordingly",          qName);      fault.setRole("urn:SZRServices");      fault.setDetail(detailerror); -    when(szrServiceMock.getIdentityLinkEidas(any(PersonInfoType.class))).thenThrow(fault); +    when(szrMock.getIdentityLinkEidas(any(PersonInfoType.class))).thenThrow(fault);    } @@ -233,7 +325,7 @@ public class SzrClientTest {        return hashBase64;      } catch (final Exception ex) { -      throw new EidasSAuthenticationException("internal.03", new Object[] {}, ex); +      throw new EidasSAuthenticationException("internal.03", new Object[]{}, ex);      }    } @@ -249,8 +341,7 @@ public class SzrClientTest {      personInfo.setTravelDocument(eDocument);      // parse some eID attributes -    final Triple<String, String, String> eIdentifier = -        EidasResponseUtils.parseEidasPersonalIdentifier(eIDASeID); +    final Triple<String, String, String> eIdentifier = EidasResponseUtils.parseEidasPersonalIdentifier(eIDASeID);      final String uniqueId = createHashFromUniqueId(eIdentifier.getThird());      final String citizenCountry = eIdentifier.getFirst(); @@ -262,9 +353,9 @@ public class SzrClientTest {      eDocument.setDocumentNumber(uniqueId);      // eID document information -    eDocument.setDocumentType(basicConfig.getBasicConfiguration( -        Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_EDOCUMENTTYPE, -        Constants.SZR_CONSTANTS_DEFAULT_DOCUMENT_TYPE)); +    eDocument.setDocumentType(basicConfig +                                  .getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_EDOCUMENTTYPE, +                                                         Constants.SZR_CONSTANTS_DEFAULT_DOCUMENT_TYPE));      return personInfo;    } diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/SzrClientTestProduction.java b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/SzrClientTestProduction.java index 2f6a989e..2f573f53 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/SzrClientTestProduction.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/SzrClientTestProduction.java @@ -27,6 +27,7 @@ import java.io.IOException;  import java.security.InvalidKeyException;  import java.security.MessageDigest;  import java.security.NoSuchProviderException; +import java.util.List;  import org.apache.commons.lang3.StringUtils;  import org.junit.Ignore; @@ -58,7 +59,7 @@ import szrservices.PersonInfoType;  import szrservices.SZRException_Exception;  import szrservices.TravelDocumentType; -//@Ignore +@Ignore  @RunWith(SpringJUnit4ClassRunner.class)  @ContextConfiguration("/SpringTest-context_basic_test.xml")  public class SzrClientTestProduction { @@ -132,13 +133,18 @@ public class SzrClientTestProduction {    @Ignore    @Test    public void getBpkTest() throws SZRException_Exception, EidasSAuthenticationException { -    final String bPK = szrClient.getBpk(getPersonInfo(), DUMMY_TARGET, +    final List<String> bPK = szrClient.getBpk(getPersonInfo(), DUMMY_TARGET,          basicConfig.getBasicConfiguration(              Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_VKZ,              "no VKZ defined")); -    if (StringUtils.isEmpty(bPK)) { -      throw new SzrCommunicationException("ernb.01", new Object[] { "bPK is null or empty" }); +    if (bPK.isEmpty()) { +      throw new SzrCommunicationException("ernb.01", new Object[]{"bPK list is empty"}); +    } +    for (String b : bPK) { +      if (StringUtils.isEmpty(b)) { +        throw new SzrCommunicationException("ernb.01", new Object[]{"bPK is null or empty"}); +      }      }    } diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/CreateIdentityLinkTaskEidNewTest.java b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/CreateIdentityLinkTaskEidNewTest.java new file mode 100644 index 00000000..dd485ee6 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/tasks/CreateIdentityLinkTaskEidNewTest.java @@ -0,0 +1,272 @@ +package at.asitplus.eidas.specific.modules.auth.eidas.v2.test.tasks; + +import static at.asitplus.eidas.specific.connector.MsEidasNodeConstants.PROP_CONFIG_SP_NEW_EID_MODE; +import static org.mockito.ArgumentMatchers.any; +import static org.powermock.api.mockito.PowerMockito.when; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.security.KeyStore; +import java.security.Provider; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.namespace.QName; + +import org.apache.commons.lang3.RandomStringUtils; +import org.jetbrains.annotations.NotNull; +import org.jose4j.jwa.AlgorithmConstraints; +import org.jose4j.jwa.AlgorithmConstraints.ConstraintType; +import org.jose4j.jws.AlgorithmIdentifiers; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import com.skjolberg.mockito.soap.SoapServiceRule; + +import at.asitplus.eidas.specific.connector.MsEidasNodeConstants; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.SzrCommunicationException; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.AuthBlockSigningService; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.EidasAttributeRegistry; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.CreateIdentityLinkTask; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.JoseUtils; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.utils.JoseUtils.JwsResult; +import at.gv.egiz.eaaf.core.api.data.EaafConfigConstants; +import at.gv.egiz.eaaf.core.api.data.EaafConstants; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.exceptions.EaafStorageException; +import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; +import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory; +import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreUtils; +import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration; +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.module.test.DummySpConfiguration; +import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl; +import at.gv.egiz.eaaf.core.impl.idp.process.ExecutionContextImpl; +import eu.eidas.auth.commons.attribute.AttributeDefinition; +import eu.eidas.auth.commons.attribute.ImmutableAttributeMap; +import eu.eidas.auth.commons.attribute.PersonType; +import eu.eidas.auth.commons.protocol.impl.AuthenticationResponse; +import lombok.val; +import szrservices.SZR; +import szrservices.SignContentEntry; +import szrservices.SignContentResponseType; + +@RunWith(SpringJUnit4ClassRunner.class) +//@RunWith(PowerMockRunner.class) +//@PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class) +@PrepareForTest(CreateIdentityLinkTask.class) +@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS) +@ContextConfiguration("/SpringTest-context_tasks_test.xml") +public class CreateIdentityLinkTaskEidNewTest { + +  @Autowired(required = true) +  private CreateIdentityLinkTask task; + +  @Autowired(required = true) +  private IConfiguration basicConfig; +  @Autowired +  protected EidasAttributeRegistry attrRegistry; + +  @Autowired +  EaafKeyStoreFactory keyStoreFactory; + +  @Autowired +  private AuthBlockSigningService authBlockSigner; + +  final ExecutionContext executionContext = new ExecutionContextImpl(); +  private MockHttpServletRequest httpReq; +  private MockHttpServletResponse httpResp; +  private TestRequestImpl pendingReq; +  private DummySpConfiguration oaParam; +  private SZR szrMock; + +  private static final String PW = "f/+saJBc3a}*/T^s"; +  private static final String ALIAS = "connectorkeypair"; + +  private static final List<String> BINDING_AUTH_ALGORITHM_WHITELIST_SIGNING = Collections.unmodifiableList(Arrays +      .asList(AlgorithmIdentifiers.ECDSA_USING_P256_CURVE_AND_SHA256, +          AlgorithmIdentifiers.ECDSA_USING_P521_CURVE_AND_SHA512, AlgorithmIdentifiers.RSA_PSS_USING_SHA256, +          AlgorithmIdentifiers.RSA_PSS_USING_SHA512)); + +  @Rule +  public final SoapServiceRule soap = SoapServiceRule.newInstance(); + +  /** +   * jUnit class initializer. +   * +   * @throws IOException In case of an error +   */ +  @BeforeClass +  public static void classInitializer() throws IOException { +    final String current = new java.io.File(".").toURI().toString(); +    System.setProperty("eidas.ms.configuration", current + "src/test/resources/config/junit_config_3.properties"); + +  } + +  /** +   * jUnit test set-up. +   */ +  @Before +  public void setUp() throws EaafStorageException, URISyntaxException { + +    httpReq = new MockHttpServletRequest("POST", "https://localhost/authhandler"); +    httpResp = new MockHttpServletResponse(); +    RequestContextHolder.resetRequestAttributes(); +    RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpReq, httpResp)); + +    final Map<String, String> spConfig = new HashMap<>(); +    spConfig.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, "testSp"); +    spConfig.put("target", "urn:publicid:gv.at:cdid+XX"); +    spConfig.put(PROP_CONFIG_SP_NEW_EID_MODE, "true"); +    oaParam = new DummySpConfiguration(spConfig, basicConfig); +    pendingReq = new TestRequestImpl(); + +    final AuthenticationResponse response = buildDummyAuthResponse(); + +    pendingReq.getSessionData(AuthProcessDataWrapper.class) +        .setGenericDataToSession(Constants.DATA_FULL_EIDAS_RESPONSE, response); +    pendingReq.setSpConfig(oaParam); +    pendingReq.setPendingReqId(at.gv.egiz.eaaf.core.impl.utils.Random.nextProcessReferenceValue()); +    pendingReq.setAuthUrl("http://test.com/"); +    pendingReq.setTransactionId("avaasbav"); + +    executionContext.put(MsEidasNodeConstants.REQ_PARAM_SELECTED_COUNTRY, "XX"); +    executionContext.put(EaafConstants.PROCESS_ENGINE_REQUIRES_NO_POSTAUTH_REDIRECT, true); + +    szrMock = soap.mock(SZR.class, "http://localhost:1234/demoszr"); +  } + +  @Test +  public void successfulProcess() throws Exception { +    //initialize test +    when(szrMock, "getStammzahlEncrypted", any(), any()).thenReturn(RandomStringUtils.randomNumeric(10)); +    val signContentResp = new SignContentResponseType(); +    final SignContentEntry signContentEntry = new SignContentEntry(); +    signContentEntry.setValue(RandomStringUtils.randomAlphanumeric(10)); +    signContentResp.getOut().add(signContentEntry); +    when(szrMock, "signContent", any(), any(), any()).thenReturn(signContentResp); + +    //perform test +    task.execute(pendingReq, executionContext); + +    //validate state +    final AuthProcessDataWrapper authProcessData = pendingReq.getSessionData(AuthProcessDataWrapper.class); +    Assert.assertNotNull("AuthProcessData", authProcessData); +    Assert.assertNotNull("eidasBind", authProcessData.getGenericDataFromSession(Constants.EIDAS_BIND, String.class)); + +    String authBlock = authProcessData.getGenericDataFromSession(Constants.SZR_AUTHBLOCK, String.class); +    Assert.assertNotNull("AuthBlock", authBlock); + +    //check authblock signature +    final AlgorithmConstraints constraints = new AlgorithmConstraints(ConstraintType.PERMIT, +        BINDING_AUTH_ALGORITHM_WHITELIST_SIGNING.toArray(new String[BINDING_AUTH_ALGORITHM_WHITELIST_SIGNING.size()])); +    Pair<KeyStore, Provider> keyStore = getKeyStore(); +    X509Certificate[] trustedCerts = EaafKeyStoreUtils +        .getPrivateKeyAndCertificates(keyStore.getFirst(), ALIAS, PW.toCharArray(), true, "junit").getSecond(); +    JwsResult result = JoseUtils.validateSignature(authBlock, Arrays.asList(trustedCerts), constraints); +    Assert.assertTrue("AuthBlock not valid", result.isValid()); +     +  } + +  @Test +  public void getStammzahlEncryptedExceptionTest() throws Exception { +    try { +      when(szrMock, "getStammzahlEncrypted", any(), any()).thenReturn(null); +      task.execute(pendingReq, executionContext); +    } catch (TaskExecutionException e) { +      Assert.assertEquals("Incorrect exception thrown", e.getMessage(), +          "IdentityLink generation for foreign person " + "FAILED."); +      Assert.assertEquals("Incorrect exception thrown", ((SzrCommunicationException) e.getCause()).getErrorId(), +          "ernb.01"); +      Assert.assertTrue("Incorrect exception thrown", e.getCause().getMessage().contains("Stammzahl response empty")); +    } +  } + +  @Test +  public void signContentExceptionTest() throws Exception { +    try { +      when(szrMock, "getStammzahlEncrypted", any(), any()).thenReturn(RandomStringUtils.randomNumeric(10)); +      when(szrMock, "signContent", any(), any(), any()).thenReturn(null); +      task.execute(pendingReq, executionContext); +    } catch (TaskExecutionException e) { +      Assert.assertEquals("Incorrect exception thrown", e.getMessage(), +          "IdentityLink generation for foreign person " + "FAILED."); +      Assert.assertEquals("Incorrect exception thrown", ((SzrCommunicationException) e.getCause()).getErrorId(), +          "ernb.01"); +      Assert.assertTrue("Incorrect exception thrown", e.getCause().getMessage().contains("BcBind response empty")); +    } +  } + +  private Pair<KeyStore, Provider> getKeyStore() throws EaafException { +    // read Connector wide config data TODO connector wide! +    String keyStoreName = basicConfig.getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEYSTORE_NAME); +    String keyStorePw = basicConfig.getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEYSTORE_PASSWORD); +    String keyStorePath = basicConfig.getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEYSTORE_PATH); +    String keyStoreType = basicConfig.getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_AUTHBLOCK_KEYSTORE_TYPE); + + +    //build new KeyStore configuration +    KeyStoreConfiguration keyStoreConfiguration = new KeyStoreConfiguration(); +    keyStoreConfiguration.setFriendlyName("jUnit test"); + +    keyStoreConfiguration.setSoftKeyStoreFilePath(keyStorePath); +    keyStoreConfiguration.setSoftKeyStorePassword(keyStorePw); +    keyStoreConfiguration.setKeyStoreType(KeyStoreConfiguration.KeyStoreType.fromString(keyStoreType)); +    keyStoreConfiguration.setKeyStoreName(keyStoreName); + +    //build new KeyStore based on configuration +    return keyStoreFactory.buildNewKeyStore(keyStoreConfiguration); + +  } + +  @NotNull +  private AuthenticationResponse buildDummyAuthResponse() throws URISyntaxException { +    final AttributeDefinition attributeDef = AttributeDefinition.builder() +        .friendlyName(Constants.eIDAS_ATTR_PERSONALIDENTIFIER).nameUri(new URI("ad", "sd", "ff")) +        .personType(PersonType.LEGAL_PERSON).xmlType(new QName("http://saf", "as", "af")) +        .attributeValueMarshaller("eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller").build(); +    final AttributeDefinition attributeDef2 = AttributeDefinition.builder() +        .friendlyName(Constants.eIDAS_ATTR_CURRENTFAMILYNAME).nameUri(new URI("ad", "sd", "fff")) +        .personType(PersonType.LEGAL_PERSON).xmlType(new QName("http://saf", "as", "aff")) +        .attributeValueMarshaller("eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller").build(); +    final AttributeDefinition attributeDef3 = AttributeDefinition.builder() +        .friendlyName(Constants.eIDAS_ATTR_CURRENTGIVENNAME).nameUri(new URI("ad", "sd", "ffff")) +        .personType(PersonType.LEGAL_PERSON).xmlType(new QName("http://saf", "as", "afff")) +        .attributeValueMarshaller("eu.eidas.auth.commons.attribute.impl.LiteralStringAttributeValueMarshaller").build(); +    final AttributeDefinition attributeDef4 = AttributeDefinition.builder() +        .friendlyName(Constants.eIDAS_ATTR_DATEOFBIRTH).nameUri(new URI("ad", "sd", "fffff")) +        .personType(PersonType.LEGAL_PERSON).xmlType(new QName("http://saf", "as", "affff")) +        .attributeValueMarshaller("eu.eidas.auth.commons.attribute.impl.DateTimeAttributeValueMarshaller").build(); + +    final ImmutableAttributeMap attributeMap = ImmutableAttributeMap.builder() +        .put(attributeDef, "de/st/" + RandomStringUtils.randomNumeric(64)) +        .put(attributeDef2, RandomStringUtils.randomAlphabetic(10)) +        .put(attributeDef3, RandomStringUtils.randomAlphabetic(10)).put(attributeDef4, "2001-01-01").build(); + +    val b = new AuthenticationResponse.Builder(); +    return b.id("aasdf").issuer("asd").subject("asf").statusCode("200").inResponseTo("asdf").subjectNameIdFormat("afaf") +        .attributes(attributeMap).build(); +  } +} diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/SpringTest-context_tasks_test.xml b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/SpringTest-context_tasks_test.xml index dd116bd3..7d5a4c53 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/SpringTest-context_tasks_test.xml +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/SpringTest-context_tasks_test.xml @@ -45,6 +45,9 @@        ref="specificConnectorAdditionalAttributesFileWithPath" />    </bean> +  <bean id="authBlockSigningService" +        class="at.asitplus.eidas.specific.modules.auth.eidas.v2.service.AuthBlockSigningService" /> +    <!-- Authentication Process Tasks -->    <bean id="ConnecteIDASNodeTask"      class="at.asitplus.eidas.specific.modules.auth.eidas.v2.tasks.GenerateAuthnRequestTask" diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_1.properties b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_1.properties index 35867187..21ed51e7 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_1.properties +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_1.properties @@ -50,6 +50,14 @@ eidas.ms.auth.eIDAS.szrclient.params.vkz=  eidas.ms.auth.eIDAS.szrclient.params.useSZRForbPKCalculation=false +eidas.ms.auth.eIDAS.authblock.keystore.password=f/+saJBc3a}*/T^s +eidas.ms.auth.eIDAS.authblock.keystore.friendlyName=connectorkeypair +eidas.ms.auth.eIDAS.authblock.keystore.path=./../keystore/teststore.jks +eidas.ms.auth.eIDAS.authblock.keystore.type=jks +eidas.ms.auth.eIDAS.authblock.key.alias=connectorkeypair +eidas.ms.auth.eIDAS.authblock.key.password=f/+saJBc3a}*/T^s + +  #Raw eIDAS Id data storage  eidas.ms.auth.eIDAS.szrclient.workarounds.eidmapping.revisionlog.active=true diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_2.properties b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_2.properties index 95ac8ec5..dcdadce5 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_2.properties +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_2.properties @@ -49,6 +49,14 @@ eidas.ms.auth.eIDAS.szrclient.params.vkz=  eidas.ms.auth.eIDAS.szrclient.params.useSZRForbPKCalculation=false +eidas.ms.auth.eIDAS.authblock.keystore.password=f/+saJBc3a}*/T^s +eidas.ms.auth.eIDAS.authblock.keystore.friendlyName=connectorkeypair +eidas.ms.auth.eIDAS.authblock.keystore.path=./../keystore/teststore.jks +eidas.ms.auth.eIDAS.authblock.keystore.type=jks +eidas.ms.auth.eIDAS.authblock.key.alias=connectorkeypair +eidas.ms.auth.eIDAS.authblock.key.password=f/+saJBc3a}*/T^s + +  #Raw eIDAS Id data storage  eidas.ms.auth.eIDAS.szrclient.workarounds.eidmapping.revisionlog.active=true diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_3.properties b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_3.properties new file mode 100644 index 00000000..c830d447 --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_3.properties @@ -0,0 +1,118 @@ +## Basic service configuration +eidas.ms.context.url.prefix= +eidas.ms.context.url.request.validation=false + +eidas.ms.context.use.clustermode=true + +##Monitoring +eidas.ms.monitoring.eIDASNode.metadata.url= + + +##Specific logger configuration +eidas.ms.technicallog.write.MDS.into.techlog=true +eidas.ms.revisionlog.write.MDS.into.revisionlog=true +eidas.ms.revisionlog.logIPAddressOfUser=true + +##Directory for static Web content +eidas.ms.webcontent.static.directory=webcontent/ +eidas.ms.webcontent.templates=templates/ +eidas.ms.webcontent.properties=properties/messages + +## extended validation of pending-request Id's +eidas.ms.core.pendingrequestid.maxlifetime=300 +eidas.ms.core.pendingrequestid.digist.algorithm=HmacSHA256 +eidas.ms.core.pendingrequestid.digist.secret=pendingReqIdSecret + +## eIDAS Ref. Implementation connector ### +eidas.ms.auth.eIDAS.node_v2.entityId=ownSpecificConnector +eidas.ms.auth.eIDAS.node_v2.forward.endpoint=http://test.com/ +eidas.ms.auth.eIDAS.node_v2.forward.method=POST +eidas.ms.auth.eIDAS.node_v2.countrycode=AT +eidas.ms.auth.eIDAS.node_v2.publicSectorTargets=.* +eidas.ms.auth.eIDAS.node_v2.workarounds.addAlwaysProviderName=true +eidas.ms.auth.eIDAS.node_v2.workarounds.useRequestIdAsTransactionIdentifier=true +eidas.ms.auth.eIDAS.node_v2.workarounds.useStaticProviderNameForPublicSPs=true +eidas.ms.auth.eIDAS.node_v2.staticProviderNameForPublicSPs=myNode + +eidas.ms.auth.eIDAS.node_v2.loa.requested.minimum=http://eidas.europa.eu/LoA/high + +eidas.ms.auth.eIDAS.szrclient.useTestService=true +eidas.ms.auth.eIDAS.szrclient.endpoint.prod= +eidas.ms.auth.eIDAS.szrclient.endpoint.test=http://localhost:1234/demoszr +eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.path=keys/..... +eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.password= +eidas.ms.auth.eIDAS.szrclient.ssl.trustStore.path= +eidas.ms.auth.eIDAS.szrclient.ssl.trustStore.password= +eidas.ms.auth.eIDAS.szrclient.timeout.connection=15 +eidas.ms.auth.eIDAS.szrclient.timeout.response=30 +eidas.ms.auth.eIDAS.szrclient.params.vkz= + +eidas.ms.auth.eIDAS.authblock.keystore.password=f/+saJBc3a}*/T^s +eidas.ms.auth.eIDAS.authblock.keystore.friendlyName=connectorkeypair +eidas.ms.auth.eIDAS.authblock.keystore.path=./../keystore/teststore.jks +eidas.ms.auth.eIDAS.authblock.keystore.type=jks +eidas.ms.auth.eIDAS.authblock.key.alias=connectorkeypair +eidas.ms.auth.eIDAS.authblock.key.password=f/+saJBc3a}*/T^s + + +eidas.ms.auth.eIDAS.szrclient.params.useSZRForbPKCalculation=false + + +#Raw eIDAS Id data storage +eidas.ms.auth.eIDAS.szrclient.workarounds.eidmapping.revisionlog.active=true + +eidas.ms.auth.eIDAS.szrclient.params.setPlaceOfBirthIfAvailable=true +eidas.ms.auth.eIDAS.szrclient.params.setBirthNameIfAvailable=true + +eidas.ms.auth.eIDAS.szrclient.debug.logfullmessages=true +eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution=false + +##without mandates +eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.0=PersonIdentifier,true +eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.1=FamilyName,true +eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.2=FirstName,true +eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.3=DateOfBirth,true + +eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.4=PlaceOfBirth,false +eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.5=BirthName,false +eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.6=Gender,false +eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.7=CurrentAddress,false +eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.8=testtest,false + +##with mandates ---- NOT FULLY SUPPORTED AT THE MOMENT ----- +eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.0=PersonIdentifier,true +eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.1=FamilyName,true +eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.2=FirstName,true +eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.3=DateOfBirth,true +eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.4=LegalPerson,true +eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.5=LegalName,true + + +## PVP2 S-Profile end-point configuration +eidas.ms.pvp2.keystore.path=keys/..... +eidas.ms.pvp2.keystore.password= +eidas.ms.pvp2.key.metadata.alias= +eidas.ms.pvp2.key.metadata.password= +eidas.ms.pvp2.key.signing.alias= +eidas.ms.pvp2.key.signing.password= +eidas.ms.pvp2.metadata.validity=24 + +## Service Provider configuration +eidas.ms.sp.0.uniqueID= +eidas.ms.sp.0.pvp2.metadata.truststore= +eidas.ms.sp.0.pvp2.metadata.truststore.password= +eidas.ms.sp.0.newEidMode=true + + +#eidas.ms.sp.0.friendlyName= +#eidas.ms.sp.0.pvp2.metadata.url= +#eidas.ms.sp.0.policy.allowed.requested.targets=.* +#eidas.ms.sp.0.policy.hasBaseIdTransferRestriction=false + + +##only for advanced config +eidas.ms.configuration.sp.disableRegistrationRequirement= +eidas.ms.configuration.restrictions.baseID.spTransmission= +eidas.ms.configuration.auth.default.countrycode= +eidas.ms.configuration.pvp.scheme.validation= +eidas.ms.configuration.pvp.enable.entitycategories=
\ No newline at end of file diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/keystore/teststore.jks b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/keystore/teststore.jksBinary files differ new file mode 100644 index 00000000..fcc6400c --- /dev/null +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/keystore/teststore.jks @@ -19,7 +19,7 @@      <!-- ===================================================================== -->      <egiz-spring-api>0.3</egiz-spring-api>      <egiz-eventlog-slf4jBackend>0.4</egiz-eventlog-slf4jBackend> -    <eaaf-core.version>1.1.8</eaaf-core.version> +    <eaaf-core.version>1.1.10-SNAPSHOT</eaaf-core.version>      <org.springframework.version>5.2.9.RELEASE</org.springframework.version>      <org.thymeleaf-spring5.version>3.0.11.RELEASE</org.thymeleaf-spring5.version>      <cxf.version>3.4.0</cxf.version> @@ -30,6 +30,8 @@      <com.google.guava.version>29.0-jre</com.google.guava.version>      <joda-time.version>2.10.6</joda-time.version>      <org.slf4j.version>1.7.30</org.slf4j.version> +    <jackson-datatype-jsr310.version>2.11.3</jackson-datatype-jsr310.version> +          <!-- testing -->      <junit.version>4.13</junit.version> @@ -202,6 +204,11 @@          <artifactId>commons-collections4</artifactId>          <version>${commons-collections4.version}</version>        </dependency> +      <dependency> +        <groupId>com.fasterxml.jackson.datatype</groupId> +        <artifactId>jackson-datatype-jsr310</artifactId> +        <version>${jackson-datatype-jsr310.version}</version> +      </dependency>        <!-- Testing --> | 
