From 4e9499a1c39498f8646799e947e38f5f491c1428 Mon Sep 17 00:00:00 2001 From: lalber Date: Mon, 8 Mar 2021 18:27:55 +0100 Subject: First version of feature --- .../impl/idp/auth/services/ErrorTicketService.java | 212 +++++++++++++++++ .../services/ProtocolAuthenticationService.java | 260 +++++++++------------ .../controller/ProtocolFinalizationController.java | 60 +++++ .../services/IProtocolAuthenticationService.java | 11 +- 4 files changed, 383 insertions(+), 160 deletions(-) create mode 100644 eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/ErrorTicketService.java diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/ErrorTicketService.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/ErrorTicketService.java new file mode 100644 index 00000000..c5bac225 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/ErrorTicketService.java @@ -0,0 +1,212 @@ +package at.gv.egiz.eaaf.core.impl.idp.auth.services; + +import at.gv.egiz.eaaf.core.api.IStatusMessenger; +import at.gv.egiz.eaaf.core.api.data.EaafConstants; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; +import at.gv.egiz.eaaf.core.impl.idp.controller.ProtocolFinalizationController; +import at.gv.egiz.eaaf.core.impl.utils.FileUtils; +import at.gv.egiz.eaaf.core.impl.utils.ServletUtils; +import lombok.Getter; +import org.apache.commons.lang3.RandomStringUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.text.StringEscapeUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; +import org.springframework.stereotype.Service; + +import javax.annotation.PostConstruct; +import javax.servlet.http.HttpServletRequest; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +@Service() +public class ErrorTicketService { + private static final Logger log = LoggerFactory.getLogger(ErrorTicketService.class); + + private static final String CONFIG_PROP_ERRORHANDLING_ACTION_PATH = "core.errorhandling.action"; + private static final String TECH_LOG_MSG = "errorCode={} Message={}"; + private static final String TICKET_LOG_MSG = "Ticket={} errorCode={} Message={}"; + + private final HashMap propertyMap = new HashMap(); + + + public enum ActionType { + TICKET_REDIRECT("ticket_redirect"), TICKET_NOREDIRECT("ticket_noredirect"), NOTICKET_REDIRECT( + "noticket_redirect"), NOTICKET_NOREDIRECT("noticket_noredirect"); + + private final String name; + + ActionType(final String text) { + this.name = text; + } + + @Override + public String toString() { + return name; + } + } + + @Autowired(required = true) + IConfiguration basicConfig; + @Autowired(required = true) + ResourceLoader resourceLoader; + + @PostConstruct + private void initialize() throws EaafException { + log.info("initErrorTicketService"); + + final String ticketConfPath = basicConfig.getBasicConfiguration(CONFIG_PROP_ERRORHANDLING_ACTION_PATH); + log.info("ticketConfPath" + ticketConfPath); + + + if (StringUtils.isEmpty(ticketConfPath)) { + log.error("Error: Path to errorhandling action configuration not known"); + throw new EaafException("Error: Path to errorhandling action configuration not known"); + } else { + + Properties getProperties = new Properties(); + try { + + final String fullFilePath = FileUtils + .makeAbsoluteUrl(ticketConfPath, basicConfig.getConfigurationRootDirectory()); + final Resource ressource = resourceLoader.getResource(fullFilePath); + final InputStream is = ressource.getInputStream(); + getProperties.load(is); + is.close(); + propertyMap.putAll((Map) getProperties); + + // log.error(propertyMap.toString()); + // log.error("working: " + propertyMap.get("auth.00")); + + } catch (Exception e) { + log.error("Error: something went wrong"); + throw new EaafException("Error: Parsing errorhandling actions failed"); + } + } + } + + public HandleData createHandleData(Throwable throwable, HttpServletRequest req) { + HandleData data = new HandleData(throwable, req); + extractErrorCode(data); + setUpErrorData(data); + + return data; + } + + private void extractErrorCode(HandleData data) { + Throwable originalException; + if (data.throwable instanceof TaskExecutionException + && ((TaskExecutionException) data.throwable).getOriginalException() != null) { + originalException = ((TaskExecutionException) data.throwable).getOriginalException(); + + } else { + originalException = data.throwable; + + } + + if (!(originalException instanceof EaafException)) { + data.errorCode = IStatusMessenger.CODES_INTERNAL_ERROR_GENERIC; + + } else { + data.errorCode = ((EaafException) originalException).getErrorId(); + + } + } + + private void setUpErrorData(HandleData data) { + + if (propertyMap.containsKey(data.errorCode)) { + String action = propertyMap.get(data.errorCode); + + if (action.equals(ActionType.TICKET_REDIRECT.toString())) { + data.actionType = ActionType.TICKET_REDIRECT; + data.generateSupportTicket(); + data.generateRedirect(); + + } else if (action.equals(ActionType.TICKET_NOREDIRECT.toString())) { + data.actionType = ActionType.TICKET_NOREDIRECT; + data.generateSupportTicket(); + + } else if (action.equals(ActionType.NOTICKET_REDIRECT.toString())) { + data.actionType = ActionType.NOTICKET_REDIRECT; + data.generateRedirect(); + + } else {// ActionType.NOTICKET_NOREDIRECT -> nothing to be done + data.actionType = ActionType.NOTICKET_NOREDIRECT; + + } + + } else { + data.generateSupportTicket(); + // TODO log with ticket gernal internal error + } + } + + public class HandleData { + private final HttpServletRequest req; + @Getter private String supportTicket; + @Getter private String redirectUrl; + @Getter private final Throwable throwable; + @Getter private String errorCode; + @Getter private ActionType actionType; + + + private HandleData(Throwable throwable, HttpServletRequest req) { + this.throwable = throwable; + this.req = req; + } + + private void generateRedirect() { + redirectUrl = ServletUtils.getBaseUrl(req); + redirectUrl += "/" + ProtocolFinalizationController.ENDPOINT_ERROR_REDIRECT + + "?" + EaafConstants.PARAM_HTTP_ERROR_CODE + "=" + + StringEscapeUtils.escapeHtml4(req.getParameter(EaafConstants.PARAM_HTTP_ERROR_CODE));; + + } + + private void generateSupportTicket() { + + String randomCode = RandomStringUtils.randomAlphanumeric(4).toUpperCase() + '-' + + RandomStringUtils.randomAlphanumeric(4).toUpperCase() + '-' + + RandomStringUtils.randomAlphanumeric(4).toUpperCase(); + supportTicket = randomCode; + } + + public void log_error() { + + if (supportTicket != null) { + log.error(TICKET_LOG_MSG, supportTicket, errorCode, throwable.getMessage(), + throwable); + } else { + log.error(TECH_LOG_MSG, errorCode, throwable.getMessage(), throwable); + } + } + + public void log_info() { + + if (supportTicket != null) { + log.info(TICKET_LOG_MSG, supportTicket, errorCode, throwable.getMessage(), throwable); + + } else { + log.info(TECH_LOG_MSG, errorCode, throwable.getMessage(), throwable); + } + } + + public void log_warn() { + + if (supportTicket != null) { + log.warn(TICKET_LOG_MSG, supportTicket, errorCode, throwable.getMessage(), throwable); + + } else { + log.warn(TECH_LOG_MSG, errorCode, throwable.getMessage(), throwable); + } + } + } +} 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 abb3d685..687a5401 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 @@ -15,7 +15,7 @@ * This product combines work with different licenses. See the "NOTICE" text file for details on the * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative * works that you distribute must include a readable copy of the "NOTICE" text file. -*/ + */ package at.gv.egiz.eaaf.core.impl.idp.auth.services; @@ -52,7 +52,6 @@ import at.gv.egiz.eaaf.core.api.idp.IAction; import at.gv.egiz.eaaf.core.api.idp.IAuthData; import at.gv.egiz.eaaf.core.api.idp.IAuthenticationDataBuilder; import at.gv.egiz.eaaf.core.api.idp.IConfiguration; -import at.gv.egiz.eaaf.core.api.idp.IModulInfo; import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; import at.gv.egiz.eaaf.core.api.idp.auth.IAuthenticationManager; import at.gv.egiz.eaaf.core.api.idp.auth.ISsoManager; @@ -69,7 +68,6 @@ 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.exceptions.TaskExecutionException; 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; @@ -82,9 +80,7 @@ import at.gv.egiz.eaaf.core.impl.utils.ServletUtils; public class ProtocolAuthenticationService implements IProtocolAuthenticationService { private static final Logger log = LoggerFactory.getLogger(ProtocolAuthenticationService.class); - private static final String CONFIG_PROP_LOGGER_ON_INFO_LEVEL = - "core.logging.level.info.errorcodes"; - private static final String TECH_LOG_MSG = "errorCode={} Message={}"; + private static final String CONFIG_PROP_LOGGER_ON_INFO_LEVEL = "core.logging.level.info.errorcodes"; @Autowired(required = true) private ApplicationContext applicationContext; @@ -100,7 +96,11 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer private IRequestStorage requestStorage; @Autowired(required = true) IPendingRequestIdGenerationStrategy pendingReqIdGenerationStrategy; - @Autowired private IConfiguration basicConfig; + @Autowired + private IConfiguration basicConfig; + + @Autowired(required = true) + private ErrorTicketService errorTicketService; @Autowired(required = false) private ISsoManager ssoManager; @@ -136,9 +136,8 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer final ISpConfiguration oaParam = pendingReq.getServiceProviderConfiguration(); if (oaParam == null) { - throw new EaafAuthenticationException( - IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_NOSPCONFIG, - new Object[] { pendingReq.getSpEntityId() }); + throw new EaafAuthenticationException(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_NOSPCONFIG, + new Object[]{pendingReq.getSpEntityId()}); } if (authmanager.doAuthentication(req, resp, pendingReq)) { @@ -148,8 +147,7 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer finalizeAuthentication(req, resp, pendingReq); // transaction is finished, log transaction finished event - revisionsLogger.logEvent(EventConstants.TRANSACTION_DESTROYED, - pendingReq.getUniqueTransactionIdentifier()); + revisionsLogger.logEvent(EventConstants.TRANSACTION_DESTROYED, pendingReq.getUniqueTransactionIdentifier()); } @@ -183,9 +181,8 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer if (pendingReq.isAbortedByUser()) { // send authentication aborted error to Service Provider buildProtocolSpecificErrorResponse( - new EaafAuthenticationException(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_USERSTOP, - new Object[] {}), - req, resp, pendingReq); + new EaafAuthenticationException(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_USERSTOP, new Object[]{}), req, + resp, pendingReq); // check if pending-request are authenticated } else if (pendingReq.isAuthenticated() && !pendingReq.isNeedUserConsent()) { @@ -193,12 +190,11 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer } else { // suspect state: pending-request is not aborted but also are not authenticated - log.warn("PendingRequest flag for 'authenticated':{} and 'needConsent':{}", - pendingReq.isAuthenticated(), pendingReq.isNeedUserConsent()); + log.warn("PendingRequest flag for 'authenticated':{} and 'needConsent':{}", pendingReq.isAuthenticated(), + pendingReq.isNeedUserConsent()); if (pendingReq.isNeedUserConsent()) { - log.error( - "PendingRequest NEEDS user-consent. " - + "Can NOT fininalize authentication --> Abort authentication process!"); + log.error("PendingRequest NEEDS user-consent. " + + "Can NOT fininalize authentication --> Abort authentication process!"); } else { log.error("PendingRequest is NOT authenticated --> Abort authentication process!"); @@ -216,44 +212,34 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer } finally { // remove pending-request requestStorage.removePendingRequest(pendingReq.getPendingRequestId()); - revisionsLogger.logEvent(EventConstants.TRANSACTION_DESTROYED, - pendingReq.getUniqueTransactionIdentifier()); + revisionsLogger.logEvent(EventConstants.TRANSACTION_DESTROYED, pendingReq.getUniqueTransactionIdentifier()); } } + @Override - public void buildProtocolSpecificErrorResponse(final Throwable throwable, - final HttpServletRequest req, final HttpServletResponse resp, final IRequest protocolRequest) - throws EaafException, IOException { + public void buildProtocolSpecificErrorResponse(final Throwable throwable, final HttpServletRequest req, + final HttpServletResponse resp, final IRequest protocolRequest) throws EaafException, IOException { try { - final Class clazz = Class.forName(protocolRequest.requestedModule()); + ErrorTicketService.HandleData errorData = errorTicketService.createHandleData(throwable, req); - if (clazz == null || !IModulInfo.class.isAssignableFrom(clazz)) { - log.error( - "Requested protocol module Class is NULL or does not implement the IModulInfo interface."); - throw new ClassCastException( - "Requested protocol module Class is NULL or does not implement the IModulInfo interface."); - } + if (errorData.getActionType().equals(ErrorTicketService.ActionType.NOTICKET_REDIRECT) || + errorData.getActionType().equals(ErrorTicketService.ActionType.TICKET_REDIRECT)) { - final IModulInfo handlingModule = (IModulInfo) applicationContext.getBean(clazz); - - if (handlingModule.generateErrorMessage(throwable, req, resp, protocolRequest)) { + displayException(req, resp, errorData); // log Error to technical log - logExceptionToTechnicalLog(throwable); + logExceptionToTechnicalLog(errorData); // log Error Message statisticLogger.logErrorOperation(throwable, protocolRequest); - // write revision log entries - revisionsLogger.logEvent(protocolRequest, EventConstants.TRANSACTION_ERROR, - protocolRequest.getUniqueTransactionIdentifier()); } else { - handleErrorNoRedirect(throwable, req, resp, true); + throw throwable; //through it on to handleErrorNoRedirect } @@ -266,8 +252,9 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer @Override public void handleErrorNoRedirect(final Throwable throwable, final HttpServletRequest req, - final HttpServletResponse resp, final boolean writeExceptionToStatisticLog) - throws IOException, EaafException { + final HttpServletResponse resp, final boolean writeExceptionToStatisticLog) throws IOException, EaafException { + + ErrorTicketService.HandleData errorData = errorTicketService.createHandleData(throwable, req); // log Exception into statistic database if (writeExceptionToStatisticLog) { @@ -275,30 +262,17 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer } // write errror to console - logExceptionToTechnicalLog(throwable); + logExceptionToTechnicalLog(errorData); // return error to Web browser - if (throwable instanceof EaafException || throwable instanceof ProcessExecutionException) { - internalMoaidExceptionHandler(req, resp, (Exception) throwable, false); - - } else { - // write generic message for general exceptions - final String msg = - statusMessager.getMessage(IStatusMessenger.CODES_INTERNAL_ERROR_GENERIC, null); - final String internalErrorCode = statusMessager.getResponseErrorCode(throwable); - - writeHtmlErrorResponse(req, resp, msg, internalErrorCode, null, - statusMessager.mapInternalErrorToExternalError(internalErrorCode)); - - } - + displayException(req, resp, errorData); } @Override public void forwardToErrorHandler(Pair errorToHandle, String errorKey, final HttpServletRequest req, final HttpServletResponse resp) throws GuiBuildException { - final IGuiBuilderConfiguration parentHopGuiConfig = - evaluateRequiredErrorHandlingMethod(errorToHandle.getFirst(), errorKey); + final 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"); @@ -321,15 +295,13 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer /** * Finalize the requested protocol operation. * - * @param httpReq HttpServletRequest - * @param httpResp HttpServletResponse - * @param protocolRequest Authentication request which is actually in process - * @param moaSession MOASession object, which is used to generate the - * protocol specific authentication information + * @param req HttpServletRequest + * @param resp HttpServletResponse + * @param pendingReq Authentication request which is actually in process * @throws Exception In case of an error */ - protected void internalFinalizeAuthenticationProcess(final HttpServletRequest req, - final HttpServletResponse resp, final IRequest pendingReq) throws Exception { + protected void internalFinalizeAuthenticationProcess(final HttpServletRequest req, final HttpServletResponse resp, + final IRequest pendingReq) throws Exception { String newSsoSessionId = null; @@ -351,8 +323,7 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer final IAuthData authData = authDataBuilder.buildAuthenticationData(pendingReq); // execute the protocol-specific action - final SloInformationInterface sloInformation = - executeProtocolSpecificAction(req, resp, pendingReq, authData); + final SloInformationInterface sloInformation = executeProtocolSpecificAction(req, resp, pendingReq, authData); // Store OA specific SSO session information if an SSO cookie is set if (StringUtils.isNotEmpty(newSsoSessionId)) { @@ -372,52 +343,42 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer } // Advanced statistic logging - statisticLogger.logSuccessOperation(pendingReq, authData, - StringUtils.isNotEmpty(newSsoSessionId)); + statisticLogger.logSuccessOperation(pendingReq, authData, StringUtils.isNotEmpty(newSsoSessionId)); } /** * Write a Exception to the MOA-ID-Auth internal technical log. * - * @param loggedException Exception to log + * @param data errordata structure */ - protected void logExceptionToTechnicalLog(final Throwable loggedException) { + protected void logExceptionToTechnicalLog(ErrorTicketService.HandleData data) { // In case of a TaskExecutionException, which is only a container for process-errors, - // extract internal exception - Throwable toLog; - if (loggedException instanceof TaskExecutionException - && ((TaskExecutionException)loggedException).getOriginalException() != null) { - toLog = ((TaskExecutionException)loggedException).getOriginalException(); - - } else { - toLog = loggedException; - - } + // extract internal exception + // Log exception - if (!(toLog instanceof EaafException)) { - log.error(TECH_LOG_MSG, IStatusMessenger.CODES_INTERNAL_ERROR_GENERIC, - toLog.getMessage(), toLog); + if (!(data.getThrowable() instanceof EaafException)) { + data.log_error(); - } else { - if (logOnInfoLevel.contains(((EaafException) toLog).getErrorId())) { - log.info(TECH_LOG_MSG, ((EaafException) toLog).getErrorId(), - toLog.getMessage(), toLog); + } else { + + if (logOnInfoLevel.contains(data.getErrorCode())) { + data.log_info(); } else { - log.warn(TECH_LOG_MSG, ((EaafException) toLog).getErrorId(), - toLog.getMessage(), toLog); + data.log_warn(); } } } + @PostConstruct private void initializer() { log.trace("Initializing {} ...", ProtocolAuthenticationService.class.getName()); - logOnInfoLevel.addAll(KeyValueUtils.getListOfCsvValues( - basicConfig.getBasicConfiguration(CONFIG_PROP_LOGGER_ON_INFO_LEVEL))); + logOnInfoLevel + .addAll(KeyValueUtils.getListOfCsvValues(basicConfig.getBasicConfiguration(CONFIG_PROP_LOGGER_ON_INFO_LEVEL))); log.info("Set errorCodes={} to LogLevel:INFO", String.join(",", logOnInfoLevel)); } @@ -425,24 +386,20 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer /** * Executes the requested protocol action. * - * @param httpReq HttpServletRequest - * @param httpResp HttpServletResponse - * @param protocolRequest Authentication request which is actually in process - * @param authData Service-provider specific authentication data - * + * @param httpReq HttpServletRequest + * @param httpResp HttpServletResponse + * @param pendingReq Authentication request which is actually in process + * @param authData Service-provider specific authentication data * @return Return Single LogOut information or null if protocol supports no SSO - * * @throws Exception in case of an error */ private SloInformationInterface executeProtocolSpecificAction(final HttpServletRequest httpReq, - final HttpServletResponse httpResp, final IRequest pendingReq, final IAuthData authData) - throws Exception { + final HttpServletResponse httpResp, final IRequest pendingReq, final IAuthData authData) throws Exception { try { // request needs no authentication --> start request processing final Class clazz = Class.forName(pendingReq.requestedAction()); if (clazz == null || !IAction.class.isAssignableFrom(clazz)) { - log.error( - "Requested protocol-action processing Class is NULL or does not implement the IAction interface."); + log.error("Requested protocol-action processing Class is NULL or does not implement the IAction interface."); throw new ClassCastException( "Requested protocol-action processing Class is NULL or does not implement the IAction interface."); @@ -452,25 +409,31 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer return protocolAction.processRequest(pendingReq, httpReq, httpResp, authData); } catch (final ClassNotFoundException e) { - log.error( - "Requested Auth. protocol processing Class is NULL or does not implement the IAction interface."); + log.error("Requested Auth. protocol processing Class is NULL or does not implement the IAction interface."); throw new ClassNotFoundException( "Requested Auth. protocol processing Class is NULL or does not implement the IAction interface.", e); } } - private void writeHtmlErrorResponse(@NonNull final HttpServletRequest httpReq, - @NonNull final HttpServletResponse httpResp, @NonNull final String msg, - @NonNull final String errorCode, @Nullable final Object[] params, String externalErrorCode) throws EaafException { + +// private void writeHtmlErrorResponse(@NonNull final HttpServletRequest httpReq, +// @NonNull final HttpServletResponse httpResp, @NonNull final String msg, @NonNull final String errorCode, +// @Nullable final Object[] params, String externalErrorCode) throws EaafException { +// this.writeHtmlErrorResponse(httpReq, httpResp, msg, errorCode, params, externalErrorCode, null, null); +// } + + public void writeHtmlErrorResponse(@NonNull final HttpServletRequest httpReq, + @NonNull final HttpServletResponse httpResp, @NonNull final String msg, @NonNull final String errorCode, + @Nullable final Object[] params, String externalErrorCode, String url, String ticket) throws EaafException { try { - final IGuiBuilderConfiguration config = - guiConfigFactory.getDefaultErrorGui(HttpUtils.extractAuthUrlFromRequest(httpReq)); + final IGuiBuilderConfiguration config = guiConfigFactory + .getDefaultErrorGui(HttpUtils.extractAuthUrlFromRequest(httpReq)); String[] errorCodeParams = null; if (params == null) { - errorCodeParams = new String[] {}; + errorCodeParams = new String[]{}; } else { errorCodeParams = new String[params.length]; for (int i = 0; i < params.length; i++) { @@ -485,20 +448,18 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer // add errorcode and errormessage if (config instanceof ModifyableGuiBuilderConfiguration) { - ((ModifyableGuiBuilderConfiguration) config).putCustomParameter( - AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG, PARAM_GUI_ERROMSG, msg); - ((ModifyableGuiBuilderConfiguration) config).putCustomParameter( - AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG, PARAM_GUI_ERRORCODE, errorCode); - ((ModifyableGuiBuilderConfiguration) config).putCustomParameter( - AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG, PARAM_GUI_EXTERNAL_ERRORCODE, - externalErrorCode); - ((ModifyableGuiBuilderConfiguration) config).putCustomParameterWithOutEscaption( - AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG, PARAM_GUI_ERRORCODEPARAMS, - ArrayUtils.toString(errorCodeParams)); + ModifyableGuiBuilderConfiguration c = ((ModifyableGuiBuilderConfiguration) config); + c.putCustomParameter(AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG, PARAM_GUI_ERROMSG, msg); + c.putCustomParameter(AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG, PARAM_GUI_ERRORCODE, errorCode); + c.putCustomParameter(AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG, PARAM_GUI_EXTERNAL_ERRORCODE, + externalErrorCode); + c.putCustomParameterWithOutEscaption(AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG, + PARAM_GUI_ERRORCODEPARAMS, ArrayUtils.toString(errorCodeParams)); + c.putCustomParameter(AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG, PARAM_GUI_TICKET, ticket); + c.putCustomParameter(AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG, PARAM_GUI_REDIRECT, url); } else { - log.info( - "Can not ADD error message, because 'GUIBuilderConfiguration' is not modifieable "); + log.info("Can not ADD error message, because 'GUIBuilderConfiguration' is not modifieable "); } guiBuilder.build(httpReq, httpResp, config, "Error-Message"); @@ -511,50 +472,40 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer } - private void internalMoaidExceptionHandler(final HttpServletRequest req, - final HttpServletResponse resp, final Exception e, final boolean writeExceptionToStatisicLog) - throws IOException, EaafException { - final String internalErrorCode = statusMessager.getResponseErrorCode(e); - + private void displayException(final HttpServletRequest req, final HttpServletResponse resp, + final ErrorTicketService.HandleData errorData) + throws IOException, EaafException { + final Throwable e = errorData.getThrowable(); + final String internalErrorCode = errorData.getErrorCode(); + + // send error response if (e instanceof ProtocolNotActiveException) { resp.getWriter().write(Encode.forHtml(e.getMessage())); resp.setContentType(EaafConstants.CONTENTTYPE_HTML_UTF8); resp.sendError(HttpServletResponse.SC_FORBIDDEN, StringEscapeUtils.escapeHtml4(StringEscapeUtils.escapeEcmaScript(e.getMessage()))); - } else if (e instanceof AuthnRequestValidatorException) { - final AuthnRequestValidatorException ex = (AuthnRequestValidatorException) e; - // log Error Message - if (writeExceptionToStatisicLog) { - statisticLogger.logErrorOperation(ex, ex.getErrorRequest()); - } - + } else if (e instanceof AuthnRequestValidatorException || e instanceof InvalidProtocolRequestException || + e instanceof ProcessExecutionException || e instanceof ConfigurationException) { // write error message writeHtmlErrorResponse(req, resp, e.getMessage(), internalErrorCode, null, - statusMessager.mapInternalErrorToExternalError(internalErrorCode)); - - } else if (e instanceof InvalidProtocolRequestException) { - // send error response - writeHtmlErrorResponse(req, resp, e.getMessage(), internalErrorCode, null, - statusMessager.mapInternalErrorToExternalError(internalErrorCode)); - - } else if (e instanceof ConfigurationException) { - // send HTML formated error message - writeHtmlErrorResponse(req, resp, e.getMessage(), internalErrorCode, null, - statusMessager.mapInternalErrorToExternalError(internalErrorCode)); + statusMessager.mapInternalErrorToExternalError(internalErrorCode), errorData.getRedirectUrl(), + errorData.getSupportTicket()); } else if (e instanceof EaafException) { // send HTML formated error message - writeHtmlErrorResponse(req, resp, e.getMessage(), internalErrorCode, - ((EaafException) e).getParams(), statusMessager.mapInternalErrorToExternalError(internalErrorCode)); + writeHtmlErrorResponse(req, resp, e.getMessage(), internalErrorCode, ((EaafException) e).getParams(), + statusMessager.mapInternalErrorToExternalError(internalErrorCode), errorData.getRedirectUrl(), + errorData.getSupportTicket()); - } else if (e instanceof ProcessExecutionException) { - // send HTML formated error message - writeHtmlErrorResponse(req, resp, e.getMessage(), internalErrorCode, null, - statusMessager.mapInternalErrorToExternalError(internalErrorCode)); + } else { + // write generic message for general exceptions + final String msg = statusMessager.getMessage(IStatusMessenger.CODES_INTERNAL_ERROR_GENERIC, null); + writeHtmlErrorResponse(req, resp, msg, internalErrorCode, null, + statusMessager.mapInternalErrorToExternalError(internalErrorCode), errorData.getRedirectUrl(), + errorData.getSupportTicket()); } - } private IGuiBuilderConfiguration evaluateRequiredErrorHandlingMethod(IRequest first, String errorId) { @@ -562,9 +513,7 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer return guiConfigFactory.getDefaultIFrameParentHopGui(first, ProtocolFinalizationController.ENDPOINT_ERRORHANDLING, errorId); - } - return null; } @@ -573,6 +522,7 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer redirectUrl = ServletUtils.getBaseUrl(req); redirectUrl += ProtocolFinalizationController.ENDPOINT_ERRORHANDLING + "?" + EaafConstants.PARAM_HTTP_ERROR_CODE + "=" + errorKey; + return redirectUrl; } 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 b2130fb4..13a93e73 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 @@ -56,11 +56,70 @@ public class ProtocolFinalizationController extends AbstractController { EaafConstants.ENDPOINT_PREFIX_SECURED + "/finalizeAuthProtocol"; public static final String ENDPOINT_ERRORHANDLING = EaafConstants.ENDPOINT_PREFIX_SECURED + "/errorHandling"; + public static final String ENDPOINT_ERROR_REDIRECT = + EaafConstants.ENDPOINT_PREFIX_SECURED + "errorRedirect"; + @Autowired(required = true) IRequestStorage requestStorage; @Autowired IPendingRequestIdGenerationStrategy requestIdValidationStragegy; + @RequestMapping(value = ENDPOINT_ERROR_REDIRECT, method = { RequestMethod.GET, RequestMethod.POST }) + public void errorRedirect(final HttpServletRequest req, final HttpServletResponse resp) + throws EaafException, IOException { + + final String errorToken = + StringEscapeUtils.escapeHtml4(req.getParameter(EaafConstants.PARAM_HTTP_ERROR_CODE)); + if (errorToken != null) { + IRequest pendingReq = null; + try { + String errorId = requestIdValidationStragegy.validateAndGetPendingRequestId(errorToken); + log.debug("Searching exception with internal error-token: {}", errorId); + + // load stored exception from database + final byte[] containerSerialized = transactionStorage.get(errorId, byte[].class); + if (containerSerialized != null) { + // remove exception if it was found + transactionStorage.remove(errorId); + log.trace("Find exception with internal error-token: {}", errorId); + + //final Object containerObj = EaafSerializationUtils.deserialize(containerSerialized, + // Arrays.asList( + // ExceptionContainer.class.getName() + // )); + final Object containerObj = SerializationUtils.deserialize(containerSerialized); + + if (containerObj instanceof ExceptionContainer) { + final ExceptionContainer container = (ExceptionContainer) containerObj; + final Throwable throwable = container.getExceptionThrown(); + pendingReq = container.getPendingRequest(); + + if (pendingReq != null) { + + } + } + } + } catch (Exception e) { + } + } + + //TODO finish +// final Class clazz = Class.forName(req.requestedModule()); +// +// if (clazz == null || !IModulInfo.class.isAssignableFrom(clazz)) { +// log.error( +// "Requested protocol module Class is NULL or does not implement the IModulInfo interface."); +// throw new ClassCastException( +// "Requested protocol module Class is NULL or does not implement the IModulInfo interface."); +// +// } +// +// final IModulInfo handlingModule = (IModulInfo) applicationContext.getBean(clazz); +// +// handlingModule.generateErrorMessage(throwable, req, resp, protocolRequest); + + } + /** * End-Point to handle errors. * @@ -69,6 +128,7 @@ public class ProtocolFinalizationController extends AbstractController { * @throws EaafException In case of an internal error * @throws IOException In case of a servlet error */ + // TODO reuse for the redirection to SP or own enpoint @RequestMapping(value = ENDPOINT_ERRORHANDLING, method = { RequestMethod.GET, RequestMethod.POST }) public void errorHandling(final HttpServletRequest req, final HttpServletResponse resp) throws EaafException, IOException { 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 6580fa30..7387f706 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 @@ -19,17 +19,16 @@ package at.gv.egiz.eaaf.core.api.idp.auth.services; -import java.io.IOException; - -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.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; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + public interface IProtocolAuthenticationService { String PARAM_GUI_ERROMSG = "errorMsg"; @@ -37,6 +36,8 @@ public interface IProtocolAuthenticationService { String PARAM_GUI_EXTERNAL_ERRORCODE = "extErrorCode"; String PARAM_GUI_ERRORCODEPARAMS = "errorParams"; String PARAM_GUI_ERRORSTACKTRACE = "stacktrace"; + String PARAM_GUI_TICKET = "supportTicket"; + String PARAM_GUI_REDIRECT = "redirectLink"; /** * Initialize an authentication process for this protocol request. -- cgit v1.2.3