diff options
Diffstat (limited to 'eaaf_modules/eaaf_module_auth_sl20')
11 files changed, 430 insertions, 174 deletions
| diff --git a/eaaf_modules/eaaf_module_auth_sl20/pom.xml b/eaaf_modules/eaaf_module_auth_sl20/pom.xml index a7ea1df0..cccb91ad 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/pom.xml +++ b/eaaf_modules/eaaf_module_auth_sl20/pom.xml @@ -6,7 +6,7 @@    <parent>      <groupId>at.gv.egiz.eaaf</groupId>      <artifactId>eaaf_modules</artifactId> -    <version>1.1.8</version> +    <version>1.1.11-SNAPSHOT</version>    </parent>    <artifactId>eaaf_module_auth_sl20</artifactId>    <name>Generic SL2.0 authentication</name> @@ -79,6 +79,16 @@        <artifactId>provider</artifactId>        <scope>test</scope>      </dependency>  +    <dependency> +      <groupId>iaik.prod</groupId> +      <artifactId>iaik_jce_full</artifactId> +      <scope>test</scope> +    </dependency> +    <dependency> +      <groupId>iaik.prod</groupId> +      <artifactId>iaik_eccelerate</artifactId> +      <scope>test</scope> +    </dependency>    </dependencies> @@ -146,4 +156,17 @@      </plugins>    </build> +  <repositories> +    <repository> +    	<id>MOA_Sig_local</id> +      	<name>MOA-Sig Dependencies</name> +      	<releases> +      		<enabled>true</enabled> +      		<checksumPolicy>ignore</checksumPolicy> +      	</releases> +        <layout>default</layout> +        <url>file://${basedir}/../eaaf_module_moa-sig/repository</url> +     </repository> +  </repositories> +  </project>
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualEidRequestTask.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualEidRequestTask.java index 5be5a61f..63bf7897 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualEidRequestTask.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualEidRequestTask.java @@ -2,6 +2,7 @@ package at.gv.egiz.eaaf.modules.auth.sl20.tasks;  import java.io.Serializable;  import java.net.ConnectException; +import java.nio.charset.StandardCharsets;  import java.security.cert.CertificateEncodingException;  import java.util.ArrayList;  import java.util.List; @@ -11,6 +12,19 @@ import java.util.Map;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.NameValuePair; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.message.BasicNameValuePair; +import org.jose4j.base64url.Base64Url; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.i18n.LocaleContextHolder; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +  import at.gv.egiz.eaaf.core.api.idp.IConfigurationWithSP;  import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration;  import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; @@ -29,22 +43,9 @@ import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoParserException;  import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20Constants;  import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20Constants.VdaAuthMethod;  import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20HttpBindingUtils; +import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20HttpBindingUtils.Sl20ResponseHolder;  import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20JsonBuilderUtils;  import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20JsonExtractorUtils; - -import org.apache.commons.lang3.StringUtils; -import org.apache.http.HttpResponse; -import org.apache.http.NameValuePair; -import org.apache.http.client.entity.UrlEncodedFormEntity; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.utils.URIBuilder; -import org.apache.http.message.BasicNameValuePair; -import org.jose4j.base64url.Base64Url; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.i18n.LocaleContextHolder; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode;  import lombok.extern.slf4j.Slf4j;  @Slf4j @@ -91,38 +92,42 @@ public abstract class AbstractCreateQualEidRequestTask extends AbstractAuthServl        // build request container        final String qualEidReqId = Random.nextProcessReferenceValue(); -      final ObjectNode sl20Req = SL20JsonBuilderUtils.createGenericRequest(qualEidReqId, null, null, -          signedQualEidCommand); +      final ObjectNode sl20Req = SL20JsonBuilderUtils.createGenericRequest(qualEidReqId,  +          pendingReq.getUniqueTransactionIdentifier(), null, signedQualEidCommand);        // build http POST request        final HttpPost httpReq = new HttpPost(new URIBuilder(vdaQualEidDUrl).build());        final List<NameValuePair> parameters = new ArrayList<>();        parameters.add(new BasicNameValuePair(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM, -          Base64Url.encode(sl20Req.toString().getBytes("UTF-8")))); +          Base64Url.encode(sl20Req.toString().getBytes(StandardCharsets.UTF_8))));        //inject additional request parameters        injectAdditionalSL20RequestParams(parameters, executionContext, request);        httpReq.setEntity(new UrlEncodedFormEntity(parameters)); -      // build http GET request -      // URIBuilder sl20ReqUri = new URIBuilder(vdaQualeIDUrl); -      // sl20ReqUri.addParameter(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM, -      // Base64Url.encode(sl20Req.toString().getBytes())); -      // HttpGet httpReq = new HttpGet(sl20ReqUri.build()); -        // set native client header        httpReq.addHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE, SL20Constants.HTTP_HEADER_VALUE_NATIVE); -      log.trace("Request VDA via SL20 with: " + Base64Url.encode(sl20Req.toString().getBytes("UTF-8"))); +      log.trace("Request VDA via SL20 with: {}", +          Base64Url.encode(sl20Req.toString().getBytes(StandardCharsets.UTF_8)));        // request VDA -      final HttpResponse httpResp = httpClientFactory.getHttpClient(false).execute(httpReq); - +      final Sl20ResponseHolder httpResp = httpClientFactory.getHttpClient(false).execute( +          httpReq, SL20HttpBindingUtils.sl20ResponseHandler()); + +      //check on error on http channel +      if (httpResp.getError() != null) { +        log.info("Basic SL2.0 response processing has an error. HTTP-StatusCode: {}  ErrorMsg: {}", +            httpResp.getResponseStatus().getStatusCode(), httpResp.getError().getMessage()); +        throw httpResp.getError(); +         +      } +              // parse response        log.info("Receive response from VDA ... "); -      final JsonNode sl20Resp = SL20JsonExtractorUtils.getSL20ContainerFromResponse(httpResp); -      final VerificationResult respPayloadContainer = SL20JsonExtractorUtils.extractSL20PayLoad(sl20Resp, null, false); +      final VerificationResult respPayloadContainer =  +          SL20JsonExtractorUtils.extractSL20PayLoad(httpResp.getResponseBody(), null, false);        if (respPayloadContainer.isValidSigned() == null) {          log.debug("Receive unsigned payLoad from VDA"); @@ -143,7 +148,7 @@ public abstract class AbstractCreateQualEidRequestTask extends AbstractAuthServl              SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_SIGNEDCOMMAND, false);          // create forward SL2.0 command -        final ObjectNode sl20Forward = sl20Resp.deepCopy(); +        final ObjectNode sl20Forward = httpResp.getResponseBody().deepCopy();          SL20JsonBuilderUtils.addOnlyOnceOfTwo(sl20Forward, SL20Constants.SL20_PAYLOAD, SL20Constants.SL20_SIGNEDPAYLOAD,              command.deepCopy(), signedCommand); @@ -227,7 +232,7 @@ public abstract class AbstractCreateQualEidRequestTask extends AbstractAuthServl      final Locale locale = LocaleContextHolder.getLocale();      final String language = locale.getLanguage();      if (StringUtils.isNotEmpty(language)) { -      log.trace("Find i18n context. Inject locale: {} into VDA request", locale.getLanguage()); +      log.trace("Find i18n context). Inject locale: {} into VDA request", locale.getLanguage());        parameters.add(new BasicNameValuePair(            SL20Constants.PARAM_SL20_REQ_AUTH_VDA_LOCALE,            language.toUpperCase(locale))); diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualEidTask.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualEidTask.java index 4786ff39..7591b3bd 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualEidTask.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualEidTask.java @@ -6,15 +6,6 @@ import java.util.Map;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse; -import org.apache.commons.lang3.StringUtils; -import org.jose4j.base64url.Base64Url; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; - -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.databind.JsonNode; -  import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;  import at.gv.egiz.eaaf.core.exceptions.EaafAuthenticationException;  import at.gv.egiz.eaaf.core.exceptions.EaafStorageException; @@ -36,6 +27,15 @@ import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20Constants;  import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20JsonExtractorUtils;  import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20ResponseUtils; +import org.apache.commons.lang3.StringUtils; +import org.jose4j.base64url.Base64Url; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonNode; +  public abstract class AbstractReceiveQualEidTask extends AbstractAuthServletTask {    private static final Logger log = LoggerFactory.getLogger(AbstractReceiveQualEidTask.class); @@ -117,7 +117,7 @@ public abstract class AbstractReceiveQualEidTask extends AbstractAuthServletTask              log.debug("VDA provides an optional sessionId. Inject it to internal error-holder ");              ex.setVdaSessionId(vdaSessionId); -          }           +          }            throw ex;          } else { @@ -161,7 +161,6 @@ public abstract class AbstractReceiveQualEidTask extends AbstractAuthServletTask          }        } catch (final EaafAuthenticationException e) { -        log.warn("SL2.0 processing error:", e);          if (sl20Result != null) {            log.debug("Received SL2.0 result: " + sl20Result);          } @@ -170,8 +169,8 @@ public abstract class AbstractReceiveQualEidTask extends AbstractAuthServletTask              new TaskExecutionException(pendingReq, "SL2.0 Authentication FAILED. Msg: " + e.getMessage(), e));        } catch (final Exception e) { -        log.warn("ERROR:", e); -        log.warn("SL2.0 Authentication FAILED with a generic error.", e); + +          if (sl20Result != null) {            log.debug("Received SL2.0 result: " + sl20Result);          } diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JoseUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JoseUtils.java index d8c39931..5b221bbe 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JoseUtils.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JoseUtils.java @@ -2,12 +2,19 @@ package at.gv.egiz.eaaf.modules.auth.sl20.utils;  import java.io.IOException;  import java.security.Key; +import java.security.KeyFactory;  import java.security.KeyStore; +import java.security.NoSuchAlgorithmException;  import java.security.Provider; +import java.security.PublicKey;  import java.security.cert.CertificateEncodingException;  import java.security.cert.X509Certificate;  import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey;  import java.security.interfaces.RSAPrivateKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec;  import java.util.Collections;  import java.util.List;  import java.util.Map; @@ -15,13 +22,8 @@ import java.util.Map.Entry;  import javax.annotation.Nonnull; -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 org.apache.commons.lang3.StringUtils; +import org.bouncycastle.jce.provider.BouncyCastleProvider;  import org.jose4j.jca.ProviderContext;  import org.jose4j.jwa.AlgorithmConstraints;  import org.jose4j.jws.AlgorithmIdentifiers; @@ -32,6 +34,11 @@ import org.jose4j.keys.resolvers.X509VerificationKeyResolver;  import org.jose4j.lang.JoseException;  import org.springframework.util.Base64Utils; +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; @@ -45,6 +52,8 @@ import lombok.extern.slf4j.Slf4j;  @Slf4j  public class JoseUtils { +  private static final Provider provider = new BouncyCastleProvider(); +      /**     * Create a JWS signature.     * @@ -161,7 +170,10 @@ public class JoseUtils {      // set signing information      final Pair<Key, X509Certificate[]> signingCred = EaafKeyStoreUtils.getPrivateKeyAndCertificates(          keyStore.getFirst(), keyAlias, keyPassword, true, friendlyNameForLogging); -    jws.setKey(signingCred.getFirst()); +     +    // set verification key +    jws.setKey(convertToBcKeyIfRequired(signingCred.getFirst())); +                    jws.setAlgorithmHeaderValue(getKeyOperationAlgorithmFromCredential(          jws.getKey(), rsaAlgToUse, eccAlgToUse, friendlyNameForLogging)); @@ -169,11 +181,16 @@ public class JoseUtils {      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()); +      providerCtx.getSuppliedKeyProviderContext().setSignatureProvider(keyStore.getSecond().getName()); +      providerCtx.getGeneralProviderContext().setGeneralProvider(BouncyCastleProvider.PROVIDER_NAME);        jws.setProviderContext(providerCtx); -    } +    } else { +      final ProviderContext providerCtx = new ProviderContext(); +      providerCtx.getGeneralProviderContext().setGeneralProvider(BouncyCastleProvider.PROVIDER_NAME); +      jws.setProviderContext(providerCtx); +       +    }       if (addFullCertChain) {        jws.setCertificateChainHeaderValue(signingCred.getSecond()); @@ -216,6 +233,8 @@ public class JoseUtils {        log.trace("Sorting received X509 certificates ... ");        final List<X509Certificate> sortedX5cCerts = X509Utils.sortCertificates(x5cCerts); +       +              if (trustedCerts.contains(sortedX5cCerts.get(0))) {          selectedKey = sortedX5cCerts.get(0).getPublicKey(); @@ -247,10 +266,15 @@ public class JoseUtils {        throw new JoseException("Can NOT select verification key for JWS. Signature verification FAILED");      } - +     +    //set BouncyCastleProvider as default provider +    final ProviderContext providerCtx = new ProviderContext(); +    providerCtx.getGeneralProviderContext().setGeneralProvider(BouncyCastleProvider.PROVIDER_NAME); +    jws.setProviderContext(providerCtx); +          // set verification key -    jws.setKey(selectedKey); - +    jws.setKey(convertToBcKeyIfRequired(selectedKey)); +           // load payLoad      return new JwsResult(          jws.verifySignature(), @@ -260,6 +284,48 @@ public class JoseUtils {    } +   +  /** +   * Convert an ECC public-key into BouncyCastle implementation. +   *   +   *  <p> IAIK JCE / Eccelerate ECC Keys are not compatible to JWS impl.</p> +   * @param input Key +   * @return input Key, or BC ECC-Key in case of a ECC Key  +   */ +  public static Key convertToBcKeyIfRequired(Key input) { +    try { +      if (input instanceof ECPublicKey  +          && "iaik.security.ec.common.ECPublicKey".equals(input.getClass().getName())) { + +        //convert Key to BouncyCastle KeyImplemenation because there is an  +        //incompatibility with IAIK EC Keys and JWS signature-verfification implementation +        PublicKey publicKey = KeyFactory.getInstance( +            input.getAlgorithm(), provider).generatePublic( +                new X509EncodedKeySpec(input.getEncoded())); +        return publicKey; +           +      } else if (input instanceof ECPrivateKey  +          && "iaik.security.ec.common.ECPrivateKey".equals(input.getClass().getName())) { +        //convert Key to BouncyCastle KeyImplemenation because there is an  +        //incompatibility with IAIK EC Keys and JWS signature-creation implementation +        Key privateKey = KeyFactory.getInstance( +            input.getAlgorithm(), provider).generatePrivate( +                new PKCS8EncodedKeySpec(input.getEncoded())); +         +        return privateKey; +       +      }  +             +    } catch (InvalidKeySpecException | NoSuchAlgorithmException e) { +      log.warn("Can NOT convert {} to {}. The verification may FAIL.",  +          input.getClass().getName(), PublicKey.class.getName(), e); +       +    } +     +    return input; +     +  } +      /**     * Select signature algorithm for a given credential.     * diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java index 10cfeafa..58e3e41c 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java @@ -13,25 +13,8 @@ import java.util.List;  import javax.annotation.Nonnull;  import javax.annotation.PostConstruct; -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.credential.KeyStoreConfiguration.KeyStoreType; -import at.gv.egiz.eaaf.core.impl.data.Pair; -import at.gv.egiz.eaaf.core.impl.utils.X509Utils; -import at.gv.egiz.eaaf.modules.auth.sl20.Constants; -import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20SecurityException; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoBuildException; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoParserException; -import at.gv.egiz.eaaf.modules.auth.sl20.utils.JoseUtils.JwsResult; -  import org.apache.commons.lang3.StringUtils; +import org.bouncycastle.jce.provider.BouncyCastleProvider;  import org.jose4j.jca.ProviderContext;  import org.jose4j.jwa.AlgorithmConstraints;  import org.jose4j.jwa.AlgorithmConstraints.ConstraintType; @@ -50,6 +33,24 @@ import org.springframework.util.Base64Utils;  import com.fasterxml.jackson.core.JsonParseException;  import com.fasterxml.jackson.databind.JsonNode; +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.credential.KeyStoreConfiguration.KeyStoreType; +import at.gv.egiz.eaaf.core.impl.data.Pair; +import at.gv.egiz.eaaf.core.impl.utils.X509Utils; +import at.gv.egiz.eaaf.modules.auth.sl20.Constants; +import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20SecurityException; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoBuildException; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoParserException; +import at.gv.egiz.eaaf.modules.auth.sl20.utils.JoseUtils.JwsResult; +  @Service  public class JsonSecurityUtils implements IJoseTools {    private static final Logger log = LoggerFactory.getLogger(JsonSecurityUtils.class); @@ -223,10 +224,15 @@ public class JsonSecurityUtils implements IJoseTools {        if (keyStore.getSecond() != null) {          log.trace("Injecting special Java Security Provider: {}", keyStore.getSecond().getName());          final ProviderContext providerCtx = new ProviderContext(); -        providerCtx.getSuppliedKeyProviderContext().setGeneralProvider( -            keyStore.getSecond().getName()); +        providerCtx.getSuppliedKeyProviderContext().setGeneralProvider(keyStore.getSecond().getName()); +        providerCtx.getGeneralProviderContext().setGeneralProvider(BouncyCastleProvider.PROVIDER_NAME);          receiverJwe.setProviderContext(providerCtx); +      } else { +        final ProviderContext providerCtx = new ProviderContext(); +        providerCtx.getGeneralProviderContext().setGeneralProvider(BouncyCastleProvider.PROVIDER_NAME); +        receiverJwe.setProviderContext(providerCtx); +                }        // validate key from header against key from config @@ -269,7 +275,7 @@ public class JsonSecurityUtils implements IJoseTools {        }        // set key -      receiverJwe.setKey(encryptionCred.getFirst()); +      receiverJwe.setKey(JoseUtils.convertToBcKeyIfRequired(encryptionCred.getFirst()));        // decrypt payload        return mapper.getMapper().readTree(receiverJwe.getPlaintextString()); diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20HttpBindingUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20HttpBindingUtils.java index 1d7c9646..d07c0e66 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20HttpBindingUtils.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20HttpBindingUtils.java @@ -3,23 +3,129 @@ package at.gv.egiz.eaaf.modules.auth.sl20.utils;  import java.io.IOException;  import java.io.StringWriter;  import java.net.URISyntaxException; +import java.text.MessageFormat;  import javax.annotation.Nonnull;  import javax.annotation.Nullable;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse; +import org.apache.http.Header; +import org.apache.http.HttpEntity; +import org.apache.http.ParseException; +import org.apache.http.StatusLine; +import org.apache.http.client.ResponseHandler;  import org.apache.http.client.utils.URIBuilder; +import org.apache.http.util.EntityUtils;  import org.jose4j.base64url.Base64Url;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus;  import org.springframework.http.MediaType;  import com.fasterxml.jackson.databind.JsonNode; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoParserException; +import lombok.Data; +import lombok.Getter; +  public class SL20HttpBindingUtils {    private static final Logger log = LoggerFactory.getLogger(SL20HttpBindingUtils.class); +  private static JsonMapper mapper = new JsonMapper(); +   +  @Data +  @Getter +  public static class Sl20ResponseHolder { +    private final JsonNode responseBody; +    private final StatusLine responseStatus; +    private SlCommandoParserException error; + +  } +   +  /** +   * Security-Layer 2.0 specific response-handler for Apache HTTP client. +   *  +   * @return {@link Sl20ResponseHolder} +   */ +  public static ResponseHandler<Sl20ResponseHolder> sl20ResponseHandler() { +    return response -> { +      try { +        final int httpStatusCode = response.getStatusLine().getStatusCode(); +        if (httpStatusCode == HttpStatus.OK.value()) { +          if (response.getEntity().getContentType() == null) { +            throw new SlCommandoParserException("SL20 response contains NO ContentType"); +             +          } + +          if (!response.getEntity().getContentType().getValue().startsWith("application/json")) { +            throw new SlCommandoParserException( +                "SL20 response with a wrong ContentType: " + response.getEntity().getContentType().getValue()); +             +          }  +           +          //parse OK response from body +          return new Sl20ResponseHolder(parseSL20ResultFromResponse(response.getEntity()), +              response.getStatusLine());                     +         +        } else if (httpStatusCode == HttpStatus.SEE_OTHER.value()  +            || httpStatusCode == HttpStatus.TEMPORARY_REDIRECT.value()) { +          final Header[] locationHeader = response.getHeaders("Location"); +          if (locationHeader == null) { +            throw new SlCommandoParserException("Find Redirect statuscode but not Location header"); +             +          } + +          final String sl20RespString = new URIBuilder(locationHeader[0].getValue()).getQueryParams().get(0).getValue(); +          return new Sl20ResponseHolder(mapper.getMapper().readTree(Base64Url.decode(sl20RespString)),  +              response.getStatusLine());  +                              +        } else if ( +            httpStatusCode == HttpStatus.INTERNAL_SERVER_ERROR.value()  +            || httpStatusCode == HttpStatus.UNAUTHORIZED.value() +            || httpStatusCode == HttpStatus.BAD_REQUEST.value()) { +          log.info("SL20 response with http-code: {}. Search for error message", httpStatusCode);                     +           +          String bodyMsg = "_EMPTY_"; +          try { +            //extract JSON body from defined http error-codes +            bodyMsg = EntityUtils.toString(response.getEntity());             +            log.info("SL20 response with http-code: {0} and errorMsg: {1}", httpStatusCode, bodyMsg); +            Sl20ResponseHolder holder = new Sl20ResponseHolder( +                mapper.getMapper().readTree(bodyMsg), response.getStatusLine()); +            return holder;  +             +          } catch (final IOException | ParseException e) { +            log.warn("SL20 response contains no valid JSON", e);             +            throw new SlCommandoParserException(MessageFormat.format( +                "SL20 response with http-code: {0} with body: {1} and generic response-processing error: {2}",  +                httpStatusCode, bodyMsg, e.getMessage())); +             +          } +       +        } else { +          //all other HTTP StatusCodes +          throw new SlCommandoParserException(MessageFormat.format( +              "SL20 response with http-code: {0} and errorMsg: {1}",  +              httpStatusCode, EntityUtils.toString(response.getEntity()))); +           +        } +       +      } catch (SlCommandoParserException e) { +        Sl20ResponseHolder holder = new Sl20ResponseHolder(null, response.getStatusLine()); +        holder.setError(e); +        return holder; +         +      } catch (final Exception e) {         +        Sl20ResponseHolder holder = new Sl20ResponseHolder(null, response.getStatusLine()); +        holder.setError( +            new SlCommandoParserException("SL20 response parsing FAILED! Reason: " + e.getMessage(), e)); +        return holder; +         +      } +    }; +  } +        /**     * Write SL2.0 response into http-response object     * @@ -59,6 +165,24 @@ public class SL20HttpBindingUtils {        httpResp.setHeader("Location", clientRedirectUri.build().toString());      } +  } +   +  private static JsonNode parseSL20ResultFromResponse(final HttpEntity resp) throws Exception { +    if (resp != null && resp.getContent() != null) { +      final String rawSL20Resp = EntityUtils.toString(resp); +      final JsonNode sl20Resp = mapper.getMapper().readTree(rawSL20Resp); + +      // TODO: check sl20Resp type like && sl20Resp.isJsonObject() +      if (sl20Resp != null) { +        return sl20Resp; + +      } else { +        throw new SlCommandoParserException("SL2.0 can NOT parse to a JSON object"); +      } + +    } else { +      throw new SlCommandoParserException("Can NOT find content in http response"); +    }    }  } diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonExtractorUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonExtractorUtils.java index 40ea0430..bed25c0c 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonExtractorUtils.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonExtractorUtils.java @@ -8,12 +8,6 @@ import java.util.List;  import java.util.Map;  import java.util.Map.Entry; -import org.apache.http.Header; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.client.utils.URIBuilder; -import org.apache.http.util.EntityUtils; -import org.jose4j.base64url.Base64Url;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory; @@ -299,84 +293,6 @@ public class SL20JsonExtractorUtils {    } -  /** -   * Extract generic transport container from httpResponse. -   * -   * @param httpResp Http response object -   * @return JSON with SL2.0 response -   * @throws SlCommandoParserException In case of an error -   */ -  public static JsonNode getSL20ContainerFromResponse(final HttpResponse httpResp) throws SlCommandoParserException { -    try { -      JsonNode sl20Resp = null; -      if (httpResp.getStatusLine().getStatusCode() == 303 || httpResp.getStatusLine().getStatusCode() == 307) { -        final Header[] locationHeader = httpResp.getHeaders("Location"); -        if (locationHeader == null) { -          throw new SlCommandoParserException("Find Redirect statuscode but not Location header"); -        } - -        final String sl20RespString = new URIBuilder(locationHeader[0].getValue()).getQueryParams().get(0).getValue(); -        sl20Resp = mapper.getMapper().readTree(Base64Url.decode(sl20RespString)); - -      } else if (httpResp.getStatusLine().getStatusCode() == 200) { -        if (httpResp.getEntity().getContentType() == null) { -          throw new SlCommandoParserException("SL20 response contains NO ContentType"); -        } - -        if (!httpResp.getEntity().getContentType().getValue().startsWith("application/json")) { -          throw new SlCommandoParserException( -              "SL20 response with a wrong ContentType: " + httpResp.getEntity().getContentType().getValue()); -        } -        sl20Resp = parseSL20ResultFromResponse(httpResp.getEntity()); - -      } else if (httpResp.getStatusLine().getStatusCode() == 500 || httpResp.getStatusLine().getStatusCode() == 401 -          || httpResp.getStatusLine().getStatusCode() == 400) { -        log.info( -            "SL20 response with http-code: " + httpResp.getStatusLine().getStatusCode() + ". Search for error message"); - -        try { -          sl20Resp = parseSL20ResultFromResponse(httpResp.getEntity()); - -        } catch (final Exception e) { -          log.warn("SL20 response contains no valid JSON", e); -          throw new SlCommandoParserException("SL20 response with http-code: " -              + httpResp.getStatusLine().getStatusCode() + " AND NO valid JSON errormsg", e); - -        } - -      } else { -        throw new SlCommandoParserException( -            "SL20 response with http-code: " + httpResp.getStatusLine().getStatusCode()); -      } - -      log.info("Find JSON object in http response"); -      return sl20Resp; - -    } catch (final Exception e) { -      throw new SlCommandoParserException("SL20 response parsing FAILED! Reason: " + e.getMessage(), e); - -    } -  } - -  private static JsonNode parseSL20ResultFromResponse(final HttpEntity resp) throws Exception { -    if (resp != null && resp.getContent() != null) { -      final String rawSL20Resp = EntityUtils.toString(resp); -      final JsonNode sl20Resp = mapper.getMapper().readTree(rawSL20Resp); - -      // TODO: check sl20Resp type like && sl20Resp.isJsonObject() -      if (sl20Resp != null) { -        return sl20Resp; - -      } else { -        throw new SlCommandoParserException("SL2.0 can NOT parse to a JSON object"); -      } - -    } else { -      throw new SlCommandoParserException("Can NOT find content in http response"); -    } - -  } -    private static JsonNode getAndCheck(final JsonNode input, final String keyID, final boolean isRequired)        throws SlCommandoParserException {      final JsonNode internal = input.get(keyID); diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/AbstractJsonSecurityUtilsTest.java b/eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/AbstractJsonSecurityUtilsTest.java index 917ef1e0..6550b026 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/AbstractJsonSecurityUtilsTest.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/AbstractJsonSecurityUtilsTest.java @@ -9,15 +9,6 @@ import java.security.Security;  import java.security.cert.CertificateEncodingException;  import java.security.cert.X509Certificate; -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.credential.KeyStoreConfiguration.KeyStoreType; -import at.gv.egiz.eaaf.core.impl.data.Pair; -import at.gv.egiz.eaaf.core.test.dummy.DummyAuthConfigMap; -import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult; -  import org.apache.commons.lang3.RandomStringUtils;  import org.bouncycastle.jce.provider.BouncyCastleProvider;  import org.jose4j.base64url.Base64Url; @@ -28,6 +19,7 @@ import org.jose4j.jwe.ContentEncryptionAlgorithmIdentifiers;  import org.jose4j.jwe.JsonWebEncryption;  import org.jose4j.jwe.KeyManagementAlgorithmIdentifiers;  import org.jose4j.lang.JoseException; +import org.junit.AfterClass;  import org.junit.Assert;  import org.junit.BeforeClass;  import org.junit.Test; @@ -38,6 +30,17 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;  import com.fasterxml.jackson.databind.JsonNode; +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.credential.KeyStoreConfiguration.KeyStoreType; +import at.gv.egiz.eaaf.core.impl.data.Pair; +import at.gv.egiz.eaaf.core.test.dummy.DummyAuthConfigMap; +import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult; +import iaik.security.ec.provider.ECCelerate; +import iaik.security.provider.IAIK; +  @RunWith(SpringJUnit4ClassRunner.class)  @ContextConfiguration("/spring/test_eaaf_sl20_hsm.beans.xml")  public abstract class AbstractJsonSecurityUtilsTest { @@ -46,12 +49,27 @@ public abstract class AbstractJsonSecurityUtilsTest {    @Autowired protected IJoseTools joseTools;    @Autowired protected EaafKeyStoreFactory keyStoreFactory; +  /** +   *jUnit test class initializer.  +   */    @BeforeClass    public static void classInitializer() { -    Security.addProvider(new BouncyCastleProvider()); +    IAIK.addAsProvider(); +    ECCelerate.addAsProvider(); +    Security.addProvider(new BouncyCastleProvider());    } +  /** +   * jUnit test class cleaner. +   */ +  @AfterClass +  public static final void classFinisher() {     +    Security.removeProvider(IAIK.getInstance().getName()); +    Security.removeProvider(ECCelerate.getInstance().getName()); +         +  } +      protected abstract void setRsaSigningKey();    protected abstract void setEcSigningKey(); @@ -78,7 +96,7 @@ public abstract class AbstractJsonSecurityUtilsTest {      final JsonWebEncryption jwe = new JsonWebEncryption();      jwe.setAlgorithmHeaderValue(KeyManagementAlgorithmIdentifiers.ECDH_ES_A256KW);      jwe.setEncryptionMethodHeaderParameter(ContentEncryptionAlgorithmIdentifiers.AES_128_GCM); -    jwe.setKey(joseTools.getEncryptionCertificate().getPublicKey()); +    jwe.setKey(JoseUtils.convertToBcKeyIfRequired(joseTools.getEncryptionCertificate().getPublicKey()));      jwe.setX509CertSha256ThumbprintHeaderValue(joseTools.getEncryptionCertificate());      jwe.setPayload(payLoad); @@ -88,8 +106,14 @@ public abstract class AbstractJsonSecurityUtilsTest {        final ProviderContext providerCtx = new ProviderContext();        providerCtx.getSuppliedKeyProviderContext().setSignatureProvider(            rsaEncKeyStore.getSecond().getName()); +      providerCtx.getGeneralProviderContext().setGeneralProvider(BouncyCastleProvider.PROVIDER_NAME);        jwe.setProviderContext(providerCtx); +    } else { +      final ProviderContext providerCtx = new ProviderContext(); +      providerCtx.getGeneralProviderContext().setGeneralProvider(BouncyCastleProvider.PROVIDER_NAME); +      jwe.setProviderContext(providerCtx); +            }      final String encData = jwe.getCompactSerialization(); @@ -141,7 +165,7 @@ public abstract class AbstractJsonSecurityUtilsTest {      final JsonWebEncryption jwe = new JsonWebEncryption();      jwe.setAlgorithmHeaderValue(KeyManagementAlgorithmIdentifiers.ECDH_ES_A256KW);      jwe.setEncryptionMethodHeaderParameter(ContentEncryptionAlgorithmIdentifiers.AES_128_GCM); -    jwe.setKey(key.getSecond()[0].getPublicKey()); +    jwe.setKey(JoseUtils.convertToBcKeyIfRequired(key.getSecond()[0].getPublicKey()));      jwe.setPayload(payLoad);      // set special provider if required @@ -149,8 +173,14 @@ public abstract class AbstractJsonSecurityUtilsTest {        final ProviderContext providerCtx = new ProviderContext();        providerCtx.getSuppliedKeyProviderContext().setSignatureProvider(            rsaEncKeyStore.getSecond().getName()); +      providerCtx.getGeneralProviderContext().setGeneralProvider(BouncyCastleProvider.PROVIDER_NAME);        jwe.setProviderContext(providerCtx); +    } else { +      final ProviderContext providerCtx = new ProviderContext(); +      providerCtx.getGeneralProviderContext().setGeneralProvider(BouncyCastleProvider.PROVIDER_NAME); +      jwe.setProviderContext(providerCtx); +            }      final String encData = jwe.getCompactSerialization(); diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JoseUtilsTest.java b/eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JoseUtilsTest.java new file mode 100644 index 00000000..b5a7639e --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JoseUtilsTest.java @@ -0,0 +1,83 @@ +package at.gv.egiz.eaaf.modules.auth.sl20.utils; + +import java.io.IOException; +import java.security.NoSuchProviderException; +import java.security.Security; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.jose4j.jwa.AlgorithmConstraints; +import org.jose4j.jwa.AlgorithmConstraints.ConstraintType; +import org.jose4j.jws.AlgorithmIdentifiers; +import org.jose4j.lang.JoseException; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.BlockJUnit4ClassRunner; + +import at.gv.egiz.eaaf.modules.auth.sl20.utils.JoseUtils.JwsResult; +import iaik.security.ec.provider.ECCelerate; +import iaik.security.provider.IAIK; + +@RunWith(BlockJUnit4ClassRunner.class) +public class JoseUtilsTest { + +  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)); + +  /** +   *jUnit test class initializer.  +   */ +  @BeforeClass +  public static final void classInitializer() { +    IAIK.addAsProvider(); +    ECCelerate.addAsProvider(); +     +  } +   +  /** +   * jUnit test class cleaner. +   */ +  @AfterClass +  public static final void classFinisher() {     +    Security.removeProvider(IAIK.getInstance().getName()); +    Security.removeProvider(ECCelerate.getInstance().getName()); +         +  } +   +  @Test +  public void testBindingAuthBlock() throws JoseException, IOException, CertificateException, NoSuchProviderException { +     +    final String serializedContent = IOUtils.toString(JoseUtils.class.getResourceAsStream( +        "/data/bindingAuth1.jws"), "UTF-8"); +         +    final iaik.x509.X509Certificate trustedCert = new iaik.x509.X509Certificate(JoseUtils.class +        .getResourceAsStream("/data/bindingAuth1.crt")); +             +    final List<X509Certificate> trustedCerts = Arrays.asList(trustedCert); +    final AlgorithmConstraints constraints = new AlgorithmConstraints(ConstraintType.PERMIT, +        BINDING_AUTH_ALGORITHM_WHITELIST_SIGNING +            .toArray(new String[BINDING_AUTH_ALGORITHM_WHITELIST_SIGNING.size()])); + +    final JwsResult result = JoseUtils.validateSignature(serializedContent, trustedCerts, constraints); + +    Assert.assertNotNull("JWS verify result", result); +    Assert.assertTrue("JWS not valid", result.isValid()); +    Assert.assertNotNull("JWS payload", result.getPayLoad()); +    Assert.assertNotNull("JWS Headers", result.getFullJoseHeader()); +    Assert.assertNotNull("JWS Signercerts", result.getX5cCerts()); +    Assert.assertEquals("Signercerts size", 1, result.getX5cCerts().size()); +    Assert.assertArrayEquals("Signercerts", trustedCert.getEncoded(), result.getX5cCerts().get(0).getEncoded()); + +  } +} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/bindingAuth1.crt b/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/bindingAuth1.crt new file mode 100644 index 00000000..11c17e71 --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/bindingAuth1.crt @@ -0,0 +1,3 @@ +-----BEGIN CERTIFICATE----- +MIIBXzCCAQWgAwIBAgIIPuBGtvo16nUwCgYIKoZIzj0EAwIwGjEYMBYGA1UEAwwPRHVtbXlQa2lTZXJ2aWNlMB4XDTIwMTAwNzEyMTAyMVoXDTIxMTAwNzEyMTAyMVowUTEpMCcGA1UEAwwgNWMzM2Q3MjdlY2YzZTAyYTE2NmYzYWI2NWZiYTEzOGExFDASBgNVBAoMC0VJRC1ERVYtUEtJMQ4wDAYDVQQLDAVULUVudjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABACA6RBPYIX3i0+TqYq2gb3XAD0B1/tee3/lP8sPc+tt6GFDN0Vsos77VojhRQnGRndmoWi9OW7KS5uQe+5++W8wCgYIKoZIzj0EAwIDSAAwRQIhAO7NlM4YfnapZ9Vam/LF/5ASPGbN4SK0fK4bhGHQw8yIAiB77JHkZIaDtgCcv7CSPf/mvldSf5ViPelhuZBPSLRUsQ== +-----END CERTIFICATE----- diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/bindingAuth1.jws b/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/bindingAuth1.jws new file mode 100644 index 00000000..6ba84d97 --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/bindingAuth1.jws @@ -0,0 +1 @@ +eyJ4NWMiOlsiTUlJQlh6Q0NBUVdnQXdJQkFnSUlQdUJHdHZvMTZuVXdDZ1lJS29aSXpqMEVBd0l3R2pFWU1CWUdBMVVFQXd3UFJIVnRiWGxRYTJsVFpYSjJhV05sTUI0WERUSXdNVEF3TnpFeU1UQXlNVm9YRFRJeE1UQXdOekV5TVRBeU1Wb3dVVEVwTUNjR0ExVUVBd3dnTldNek0yUTNNamRsWTJZelpUQXlZVEUyTm1ZellXSTJOV1ppWVRFek9HRXhGREFTQmdOVkJBb01DMFZKUkMxRVJWWXRVRXRKTVE0d0RBWURWUVFMREFWVUxVVnVkakJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCQUNBNlJCUFlJWDNpMCtUcVlxMmdiM1hBRDBCMVwvdGVlM1wvbFA4c1BjK3R0NkdGRE4wVnNvczc3Vm9qaFJRbkdSbmRtb1dpOU9XN0tTNXVRZSs1KytXOHdDZ1lJS29aSXpqMEVBd0lEU0FBd1JRSWhBTzdObE00WWZuYXBaOVZhbVwvTEZcLzVBU1BHYk40U0swZks0YmhHSFF3OHlJQWlCNzdKSGtaSWFEdGdDY3Y3Q1NQZlwvbXZsZFNmNVZpUGVsaHVaQlBTTFJVc1E9PSJdLCJ0eXAiOiJiaW5kaW5nQXV0aCIsImFsZyI6IkVTMjU2In0.MzIxZmVmYTQtODVkOC00YmE5LWE0MmUtYWY4MzM3YTEyNTA1.diiXXegwv3Gu6ezJRxf7F5BnRxNhTnBXJ0D5RX4OqDxs2QvfzSPA4mOkUed18_56aILMBLVL-XIMszNILfp7OA
\ No newline at end of file | 
