From a19b85723223dbefff7f34a59421c2d2edf3261f Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Wed, 1 Apr 2020 23:17:27 +0200 Subject: update process-engine support HTTP POST and GET error forwarting. This is needed for processes in IFrames --- .../services/ProtocolAuthenticationService.java | 43 ++++++++++++++++++++++ .../impl/idp/controller/AbstractController.java | 37 +++++-------------- .../controller/ProtocolFinalizationController.java | 2 +- .../impl/idp/controller/protocols/RequestImpl.java | 27 ++++++++++---- .../gui/DummyGuiBuilderConfigurationFactory.java | 14 ++++++- .../idp/module/test/DummyProtocolAuthService.java | 18 +++++++++ .../core/impl/idp/module/test/TestRequestImpl.java | 18 +++++++-- .../java/at/gv/egiz/eaaf/core/api/IRequest.java | 19 ++++++++++ .../api/gui/IGuiBuilderConfigurationFactory.java | 13 +++++++ .../services/IProtocolAuthenticationService.java | 16 ++++++++ 10 files changed, 167 insertions(+), 40 deletions(-) diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/ProtocolAuthenticationService.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/ProtocolAuthenticationService.java index 4c82adac..5f84d118 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/ProtocolAuthenticationService.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/ProtocolAuthenticationService.java @@ -69,9 +69,12 @@ import at.gv.egiz.eaaf.core.exceptions.GuiBuildException; import at.gv.egiz.eaaf.core.exceptions.InvalidProtocolRequestException; import at.gv.egiz.eaaf.core.exceptions.ProcessExecutionException; import at.gv.egiz.eaaf.core.exceptions.ProtocolNotActiveException; +import at.gv.egiz.eaaf.core.impl.data.Pair; import at.gv.egiz.eaaf.core.impl.gui.AbstractGuiFormBuilderConfiguration; import at.gv.egiz.eaaf.core.impl.http.HttpUtils; +import at.gv.egiz.eaaf.core.impl.idp.controller.ProtocolFinalizationController; import at.gv.egiz.eaaf.core.impl.idp.controller.protocols.RequestImpl; +import at.gv.egiz.eaaf.core.impl.utils.ServletUtils; @Service public class ProtocolAuthenticationService implements IProtocolAuthenticationService { @@ -289,6 +292,46 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer } + @Override + public void forwardToErrorHandler(Pair errorToHandle, String errorKey, + final HttpServletRequest req, final HttpServletResponse resp) throws GuiBuildException { + IGuiBuilderConfiguration parentHopGuiConfig = + evaluateRequiredErrorHandlingMethod(errorToHandle.getFirst(), errorKey); + if (parentHopGuiConfig != null) { + log.trace("iFrame to parent hop requested. Building GUI step for error handling ... "); + guiBuilder.build(req, resp, parentHopGuiConfig, "iFrame-to-parent"); + + } else { + // build up redirect URL + final String redirectUrl = generateErrorRedirectUrl(req, errorKey); + resp.setContentType("text/html"); + resp.setStatus(302); + resp.addHeader("Location", redirectUrl); + log.debug("REDIRECT TO: " + redirectUrl); + + } + } + + private IGuiBuilderConfiguration evaluateRequiredErrorHandlingMethod(IRequest first, String errorId) { + if (first != null && first.isProcessInIframe()) { + return guiConfigFactory.getDefaultIFrameParentHopGui(first, + "/" + ProtocolFinalizationController.ENDPOINT_ERRORHANDLING, + errorId); + + } + + return null; + } + + private String generateErrorRedirectUrl(final HttpServletRequest req, String errorKey) { + String redirectUrl = null; + redirectUrl = ServletUtils.getBaseUrl(req); + redirectUrl += "/" + ProtocolFinalizationController.ENDPOINT_ERRORHANDLING + "?" + + EaafConstants.PARAM_HTTP_ERROR_CODE + "=" + errorKey; + return redirectUrl; + + } + public void setGuiBuilder(final IGuiFormBuilder guiBuilder) { this.guiBuilder = guiBuilder; } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractController.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractController.java index dd113907..fc62af45 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractController.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractController.java @@ -26,6 +26,13 @@ import javax.annotation.Nullable; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.commons.text.StringEscapeUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.web.bind.annotation.ExceptionHandler; + import at.gv.egiz.components.eventlog.api.EventConstants; import at.gv.egiz.eaaf.core.api.IRequest; import at.gv.egiz.eaaf.core.api.IStatusMessenger; @@ -41,14 +48,6 @@ import at.gv.egiz.eaaf.core.exceptions.ProcessExecutionException; import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; import at.gv.egiz.eaaf.core.impl.data.Pair; import at.gv.egiz.eaaf.core.impl.utils.Random; -import at.gv.egiz.eaaf.core.impl.utils.ServletUtils; - -import org.apache.commons.text.StringEscapeUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.web.bind.annotation.ExceptionHandler; /** * Basic application controller that implements core error-handling. @@ -70,7 +69,7 @@ public abstract class AbstractController { protected ITransactionStorage transactionStorage; @Autowired(required = true) protected IStatusMessenger statusMessager; - + @Autowired protected IRevisionLogger revisionsLogger; @@ -150,15 +149,8 @@ public abstract class AbstractController { try { final String errorKey = storeErrorAndGetErrorToken(errorToHandle); - - // build up redirect URL - final String redirectUrl = generateErrorRedirectUrl(req, errorKey); - resp.setContentType("text/html"); - resp.setStatus(302); - - resp.addHeader("Location", redirectUrl); - log.debug("REDIRECT TO: " + redirectUrl); - + protAuthService.forwardToErrorHandler(errorToHandle, errorKey, req, resp); + return; } catch (final Exception e) { @@ -170,15 +162,6 @@ public abstract class AbstractController { } - protected String generateErrorRedirectUrl(final HttpServletRequest req, String errorKey) { - String redirectUrl = null; - redirectUrl = ServletUtils.getBaseUrl(req); - redirectUrl += "/" + ProtocolFinalizationController.ENDPOINT_ERRORHANDLING + "?" - + EaafConstants.PARAM_HTTP_ERROR_CODE + "=" + errorKey; - return redirectUrl; - - } - protected String storeErrorAndGetErrorToken(Pair errorToHandle) throws EaafException { // log error directly in debug mode if (log.isDebugEnabled()) { diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/ProtocolFinalizationController.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/ProtocolFinalizationController.java index 51a8aefd..17da63f5 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/ProtocolFinalizationController.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/ProtocolFinalizationController.java @@ -63,7 +63,7 @@ public class ProtocolFinalizationController extends AbstractController { * @throws EaafException In case of an internal error * @throws IOException In case of a servlet error */ - @RequestMapping(value = ENDPOINT_ERRORHANDLING, method = { RequestMethod.GET }) + @RequestMapping(value = ENDPOINT_ERRORHANDLING, method = { RequestMethod.GET, RequestMethod.POST }) public void errorHandling(final HttpServletRequest req, final HttpServletResponse resp) throws EaafException, IOException { // receive an authentication error diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/protocols/RequestImpl.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/protocols/RequestImpl.java index f4494106..df13fda9 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/protocols/RequestImpl.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/protocols/RequestImpl.java @@ -32,6 +32,13 @@ import java.util.UUID; import javax.annotation.Nonnull; import javax.servlet.http.HttpServletRequest; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; + 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; @@ -44,13 +51,6 @@ import at.gv.egiz.eaaf.core.impl.http.HttpUtils; import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper; import at.gv.egiz.eaaf.core.impl.utils.TransactionIdUtils; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.lang.NonNull; -import org.springframework.lang.Nullable; -import org.springframework.util.Assert; - public abstract class RequestImpl implements IRequest, Serializable { private static final Logger log = LoggerFactory.getLogger(RequestImpl.class); @@ -92,6 +92,8 @@ public abstract class RequestImpl implements IRequest, Serializable { private boolean needUserConsent = false; + private boolean currentlyInIframe = false; + private final Map genericDataStorage = new HashMap<>(); /** @@ -456,6 +458,17 @@ public abstract class RequestImpl implements IRequest, Serializable { } + @Override + public boolean isProcessInIframe() { + return this.currentlyInIframe; + } + + @Override + public void setProcessInFrame(boolean flag) { + this.currentlyInIframe = flag; + + } + @Override public final Object getRawData(final String key) { if (StringUtils.isNotEmpty(key)) { diff --git a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/module/gui/DummyGuiBuilderConfigurationFactory.java b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/module/gui/DummyGuiBuilderConfigurationFactory.java index be71a29c..570c3dd2 100644 --- a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/module/gui/DummyGuiBuilderConfigurationFactory.java +++ b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/module/gui/DummyGuiBuilderConfigurationFactory.java @@ -11,13 +11,20 @@ import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiBuilderConfiguration; public class DummyGuiBuilderConfigurationFactory implements IGuiBuilderConfigurationFactory { private IGuiBuilderConfiguration errorGuiConfig; + private IGuiBuilderConfiguration parentHopGuiConfig; private IVelocityGuiBuilderConfiguration velocityBuilderConfig; @Override public IGuiBuilderConfiguration getDefaultErrorGui(String authUrl) { return errorGuiConfig; } - + + @Override + public IGuiBuilderConfiguration getDefaultIFrameParentHopGui(IRequest pendingReq, String endpoint, + String errorKey) { + return parentHopGuiConfig; + } + @Override public IVelocityGuiBuilderConfiguration getSpSpecificSaml2PostConfiguration(IRequest pendingReq, String viewName, URI configRootContextDir) throws MalformedURLException { @@ -28,9 +35,12 @@ public class DummyGuiBuilderConfigurationFactory implements IGuiBuilderConfigura this.errorGuiConfig = errorGuiConfig; } + public void setDefaultIFrameParentHopGui(IGuiBuilderConfiguration guiConfig) { + this.parentHopGuiConfig = guiConfig; + } + public void setVelocityBuilderConfig(IVelocityGuiBuilderConfiguration velocityBuilderConfig) { this.velocityBuilderConfig = velocityBuilderConfig; } - } diff --git a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/module/test/DummyProtocolAuthService.java b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/module/test/DummyProtocolAuthService.java index 300a390d..4b07bea9 100644 --- a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/module/test/DummyProtocolAuthService.java +++ b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/module/test/DummyProtocolAuthService.java @@ -8,6 +8,9 @@ import javax.servlet.http.HttpServletResponse; import at.gv.egiz.eaaf.core.api.IRequest; import at.gv.egiz.eaaf.core.api.idp.auth.services.IProtocolAuthenticationService; import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.exceptions.GuiBuildException; +import at.gv.egiz.eaaf.core.impl.data.Pair; +import lombok.Getter; public class DummyProtocolAuthService implements IProtocolAuthenticationService { @@ -16,6 +19,9 @@ public class DummyProtocolAuthService implements IProtocolAuthenticationService private HttpServletResponse httpResp; private Throwable exception; private boolean writeToStatisticLog; + + @Getter + private String errorKey; @Override public void performAuthentication(final HttpServletRequest req, final HttpServletResponse resp, @@ -57,6 +63,18 @@ public class DummyProtocolAuthService implements IProtocolAuthenticationService } + @Override + public void forwardToErrorHandler(Pair errorToHandle, String errorKey, + HttpServletRequest req, HttpServletResponse resp) throws GuiBuildException { + this.httpReq = req; + this.httpResp = resp; + this.pendingReq = errorToHandle.getFirst(); + this.exception = errorToHandle.getSecond(); + this.errorKey = errorKey; + + + } + public IRequest getPendingReq() { return pendingReq; } diff --git a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/module/test/TestRequestImpl.java b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/module/test/TestRequestImpl.java index 8f8f8114..b3f733d1 100644 --- a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/module/test/TestRequestImpl.java +++ b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/module/test/TestRequestImpl.java @@ -24,13 +24,13 @@ import java.lang.reflect.InvocationTargetException; import java.util.HashMap; import java.util.Map; +import org.apache.commons.lang3.StringUtils; + import at.gv.egiz.eaaf.core.api.IRequest; import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; import at.gv.egiz.eaaf.core.exceptions.EaafStorageException; import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper; -import org.apache.commons.lang3.StringUtils; - /** * Test pending-request for jUnit tests. * @@ -49,8 +49,9 @@ public class TestRequestImpl implements IRequest { private boolean authenticated; private boolean needAuthentication = false; private boolean stoppedByUser; + private boolean currentlyInIframe = false; private String piiTransactionId; - + /* * (non-Javadoc) * @@ -388,4 +389,15 @@ public class TestRequestImpl implements IRequest { this.needAuthentication = needAuthentication; } + @Override + public boolean isProcessInIframe() { + return this.currentlyInIframe; + } + + @Override + public void setProcessInFrame(boolean flag) { + this.currentlyInIframe = flag; + + } + } diff --git a/eaaf_core_api/src/main/java/at/gv/egiz/eaaf/core/api/IRequest.java b/eaaf_core_api/src/main/java/at/gv/egiz/eaaf/core/api/IRequest.java index 384446b8..05b7784e 100644 --- a/eaaf_core_api/src/main/java/at/gv/egiz/eaaf/core/api/IRequest.java +++ b/eaaf_core_api/src/main/java/at/gv/egiz/eaaf/core/api/IRequest.java @@ -263,5 +263,24 @@ public interface IRequest extends Serializable { * otherwise false */ void setAbortedByUser(boolean isAborted); + + /** + * Indicates, if the current process stage is in iFrame. + * + *

If the current state is marked as 'in iFrame', + * than the process engine will perform an target=_parent hope in case of an error

+ * + * @return true, if the process is in iFrame, otherwise false + */ + boolean isProcessInIframe(); + + /** + * Set the 'isProcessInIframe' flag to this pending-request. + * + * @param flag true, if the process is in iFrame and needs a target=_parent hope in case of an error + */ + void setProcessInFrame(boolean flag); + + } diff --git a/eaaf_core_api/src/main/java/at/gv/egiz/eaaf/core/api/gui/IGuiBuilderConfigurationFactory.java b/eaaf_core_api/src/main/java/at/gv/egiz/eaaf/core/api/gui/IGuiBuilderConfigurationFactory.java index ed888f87..618b5987 100644 --- a/eaaf_core_api/src/main/java/at/gv/egiz/eaaf/core/api/gui/IGuiBuilderConfigurationFactory.java +++ b/eaaf_core_api/src/main/java/at/gv/egiz/eaaf/core/api/gui/IGuiBuilderConfigurationFactory.java @@ -22,6 +22,8 @@ package at.gv.egiz.eaaf.core.api.gui; import java.net.MalformedURLException; import java.net.URI; +import javax.annotation.Nonnull; + import at.gv.egiz.eaaf.core.api.IRequest; public interface IGuiBuilderConfigurationFactory { @@ -34,6 +36,17 @@ public interface IGuiBuilderConfigurationFactory { */ IGuiBuilderConfiguration getDefaultErrorGui(String authUrl); + /** + * Get a default {@link IGuiBuilderConfiguration} that implements an iFrame to parent hop. + * + * @param pendingReq Current pending-request object + * @param endpoint Request end-point + * @param errorKey Error identifier + * @return GUIBuilder configuration with parent hop. + */ + IGuiBuilderConfiguration getDefaultIFrameParentHopGui(@Nonnull IRequest pendingReq, + @Nonnull String endpoint, @Nonnull String errorKey); + /** * Default Velocity based GUI builder configuration. * diff --git a/eaaf_core_api/src/main/java/at/gv/egiz/eaaf/core/api/idp/auth/services/IProtocolAuthenticationService.java b/eaaf_core_api/src/main/java/at/gv/egiz/eaaf/core/api/idp/auth/services/IProtocolAuthenticationService.java index 86d15d5b..d1d68c2d 100644 --- a/eaaf_core_api/src/main/java/at/gv/egiz/eaaf/core/api/idp/auth/services/IProtocolAuthenticationService.java +++ b/eaaf_core_api/src/main/java/at/gv/egiz/eaaf/core/api/idp/auth/services/IProtocolAuthenticationService.java @@ -27,6 +27,8 @@ import javax.servlet.http.HttpServletResponse; import at.gv.egiz.eaaf.core.api.IRequest; import at.gv.egiz.eaaf.core.api.logging.IStatisticLogger; import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.exceptions.GuiBuildException; +import at.gv.egiz.eaaf.core.impl.data.Pair; public interface IProtocolAuthenticationService { @@ -92,4 +94,18 @@ public interface IProtocolAuthenticationService { void handleErrorNoRedirect(Throwable throwable, HttpServletRequest req, HttpServletResponse resp, boolean writeExceptionToStatisticLog) throws IOException, EaafException; + /** + * Forward the process to error-handler in case of an error. + * + * @param errorToHandle Error to handle + * @param errorKey ErrorId for error-handler + * @param req HTTP response + * @param resp HTTP response + * @throws GuiBuildException In case of an GUI generation error + */ + void forwardToErrorHandler(Pair errorToHandle, String errorKey, + HttpServletRequest req, HttpServletResponse resp) throws GuiBuildException; + + + } -- cgit v1.2.3