summaryrefslogtreecommitdiff
path: root/eaaf_modules
diff options
context:
space:
mode:
authorThomas Lenz <thomas.lenz@egiz.gv.at>2020-02-05 15:31:09 +0100
committerThomas Lenz <thomas.lenz@egiz.gv.at>2020-02-05 15:31:09 +0100
commit8ebf6c4b08a008a96b4ac60167c26b48c30e97ce (patch)
tree0b55e8e57dcdfdb99a2bc72eab07a9429fc64af6 /eaaf_modules
parent882789ecf04615abf8d5c80e3a0695d1cfc76fa0 (diff)
downloadEAAF-Components-8ebf6c4b08a008a96b4ac60167c26b48c30e97ce.tar.gz
EAAF-Components-8ebf6c4b08a008a96b4ac60167c26b48c30e97ce.tar.bz2
EAAF-Components-8ebf6c4b08a008a96b4ac60167c26b48c30e97ce.zip
refactor generic error-handling to solve possible invalid error-response in SL2.0
Diffstat (limited to 'eaaf_modules')
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualEidTask.java141
-rw-r--r--eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20ResponseUtils.java166
2 files changed, 183 insertions, 124 deletions
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 87dd6263..655cc2c6 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
@@ -1,28 +1,11 @@
package at.gv.egiz.eaaf.modules.auth.sl20.tasks;
import java.io.IOException;
-import java.io.StringWriter;
-import java.net.URISyntaxException;
-import java.util.HashMap;
import java.util.Map;
-import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.http.client.utils.URIBuilder;
-import org.apache.http.entity.ContentType;
-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 com.fasterxml.jackson.databind.node.ObjectNode;
-
-import at.gv.egiz.eaaf.core.api.data.EaafConstants;
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;
@@ -40,14 +23,21 @@ import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoParserException;
import at.gv.egiz.eaaf.modules.auth.sl20.utils.IJoseTools;
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.SL20JsonBuilderUtils;
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);
- private static final String PATTERN_PENDING_REQ_ID = "#PENDINGREQID#";
-
@Autowired(required = true)
private IJoseTools joseTools;
@@ -177,10 +167,14 @@ public abstract class AbstractReceiveQualEidTask extends AbstractAuthServletTask
// write SL2.0 response
if (sl20ReqObj != null) {
- // buildResponse(request, response, sl20ReqObj, aTrustErrorWorkAround);
- buildResponse(request, response, sl20ReqObj);
+ final String resumeEndpoint = new DataUrlBuilder().buildDataUrl(pendingReq.getAuthUrl(),
+ getResumeEndPoint(), pendingReq.getPendingRequestId());
+ SL20ResponseUtils.buildResponse(request, response, pendingReq, resumeEndpoint,
+ SL20JsonExtractorUtils.getStringValue(sl20ReqObj, SL20Constants.SL20_TRANSACTIONID, false),
+ authConfig);
+
} else {
- buildErrorResponse(response, "2000", "General transport Binding error");
+ SL20ResponseUtils.buildErrorResponse(response, "2000", "General transport Binding error");
}
}
@@ -213,106 +207,5 @@ public abstract class AbstractReceiveQualEidTask extends AbstractAuthServletTask
protected abstract String getResumeEndPoint();
- private void buildErrorResponse(final HttpServletResponse response, final String errorCode, final String errorMsg)
- throws Exception {
- final ObjectNode error = SL20JsonBuilderUtils.createErrorCommandResult(errorCode, errorMsg);
- final ObjectNode errorCommand = SL20JsonBuilderUtils
- .createCommandResponse(SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR, error, null);
-
- final ObjectNode respContainer = SL20JsonBuilderUtils.createGenericResponse(UUID.randomUUID().toString(), null,
- null, errorCommand, null);
-
- log.trace("SL20 response to VDA: " + respContainer);
- final StringWriter writer = new StringWriter();
- writer.write(respContainer.toString());
- final byte[] content = writer.toString().getBytes("UTF-8");
- response.setStatus(HttpServletResponse.SC_OK);
- response.setContentLength(content.length);
- response.setContentType(ContentType.APPLICATION_JSON.toString());
- response.getOutputStream().write(content);
-
- }
-
- private void buildResponse(final HttpServletRequest request, final HttpServletResponse response,
- final JsonNode sl20ReqObj) throws IOException, SL20Exception, URISyntaxException {
- // create response
- final Map<String, String> reqParameters = new HashMap<>();
- reqParameters.put(EaafConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID, pendingReq.getPendingRequestId());
- final ObjectNode callReqParams = SL20JsonBuilderUtils.createCallCommandParameters(
- new DataUrlBuilder().buildDataUrl(pendingReq.getAuthUrl(), getResumeEndPoint(), null),
- SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_METHOD_GET, false, reqParameters);
- final ObjectNode callCommand = SL20JsonBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_CALL,
- callReqParams);
-
- // build first redirect command for app
- final ObjectNode redirectOneParams = SL20JsonBuilderUtils
- .createRedirectCommandParameters(generateIpcRedirectUrlForDebugging(), callCommand, null, true);
- final ObjectNode redirectOneCommand = SL20JsonBuilderUtils
- .createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT, redirectOneParams);
-
- // build second redirect command for IDP
- final ObjectNode redirectTwoParams = SL20JsonBuilderUtils.createRedirectCommandParameters(new DataUrlBuilder()
- .buildDataUrl(pendingReq.getAuthUrl(), getResumeEndPoint(), pendingReq.getPendingRequestId()),
- redirectOneCommand, null, false);
- final ObjectNode redirectTwoCommand = SL20JsonBuilderUtils
- .createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT, redirectTwoParams);
-
- // build generic SL2.0 response container
- final String transactionId = SL20JsonExtractorUtils.getStringValue(sl20ReqObj, SL20Constants.SL20_TRANSACTIONID,
- false);
- final ObjectNode respContainer = SL20JsonBuilderUtils.createGenericRequest(UUID.randomUUID().toString(),
- transactionId, redirectTwoCommand, null);
-
- if (request.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE) != null && request
- .getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE).equals(SL20Constants.HTTP_HEADER_VALUE_NATIVE)) {
- log.debug("Client request containts 'native client' header ... ");
- log.trace("SL20 response to VDA: " + respContainer);
- final StringWriter writer = new StringWriter();
- writer.write(respContainer.toString());
- final byte[] content = writer.toString().getBytes("UTF-8");
- response.setStatus(HttpServletResponse.SC_OK);
- response.setContentLength(content.length);
- response.setContentType(ContentType.APPLICATION_JSON.toString());
- response.getOutputStream().write(content);
-
- } 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 ... ");
- final URIBuilder clientRedirectUri = new URIBuilder(new DataUrlBuilder().buildDataUrl(pendingReq.getAuthUrl(),
- getResumeEndPoint(), pendingReq.getPendingRequestId()));
- response.setStatus(Integer.parseInt(authConfig.getBasicConfiguration(Constants.CONFIG_PROP_HTTP_REDIRECT_CODE,
- Constants.CONFIG_PROP_HTTP_REDIRECT_CODE_DEFAULT_VALUE)));
- response.setHeader("Location", clientRedirectUri.build().toString());
-
- // throw new SL20Exception("sl20.06",
- // new Object[] {"SL2.0 DataURL communication needs http header: '" +
- // SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE + "'"});
-
- }
- }
-
- /**
- * Generates a IPC redirect URL that is configured on IDP side.
- *
- * @return IPC ReturnURL, or null if no URL is configured
- */
- private String generateIpcRedirectUrlForDebugging() {
-
- String ipcRedirectUrlConfig = authConfig.getBasicConfiguration(Constants.CONFIG_PROP_IPC_RETURN_URL);
- if (StringUtils.isNotEmpty(ipcRedirectUrlConfig)) {
- if (ipcRedirectUrlConfig.contains(PATTERN_PENDING_REQ_ID)) {
- log.trace("Find 'pendingReqId' pattern in IPC redirect URL. Update url ... ");
- ipcRedirectUrlConfig = ipcRedirectUrlConfig.replaceAll("#PENDINGREQID#",
- EaafConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID + "=" + pendingReq.getPendingRequestId());
-
- }
-
- return ipcRedirectUrlConfig;
- }
-
- return null;
-
- }
}
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
new file mode 100644
index 00000000..4bb91634
--- /dev/null
+++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20ResponseUtils.java
@@ -0,0 +1,166 @@
+package at.gv.egiz.eaaf.modules.auth.sl20.utils;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+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 lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class SL20ResponseUtils {
+ private static final String PATTERN_PENDING_REQ_ID = "#PENDINGREQID#";
+
+ /**
+ * Build a generic SL2.x error-response without redirect to AuthHandler.
+ *
+ * @param response http response object
+ * @param errorCode ErrorCode
+ * @param errorMsg Error message
+ * @throws Exception In case of a message generation error
+ */
+ public static void buildErrorResponse(final HttpServletResponse response,
+ final String errorCode, final String errorMsg)
+ throws Exception {
+ final ObjectNode error = SL20JsonBuilderUtils.createErrorCommandResult(errorCode, errorMsg);
+ final ObjectNode errorCommand = SL20JsonBuilderUtils
+ .createCommandResponse(SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR, error, null);
+
+ final ObjectNode respContainer = SL20JsonBuilderUtils.createGenericResponse(UUID.randomUUID().toString(), null,
+ null, errorCommand, null);
+
+ log.trace("SL20 response to VDA: " + respContainer);
+ final StringWriter writer = new StringWriter();
+ writer.write(respContainer.toString());
+ final byte[] content = writer.toString().getBytes("UTF-8");
+ response.setStatus(HttpServletResponse.SC_OK);
+ response.setContentLength(content.length);
+ response.setContentType(ContentType.APPLICATION_JSON.toString());
+ response.getOutputStream().write(content);
+
+ }
+
+ /**
+ * Build a Security-Layer 2.x conform redirect response.
+ *
+ * @param request http request
+ * @param response http response
+ * @param pendingReq Current pending request
+ * @param fullRedirectUrl Endpoint, where the auth. process should be resumed after redirect
+ * @param transactionId SL2.0 transactionId if available
+ * @param authConfig Basic application configuration
+ * @throws IOException In case of a http servlet error
+ * @throws SL20Exception In case of a SL2.0 request generation error
+ * @throws URISyntaxException In case of an invalid Redirect URL
+ */
+ public static void buildResponse(final HttpServletRequest request, final HttpServletResponse response,
+ IRequest pendingReq, String fullRedirectUrl, String transactionId, IConfiguration authConfig)
+ throws IOException, SL20Exception, URISyntaxException {
+ // create response
+ final Map<String, String> reqParameters = new HashMap<>();
+
+ final URL redirectUrl = new URL(fullRedirectUrl);
+ if (redirectUrl.getQuery() != null) {
+ final String [] elements = redirectUrl.getQuery().split("&");
+ for (final String element : elements) {
+ final String[] keyValue = element.split("=");
+ if (keyValue.length == 2) {
+ reqParameters.put(keyValue[0], keyValue[1]);
+
+ } else {
+ log.warn("Ignore parameter with name: {}", keyValue[0]);
+
+ }
+ }
+ }
+
+ //reqParameters.put(EaafConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID, pendingReq.getPendingRequestId());
+
+ final ObjectNode callReqParams = SL20JsonBuilderUtils.createCallCommandParameters(
+ fullRedirectUrl.split("\\?")[0],
+ SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_METHOD_GET, false, reqParameters);
+ final ObjectNode callCommand = SL20JsonBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_CALL,
+ callReqParams);
+
+ // build first redirect command for app
+ final ObjectNode redirectOneParams = SL20JsonBuilderUtils
+ .createRedirectCommandParameters(generateIpcRedirectUrlForDebugging(
+ pendingReq,
+ authConfig.getBasicConfiguration(Constants.CONFIG_PROP_IPC_RETURN_URL)),
+ callCommand, null, true);
+ final ObjectNode redirectOneCommand = SL20JsonBuilderUtils
+ .createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT, redirectOneParams);
+
+ // build second redirect command for IDP
+ final ObjectNode redirectTwoParams = SL20JsonBuilderUtils.createRedirectCommandParameters(
+ fullRedirectUrl,
+ redirectOneCommand, null, false);
+ final ObjectNode redirectTwoCommand = SL20JsonBuilderUtils
+ .createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT, redirectTwoParams);
+
+ // build generic SL2.0 response container
+ final ObjectNode respContainer = SL20JsonBuilderUtils.createGenericRequest(UUID.randomUUID().toString(),
+ transactionId, redirectTwoCommand, null);
+
+ if (request.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE) != null && request
+ .getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE).equals(SL20Constants.HTTP_HEADER_VALUE_NATIVE)) {
+ log.debug("Client request containts 'native client' header ... ");
+ log.trace("SL20 response to VDA: " + respContainer);
+ final StringWriter writer = new StringWriter();
+ writer.write(respContainer.toString());
+ final byte[] content = writer.toString().getBytes("UTF-8");
+ response.setStatus(HttpServletResponse.SC_OK);
+ response.setContentLength(content.length);
+ response.setContentType(ContentType.APPLICATION_JSON.toString());
+ response.getOutputStream().write(content);
+
+ } 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 ... ");
+ 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)));
+ response.setHeader("Location", clientRedirectUri.build().toString());
+
+ }
+ }
+
+ /**
+ * Generates a IPC redirect URL that is configured on IDP side.
+ *
+ * @return IPC ReturnURL, or null if no URL is configured
+ */
+ private static String generateIpcRedirectUrlForDebugging(IRequest pendingReq, String ipcRedirectUrlConfig) {
+ if (StringUtils.isNotEmpty(ipcRedirectUrlConfig)) {
+ if (ipcRedirectUrlConfig.contains(PATTERN_PENDING_REQ_ID)) {
+ log.trace("Find 'pendingReqId' pattern in IPC redirect URL. Update url ... ");
+ ipcRedirectUrlConfig = ipcRedirectUrlConfig.replaceAll("#PENDINGREQID#",
+ EaafConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID + "=" + pendingReq.getPendingRequestId());
+
+ }
+
+ return ipcRedirectUrlConfig;
+ }
+
+ return null;
+
+ }
+}