summaryrefslogtreecommitdiff
path: root/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20
diff options
context:
space:
mode:
Diffstat (limited to 'eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20')
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/AbstractSL20AuthenticationModulImpl.java10
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/Constants.java36
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/EventCodes.java2
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20EidDataValidationException.java19
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20Exception.java2
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualEidRequestTask.java160
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualEidTask.java23
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JoseUtils.java374
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java161
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20Constants.java19
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20HttpBindingUtils.java138
-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/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20ResponseUtils.java14
13 files changed, 741 insertions, 301 deletions
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/AbstractSL20AuthenticationModulImpl.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/AbstractSL20AuthenticationModulImpl.java
index e9932ae8..d561a0bc 100644
--- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/AbstractSL20AuthenticationModulImpl.java
+++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/AbstractSL20AuthenticationModulImpl.java
@@ -29,11 +29,9 @@ public abstract class AbstractSL20AuthenticationModulImpl implements AuthModule
private int priority = 3;
public static final List<String> VDA_TYPE_IDS = Arrays.asList("1", "2", "3", "4");
-
+
@Autowired(required = true)
protected IConfiguration authConfig;
- @Autowired(required = true)
- private AbstractAuthenticationManager authManager;
@Override
public int getPriority() {
@@ -51,9 +49,9 @@ public abstract class AbstractSL20AuthenticationModulImpl implements AuthModule
@PostConstruct
protected void initalSL20Authentication() {
- // parameter to whiteList
- authManager.addHeaderNameToWhiteList(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE);
- authManager.addHeaderNameToWhiteList(SL20Constants.HTTP_HEADER_SL20_VDA_TYPE);
+ // parameter to whiteList
+ AbstractAuthenticationManager.addHeaderNameToWhiteList(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE);
+ AbstractAuthenticationManager.addHeaderNameToWhiteList(SL20Constants.HTTP_HEADER_SL20_VDA_TYPE);
}
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/Constants.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/Constants.java
index 11fd41fb..74d67d01 100644
--- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/Constants.java
+++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/Constants.java
@@ -7,37 +7,41 @@ public class Constants {
public static final String CONFIG_PROP_VDA_AUTHBLOCK_TRANSFORMATION_ID = CONFIG_PROP_PREFIX
+ ".vda.authblock.transformation.id";
-
+
//KeyStore configuration
- public static final String CONFIG_PROP_SECURITY_KEYSTORE_TYPE =
+ public static final String CONFIG_PROP_SECURITY_KEYSTORE_TYPE =
CONFIG_PROP_PREFIX + ".security.keystore.type";
- public static final String CONFIG_PROP_SECURITY_KEYSTORE_NAME =
+ public static final String CONFIG_PROP_SECURITY_KEYSTORE_NAME =
CONFIG_PROP_PREFIX + ".security.keystore.name";
- public static final String CONFIG_PROP_SECURITY_KEYSTORE_PATH =
+ public static final String CONFIG_PROP_SECURITY_KEYSTORE_PATH =
CONFIG_PROP_PREFIX + ".security.keystore.path";
- public static final String CONFIG_PROP_SECURITY_KEYSTORE_PASSWORD =
+ public static final String CONFIG_PROP_SECURITY_KEYSTORE_PASSWORD =
CONFIG_PROP_PREFIX + ".security.keystore.password";
-
- public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_ALIAS =
+
+ public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_ALIAS =
CONFIG_PROP_PREFIX + ".security.sign.alias";
- public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_PASSWORD =
+ public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_PASSWORD =
CONFIG_PROP_PREFIX + ".security.sign.password";
- public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_ALIAS =
+ public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_ALIAS =
CONFIG_PROP_PREFIX + ".security.encryption.alias";
- public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_PASSWORD =
+ public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_PASSWORD =
CONFIG_PROP_PREFIX + ".security.encryption.password";
//TrustStore configuration
- public static final String CONFIG_PROP_SECURITY_TRUSTSTORE_TYPE =
+ public static final String CONFIG_PROP_SECURITY_TRUSTSTORE_TYPE =
CONFIG_PROP_PREFIX + ".security.truststore.type";
- public static final String CONFIG_PROP_SECURITY_TRUSTSTORE_NAME =
+ public static final String CONFIG_PROP_SECURITY_TRUSTSTORE_NAME =
CONFIG_PROP_PREFIX + ".security.truststore.name";
- public static final String CONFIG_PROP_SECURITY_TRUSTSTORE_PATH =
+ public static final String CONFIG_PROP_SECURITY_TRUSTSTORE_PATH =
CONFIG_PROP_PREFIX + ".security.truststore.path";
- public static final String CONFIG_PROP_SECURITY_TRUSTSTORE_PASSWORD =
+ public static final String CONFIG_PROP_SECURITY_TRUSTSTORE_PASSWORD =
CONFIG_PROP_PREFIX + ".security.truststore.password";
-
-
+
+ public static final String CONFIG_PROP_SECURITY_SIG_ALG_RSA =
+ CONFIG_PROP_PREFIX + ".security.sigalg.rsa";
+ public static final String CONFIG_PROP_SECURITY_SIG_ALG_ECC =
+ CONFIG_PROP_PREFIX + ".security.sigalg.ecc";
+
public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT = "default";
public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT = CONFIG_PROP_VDA_ENDPOINT_QUALeID
+ CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT;
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/EventCodes.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/EventCodes.java
index af155206..62779072 100644
--- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/EventCodes.java
+++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/EventCodes.java
@@ -12,5 +12,5 @@ public class EventCodes {
public static final int AUTHPROCESS_SL20_ENDPOINT_URL = 4112;
public static final int AUTHPROCESS_SL20_DATAURL_IP = 4113;
- public static final int AUTHPROCESS_SL20_CONSENT_VALID = 4113;
+ public static final int AUTHPROCESS_SL20_CONSENT_VALID = 4114;
}
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20EidDataValidationException.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20EidDataValidationException.java
index a14fbe9e..f0d993ca 100644
--- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20EidDataValidationException.java
+++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20EidDataValidationException.java
@@ -1,15 +1,26 @@
package at.gv.egiz.eaaf.modules.auth.sl20.exceptions;
public class SL20EidDataValidationException extends SL20Exception {
- private static final long serialVersionUID = 1L;
+
+ private static final long serialVersionUID = -2604130523926584663L;
public SL20EidDataValidationException(final Object[] parameters) {
- super("sl20.07", parameters);
+ this("99", parameters);
}
-
+
public SL20EidDataValidationException(final Object[] parameters, final Throwable e) {
- super("sl20.07", parameters, e);
+ this("99", parameters, e);
+
+ }
+
+ public SL20EidDataValidationException(final String subErrorId, final Object[] parameters) {
+ super("sl20.07." + subErrorId, parameters);
+
+ }
+
+ public SL20EidDataValidationException(final String subErrorId, final Object[] parameters, final Throwable e) {
+ super("sl20.07." + subErrorId, parameters, e);
}
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20Exception.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20Exception.java
index 12921ad6..08373a2d 100644
--- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20Exception.java
+++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20Exception.java
@@ -4,7 +4,7 @@ import at.gv.egiz.eaaf.core.exceptions.EaafAuthenticationException;
public class SL20Exception extends EaafAuthenticationException {
- private static final long serialVersionUID = 1L;
+ private static final long serialVersionUID = -6716465236880571576L;
public SL20Exception(final String messageId, final Object[] parameters) {
super(messageId, parameters);
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 6c11fa63..9dcfbe75 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
@@ -1,25 +1,29 @@
package at.gv.egiz.eaaf.modules.auth.sl20.tasks;
import java.io.Serializable;
+import java.net.SocketException;
+import java.net.SocketTimeoutException;
+import java.nio.charset.StandardCharsets;
import java.security.cert.CertificateEncodingException;
import java.util.ArrayList;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
+import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
-import org.apache.http.HttpResponse;
+import org.apache.commons.lang3.time.StopWatch;
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.slf4j.Logger;
-import org.slf4j.LoggerFactory;
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;
@@ -33,7 +37,6 @@ import at.gv.egiz.eaaf.core.impl.http.IHttpClientFactory;
import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask;
import at.gv.egiz.eaaf.core.impl.utils.KeyValueUtils;
import at.gv.egiz.eaaf.core.impl.utils.Random;
-import at.gv.egiz.eaaf.core.impl.utils.TransactionIdUtils;
import at.gv.egiz.eaaf.modules.auth.sl20.Constants;
import at.gv.egiz.eaaf.modules.auth.sl20.EventCodes;
import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult;
@@ -42,12 +45,16 @@ 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 lombok.extern.slf4j.Slf4j;
+@Slf4j
public abstract class AbstractCreateQualEidRequestTask extends AbstractAuthServletTask {
- private static final Logger log = LoggerFactory.getLogger(AbstractCreateQualEidRequestTask.class);
+ private static final String FRIENDLYNAME_HTTP_CLIENT = "A-Trust Client";
+
@Autowired(required = true)
private IHttpClientFactory httpClientFactory;
@Autowired(required = true)
@@ -60,7 +67,8 @@ public abstract class AbstractCreateQualEidRequestTask extends AbstractAuthServl
log.debug("Starting SL2.0 authentication process .... ");
revisionsLogger.logEvent(pendingReq, EventCodes.AUTHPROCESS_SL20_SELECTED, "sl20auth");
-
+
+ String vdaQualEidDUrl = null;
try {
// get service-provider configuration
final ISpConfiguration oaConfig = pendingReq.getServiceProviderConfiguration();
@@ -72,7 +80,7 @@ public abstract class AbstractCreateQualEidRequestTask extends AbstractAuthServl
}
// get basic configuration parameters
- final String vdaQualEidDUrl = extractVdaUrlForSpecificOa(oaConfig, executionContext);
+ vdaQualEidDUrl = extractVdaUrlForSpecificOa(oaConfig, executionContext);
if (StringUtils.isEmpty(vdaQualEidDUrl)) {
log.error("NO VDA URL for qualified eID (" + Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT + ")");
throw new SL20Exception("sl20.03", new Object[] { "NO VDA URL for qualified eID" });
@@ -89,55 +97,48 @@ 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"))));
-
- //set specific authentication method if it was selection by process step before
- VdaAuthMethod authMethod = getVdaAuthMethodFromContext(executionContext);
- if (authMethod != null) {
- log.debug("Request VDA with authType: {}", authMethod);
- parameters.add(new BasicNameValuePair(SL20Constants.PARAM_SL20_REQ_AUTH_METHOD_PARAM,
- authMethod.getAuthMethod()));
- }
+ Base64Url.encode(sl20Req.toString().getBytes(StandardCharsets.UTF_8))));
- //set VDA sessionId if it was available on context
- String vdaSessionId = getVdaSessionIdFromContext(executionContext);
- if (vdaSessionId != null) {
- log.trace("Request VDA with sessionId: {}", vdaSessionId);
- parameters.add(new BasicNameValuePair(
- SL20Constants.PARAM_SL20_REQ_AUTH_VDA_SESSIONID,
- vdaSessionId));
-
- }
-
-
-
- httpReq.setEntity(new UrlEncodedFormEntity(parameters));
+ //inject additional request parameters
+ injectAdditionalSL20RequestParams(parameters, executionContext, request);
- // 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());
+ httpReq.setEntity(new UrlEncodedFormEntity(parameters));
// 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);
-
- // parse response
- log.info("Receive response from VDA ... ");
- final JsonNode sl20Resp = SL20JsonExtractorUtils.getSL20ContainerFromResponse(httpResp);
- final VerificationResult respPayloadContainer = SL20JsonExtractorUtils.extractSL20PayLoad(sl20Resp, null, false);
+
+ final StopWatch watch = StopWatch.createStarted();
+ log.info("Requesting {} for authentication ... ", FRIENDLYNAME_HTTP_CLIENT);
+ final Sl20ResponseHolder httpResp = httpClientFactory.getHttpClient(false).execute(
+ httpReq, SL20HttpBindingUtils.sl20ResponseHandler());
+
+ watch.stop();
+ log.info("Respone from {} received after: {}[ms] with statusCode: {}", FRIENDLYNAME_HTTP_CLIENT,
+ watch.getTime(TimeUnit.MILLISECONDS), httpResp.getResponseStatus().getStatusCode());
+
+ //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
+ final VerificationResult respPayloadContainer =
+ SL20JsonExtractorUtils.extractSL20PayLoad(httpResp.getResponseBody(), null, false);
if (respPayloadContainer.isValidSigned() == null) {
log.debug("Receive unsigned payLoad from VDA");
@@ -158,10 +159,10 @@ 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);
-
+
// store pending request
pendingReq.setRawDataToTransaction(Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_REQID,
qualEidReqId);
@@ -201,21 +202,58 @@ public abstract class AbstractCreateQualEidRequestTask extends AbstractAuthServl
} catch (final EaafAuthenticationException e) {
throw new TaskExecutionException(pendingReq, "SL2.0 Authentication FAILED. Msg: " + e.getMessage(), e);
+ } catch (final SocketException | SocketTimeoutException e) {
+ log.error("SL2.0 Authentication has a VDA connector error. Endpoint: {}",
+ vdaQualEidDUrl, e);
+ throw new TaskExecutionException(pendingReq, e.getMessage(),
+ new SL20Exception("sl20.02", new Object[] { e.getMessage()}, e));
+
} catch (final Exception e) {
log.warn("SL2.0 Authentication FAILED with a generic error.", e);
throw new TaskExecutionException(pendingReq, e.getMessage(), e);
- } finally {
- TransactionIdUtils.removeTransactionId();
- TransactionIdUtils.removeSessionId();
+ }
+
+ }
+ protected void injectAdditionalSL20RequestParams(List<NameValuePair> parameters,
+ ExecutionContext executionContext, HttpServletRequest request) {
+ //set specific authentication method if it was selection by process step before
+ final VdaAuthMethod authMethod = getVdaAuthMethodFromContext(executionContext);
+ if (authMethod != null) {
+ log.debug("Request VDA with authType: {}", authMethod);
+ parameters.add(new BasicNameValuePair(SL20Constants.PARAM_SL20_REQ_AUTH_METHOD_PARAM,
+ authMethod.getAuthMethod()));
}
+ //set VDA sessionId if it was available on context
+ final String vdaSessionId = getVdaSessionIdFromContext(executionContext);
+ if (vdaSessionId != null) {
+ log.trace("Request VDA with sessionId: {}", vdaSessionId);
+ parameters.add(new BasicNameValuePair(
+ SL20Constants.PARAM_SL20_REQ_AUTH_VDA_SESSIONID,
+ vdaSessionId));
+
+ }
+
+ //set i18n language into VDA request
+ 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());
+ parameters.add(new BasicNameValuePair(
+ SL20Constants.PARAM_SL20_REQ_AUTH_VDA_LOCALE,
+ language.toUpperCase(locale)));
+
+ } else {
+ log.info("Find i18n context, but Language is UNKNOWN. It will be ignored");
+
+ }
}
/**
- * Get ExecutionContext parameter-key for VDA AuthMethod information.
- *
+ * Get ExecutionContext parameter-key for VDA AuthMethod information.
+ *
* @return Key to get AuthMethod from {@link ExecutionContext}
*/
protected abstract String getAuthMethodContextParamKey();
@@ -231,34 +269,34 @@ public abstract class AbstractCreateQualEidRequestTask extends AbstractAuthServl
*/
protected abstract String buildSignedQualifiedEidCommand() throws CertificateEncodingException, SL20Exception;
-
+
private VdaAuthMethod getVdaAuthMethodFromContext(ExecutionContext executionContext) {
- Serializable authMethodRaw = executionContext.get(getAuthMethodContextParamKey());
+ final Serializable authMethodRaw = executionContext.get(getAuthMethodContextParamKey());
if (authMethodRaw instanceof String) {
log.trace("Find authMethod parameter: {} on context", authMethodRaw);
return VdaAuthMethod.fromString((String) authMethodRaw);
-
+
}
-
+
return null;
}
-
+
private String getVdaSessionIdFromContext(ExecutionContext executionContext) {
- Serializable vdaSessionId = executionContext.get(
+ final Serializable vdaSessionId = executionContext.get(
SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERROR_VDASESSIONID);
- if (vdaSessionId instanceof String
+ if (vdaSessionId instanceof String
&& StringUtils.isNotEmpty((CharSequence) vdaSessionId)) {
executionContext.remove(
SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERROR_VDASESSIONID);
-
+
log.trace("Find vdaSessionId parameter: {} on context", vdaSessionId);
return (String) vdaSessionId;
-
+
}
-
+
return null;
}
-
+
private String extractVdaUrlForSpecificOa(final ISpConfiguration oaConfig, final ExecutionContext executionContext) {
// load SP specific config for development and testing purposes
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..dfa05a89 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
@@ -8,8 +8,6 @@ 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;
@@ -22,7 +20,6 @@ import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException;
import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask;
import at.gv.egiz.eaaf.core.impl.utils.DataUrlBuilder;
import at.gv.egiz.eaaf.core.impl.utils.StreamUtils;
-import at.gv.egiz.eaaf.core.impl.utils.TransactionIdUtils;
import at.gv.egiz.eaaf.modules.auth.sl20.Constants;
import at.gv.egiz.eaaf.modules.auth.sl20.EventCodes;
import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult;
@@ -35,9 +32,10 @@ import at.gv.egiz.eaaf.modules.auth.sl20.utils.JsonMapper;
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 lombok.extern.slf4j.Slf4j;
+@Slf4j
public abstract class AbstractReceiveQualEidTask extends AbstractAuthServletTask {
- private static final Logger log = LoggerFactory.getLogger(AbstractReceiveQualEidTask.class);
@Autowired(required = true)
private IJoseTools joseTools;
@@ -82,13 +80,14 @@ public abstract class AbstractReceiveQualEidTask extends AbstractAuthServletTask
sl20ReqObj = new JsonMapper().getMapper().readTree(Base64Url.decodeToUtf8String(sl20Result));
} catch (final JsonParseException e) {
- log.warn("SL2.0 command or result is NOT valid JSON.", e);
- log.debug("SL2.0 msg: " + sl20Result);
+ log.error("SL2.0 command or result is NOT valid JSON. Received msg: {}", sl20Result, e);
throw new SL20Exception("sl20.02", new Object[] { "SL2.0 command or result is NOT valid JSON." },
e);
}
+ log.info("Receive response from A-Trust. Starting response-message validation ... ");
+
// check on errorMessage
final VerificationResult payLoadContainerErrorCheck = SL20JsonExtractorUtils.extractSL20PayLoad(
sl20ReqObj,
@@ -117,7 +116,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 +160,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 +168,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);
}
@@ -212,11 +210,6 @@ public abstract class AbstractReceiveQualEidTask extends AbstractAuthServletTask
log.error("Can NOT send error message. SOMETHING IS REALY WRONG!", e);
}
-
- } finally {
- TransactionIdUtils.removeTransactionId();
- TransactionIdUtils.removeSessionId();
-
}
}
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
new file mode 100644
index 00000000..5b221bbe
--- /dev/null
+++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JoseUtils.java
@@ -0,0 +1,374 @@
+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;
+import java.util.Map.Entry;
+
+import javax.annotation.Nonnull;
+
+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;
+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 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;
+
+/**
+ * {@link JoseUtils} provides static methods JWS and JWE processing.
+ *
+ * @author tlenz
+ *
+ */
+@Slf4j
+public class JoseUtils {
+
+ private static final Provider provider = new BouncyCastleProvider();
+
+ /**
+ * Create a JWS signature.
+ *
+ * <p>
+ * Use {@link org.jose4j.jws.AlgorithmIdentifiers.RSA_PSS_USING_SHA256} in case
+ * of a RSA based key and
+ * {@link org.jose4j.jws.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 org.jose4j.jws.AlgorithmIdentifiers.RSA_PSS_USING_SHA256} in case
+ * of a RSA based key and
+ * {@link org.jose4j.jws.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);
+
+ // set verification key
+ jws.setKey(convertToBcKeyIfRequired(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());
+ 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());
+
+ }
+
+ 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 BouncyCastleProvider as default provider
+ final ProviderContext providerCtx = new ProviderContext();
+ providerCtx.getGeneralProviderContext().setGeneralProvider(BouncyCastleProvider.PROVIDER_NAME);
+ jws.setProviderContext(providerCtx);
+
+ // set verification key
+ jws.setKey(convertToBcKeyIfRequired(selectedKey));
+
+ // load payLoad
+ return new JwsResult(
+ jws.verifySignature(),
+ jws.getUnverifiedPayload(),
+ jws.getHeaders(),
+ x5cCerts);
+
+ }
+
+
+ /**
+ * 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.
+ *
+ * @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/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 43c44647..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
@@ -14,15 +14,14 @@ import javax.annotation.Nonnull;
import javax.annotation.PostConstruct;
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;
import org.jose4j.jwe.JsonWebEncryption;
import org.jose4j.jws.AlgorithmIdentifiers;
-import org.jose4j.jws.JsonWebSignature;
-import org.jose4j.jwx.JsonWebStructure;
+import org.jose4j.jwx.HeaderParameterNames;
import org.jose4j.keys.X509Util;
-import org.jose4j.keys.resolvers.X509VerificationKeyResolver;
import org.jose4j.lang.JoseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -37,6 +36,7 @@ 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;
@@ -49,6 +49,7 @@ 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 {
@@ -125,40 +126,16 @@ public class JsonSecurityUtils implements IJoseTools {
@Override
public String createSignature(final String payLoad, boolean addFullCertChain) throws SlCommandoBuildException {
try {
- final JsonWebSignature jws = new JsonWebSignature();
-
- // set payload
- jws.setPayload(payLoad);
-
- // set basic header
- jws.setContentTypeHeaderValue(SL20Constants.SL20_CONTENTTYPE_SIGNED_COMMAND);
-
- // set signing information
- jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
- final Pair<Key, X509Certificate[]> signingCred = EaafKeyStoreUtils.getPrivateKeyAndCertificates(
- keyStore.getFirst(), getSigningKeyAlias(), getSigningKeyPassword(), true, FRIENDLYNAME_KEYSTORE);
- jws.setKey(signingCred.getFirst());
-
- // 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();
+ return JoseUtils.createSignature(keyStore, getSigningKeyAlias(), getSigningKeyPassword(),
+ payLoad, addFullCertChain,
+ Collections.singletonMap(
+ HeaderParameterNames.CONTENT_TYPE,
+ SL20Constants.SL20_CONTENTTYPE_SIGNED_COMMAND),
+ getRsaSigningAlgorithm(),
+ getEccSigningAlgorithm(),
+ FRIENDLYNAME_KEYSTORE);
- } catch (final JoseException | EaafKeyAccessException e) {
+ } catch (final JoseException | EaafException e) {
log.warn("Can NOT sign SL2.0 command.", e);
throw new SlCommandoBuildException("Can NOT sign SL2.0 command.", e);
@@ -179,61 +156,12 @@ public class JsonSecurityUtils implements IJoseTools {
public VerificationResult 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.");
- try {
- log.debug("Cert: " + Base64Utils.encodeToString(sortedX5cCerts.get(0).getEncoded()));
-
- } catch (final CertificateEncodingException e) {
- e.printStackTrace();
- }
-
- }
-
- } 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
+ final JwsResult result = JoseUtils.validateSignature(serializedContent, trustedCerts, constraints);
return new VerificationResult(
- mapper.getMapper().readTree(jws.getHeaders().getFullHeaderAsJsonString()),
- mapper.getMapper().readTree(jws.getPayload()),
- x5cCerts, jws.verifySignature());
+ mapper.getMapper().readTree(result.getFullJoseHeader().getFullHeaderAsJsonString()),
+ mapper.getMapper().readTree(result.getPayLoad()),
+ result.getX5cCerts(), result.isValid());
}
@@ -241,7 +169,7 @@ public class JsonSecurityUtils implements IJoseTools {
@Nonnull
public VerificationResult validateSignature(@Nonnull final String serializedContent) throws SL20Exception {
try {
- final AlgorithmConstraints algConstraints = new AlgorithmConstraints(ConstraintType.WHITELIST,
+ final AlgorithmConstraints algConstraints = new AlgorithmConstraints(ConstraintType.PERMIT,
SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING
.toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING.size()]));
@@ -251,7 +179,7 @@ public class JsonSecurityUtils implements IJoseTools {
if (!result.isValidSigned()) {
log.info("JWS signature invalide. Stopping authentication process ...");
- log.debug("Received JWS msg: " + serializedContent);
+ log.debug("Received JWS msg: {}", serializedContent);
throw new SL20SecurityException("JWS signature invalide.");
}
@@ -278,11 +206,11 @@ public class JsonSecurityUtils implements IJoseTools {
// set security constrains
receiverJwe.setAlgorithmConstraints(
- new AlgorithmConstraints(ConstraintType.WHITELIST,
+ new AlgorithmConstraints(ConstraintType.PERMIT,
SL20Constants.SL20_ALGORITHM_WHITELIST_KEYENCRYPTION
.toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_KEYENCRYPTION.size()])));
receiverJwe.setContentEncryptionAlgorithmConstraints(
- new AlgorithmConstraints(ConstraintType.WHITELIST, SL20Constants.SL20_ALGORITHM_WHITELIST_ENCRYPTION
+ new AlgorithmConstraints(ConstraintType.PERMIT, SL20Constants.SL20_ALGORITHM_WHITELIST_ENCRYPTION
.toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_ENCRYPTION.size()])));
// set payload
@@ -292,6 +220,21 @@ public class JsonSecurityUtils implements IJoseTools {
keyStore.getFirst(), getEncryptionKeyAlias(), getEncryptionKeyPassword(), true,
FRIENDLYNAME_KEYSTORE);
+ // 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().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
final List<X509Certificate> x5cCerts = receiverJwe.getCertificateChainHeaderValue();
final String x5t256 = receiverJwe.getX509CertSha256ThumbprintHeaderValue();
@@ -318,7 +261,7 @@ public class JsonSecurityUtils implements IJoseTools {
final String certFingerPrint = X509Util.x5tS256(encryptionCred.getSecond()[0]);
if (!certFingerPrint.equals(x5t256)) {
log.info("X5t256 from JOSE header does NOT match encryption certificate");
- log.debug("X5t256 from JOSE header: " + x5t256 + " Encrytption cert: " + certFingerPrint);
+ log.debug("X5t256 from JOSE header: {} Encrytption cert: {}", x5t256, certFingerPrint);
throw new SL20Exception("sl20.05",
new Object[] { "X5t256 from JOSE header does NOT match encryption certificate" });
@@ -332,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());
@@ -377,8 +320,7 @@ public class JsonSecurityUtils implements IJoseTools {
config.setFriendlyName(FRIENDLYNAME_KEYSTORE);
config.setKeyStoreType(authConfig.getBasicConfiguration(
- authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_TYPE),
- KeyStoreType.JKS.getKeyStoreType()));
+ Constants.CONFIG_PROP_SECURITY_KEYSTORE_TYPE, KeyStoreType.JKS.getKeyStoreType()));
config.setKeyStoreName(
authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_NAME));
config.setSoftKeyStoreFilePath(
@@ -398,8 +340,7 @@ public class JsonSecurityUtils implements IJoseTools {
config.setFriendlyName(FRIENDLYNAME_TRUSTSTORE);
config.setKeyStoreType(authConfig.getBasicConfiguration(
- authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_TRUSTSTORE_TYPE),
- KeyStoreType.JKS.getKeyStoreType()));
+ Constants.CONFIG_PROP_SECURITY_TRUSTSTORE_TYPE, KeyStoreType.JKS.getKeyStoreType()));
config.setKeyStoreName(
authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_TRUSTSTORE_NAME));
config.setSoftKeyStoreFilePath(
@@ -452,4 +393,26 @@ public class JsonSecurityUtils implements IJoseTools {
return null;
}
+ private String getRsaSigningAlgorithm() {
+ String value = authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_SIG_ALG_RSA,
+ AlgorithmIdentifiers.RSA_PSS_USING_SHA256);
+ if (value != null) {
+ value = value.trim();
+ }
+
+ return value;
+
+ }
+
+ private String getEccSigningAlgorithm() {
+ String value = authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_SIG_ALG_ECC,
+ AlgorithmIdentifiers.ECDSA_USING_P256_CURVE_AND_SHA256);
+ if (value != null) {
+ value = value.trim();
+ }
+
+ return value;
+
+ }
+
}
diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20Constants.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20Constants.java
index edf70cc8..c95bcc45 100644
--- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20Constants.java
+++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20Constants.java
@@ -13,14 +13,15 @@ import org.jose4j.jws.AlgorithmIdentifiers;
public class SL20Constants {
public static final int CURRENT_SL20_VERSION = 10;
-
+
// http binding parameters
public static final String PARAM_SL20_REQ_COMMAND_PARAM = "slcommand";
public static final String PARAM_SL20_REQ_COMMAND_PARAM_OLD = "sl2command";
public static final String PARAM_SL20_REQ_AUTH_METHOD_PARAM = "authtype";
public static final String PARAM_SL20_REQ_AUTH_VDA_SESSIONID = "session";
-
+ public static final String PARAM_SL20_REQ_AUTH_VDA_LOCALE = "locale";
+
public enum VdaAuthMethod {
ANY("any"), MOBILEPHONE("handy"), CARD("card"), SMARTPHONE("smartphone");
@@ -51,7 +52,7 @@ public class SL20Constants {
} catch (IllegalArgumentException | NullPointerException e) {
return VdaAuthMethod.ANY;
-
+
}
}
@@ -59,9 +60,9 @@ public class SL20Constants {
public String toString() {
return getAuthMethod();
- }
+ }
}
-
+
public static final String PARAM_SL20_REQ_ICP_RETURN_URL_PARAM = "slIPCReturnUrl";
public static final String PARAM_SL20_REQ_TRANSACTIONID = "slTransactionID";
@@ -97,7 +98,11 @@ public class SL20Constants {
KeyManagementAlgorithmIdentifiers.RSA_OAEP_256;
public static final List<String> SL20_ALGORITHM_WHITELIST_KEYENCRYPTION = Collections
- .unmodifiableList(Arrays.asList(JSON_ALGORITHM_ENC_KEY_RSAOAEP, JSON_ALGORITHM_ENC_KEY_RSAOAEP256));
+ .unmodifiableList(Arrays.asList(
+ JSON_ALGORITHM_ENC_KEY_RSAOAEP,
+ JSON_ALGORITHM_ENC_KEY_RSAOAEP256,
+ KeyManagementAlgorithmIdentifiers.ECDH_ES_A128KW,
+ KeyManagementAlgorithmIdentifiers.ECDH_ES_A256KW));
public static final String JSON_ALGORITHM_ENC_PAYLOAD_A128CBCHS256 =
ContentEncryptionAlgorithmIdentifiers.AES_128_CBC_HMAC_SHA_256;
@@ -177,7 +182,7 @@ public class SL20Constants {
// error command
public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE = "errorCode";
public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE = "errorMessage";
- public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERROR_VDASESSIONID
+ public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERROR_VDASESSIONID
= "handySignaturSession";
// qualified eID command
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..2b6ddb96 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,133 @@ 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.entity.ContentType;
+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");
+
+ }
+
+ final ContentType contentType = ContentType.getOrDefault(response.getEntity());
+ if (!ContentType.APPLICATION_JSON.getMimeType().equals(contentType.getMimeType())) {
+ log.error("SL20 response with statuscode: {} has wrong http ContentType: {}",
+ response.getStatusLine(), contentType);
+ throw new SlCommandoParserException(
+ "SL20 response with a wrong http ContentType: " + contentType);
+
+ }
+
+ //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 +169,34 @@ 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);
+ try {
+ final JsonNode sl20Resp = mapper.getMapper().readTree(rawSL20Resp);
+ if (sl20Resp != null) {
+ return sl20Resp;
+
+ } else {
+ log.error("SL2.0 can NOT parse to a JSON object from msg: {}", rawSL20Resp);
+ throw new SlCommandoParserException("SL2.0 can NOT parse to a JSON object");
+ }
+
+ } catch (SlCommandoParserException e) {
+ throw e;
+
+ } catch (Exception e) {
+ log.error("SL2.0 can NOT parse to a JSON object from msg: {}", rawSL20Resp);
+ throw new SlCommandoParserException("SL2.0 can NOT parse to a JSON object");
+
+ }
+
+ } else {
+ throw new SlCommandoParserException("Can NOT find any 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/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20ResponseUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20ResponseUtils.java
index 4bb91634..c3826087 100644
--- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20ResponseUtils.java
+++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20ResponseUtils.java
@@ -11,17 +11,17 @@ import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import at.gv.egiz.eaaf.core.api.IRequest;
-import at.gv.egiz.eaaf.core.api.data.EaafConstants;
-import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
-import at.gv.egiz.eaaf.modules.auth.sl20.Constants;
-import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception;
-
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.modules.auth.sl20.Constants;
+import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@@ -134,7 +134,7 @@ public class SL20ResponseUtils {
} else {
log.info("SL2.0 DataURL communication needs http header: '" + SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE + "'");
- log.debug("Client request containts is no native client ... ");
+ log.debug("Client request is no a native client. SL2.0 anwser will be a http redirect ... ");
final URIBuilder clientRedirectUri = new URIBuilder(fullRedirectUrl);
response.setStatus(Integer.parseInt(authConfig.getBasicConfiguration(Constants.CONFIG_PROP_HTTP_REDIRECT_CODE,
Constants.CONFIG_PROP_HTTP_REDIRECT_CODE_DEFAULT_VALUE)));