summaryrefslogtreecommitdiff
path: root/eaaf_modules/eaaf_module_auth_sl20/src
diff options
context:
space:
mode:
Diffstat (limited to 'eaaf_modules/eaaf_module_auth_sl20/src')
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualEidRequestTask.java65
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualEidTask.java25
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JoseUtils.java92
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java48
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20HttpBindingUtils.java124
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonExtractorUtils.java84
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/AbstractJsonSecurityUtilsTest.java54
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/test/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JoseUtilsTest.java83
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/bindingAuth1.crt3
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/test/resources/data/bindingAuth1.jws1
10 files changed, 406 insertions, 173 deletions
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