From 3cbba3fcda614fa37357822d0eeb543c3e19276e Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Wed, 21 Apr 2021 07:42:50 +0200 Subject: some small updates in central error-handling --- .../idp/auth/AbstractAuthenticationManager.java | 2 +- .../idp/auth/services/DefaultErrorService.java | 111 ++++++++++ .../impl/idp/auth/services/ErrorTicketService.java | 243 --------------------- .../core/impl/idp/auth/services/IErrorService.java | 104 +++++++-- .../services/ProtocolAuthenticationService.java | 201 +++++++++-------- .../controller/ProtocolFinalizationController.java | 7 +- .../tasks/RestartAuthProzessManagement.java | 2 +- .../messages/eaaf_core_messages.properties | 12 + .../services/IProtocolAuthenticationService.java | 30 +-- 9 files changed, 337 insertions(+), 375 deletions(-) create mode 100644 eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/DefaultErrorService.java delete 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/AbstractAuthenticationManager.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/AbstractAuthenticationManager.java index d2365e4a..2449340d 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/AbstractAuthenticationManager.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/AbstractAuthenticationManager.java @@ -348,7 +348,7 @@ public abstract class AbstractAuthenticationManager implements IAuthenticationMa if (processDefinitionId == null) { log.warn("No suitable process found for PendingReqId " + pendingReq.getPendingRequestId()); - throw new EaafException("process.02", new Object[] { pendingReq.getPendingRequestId() }); + throw new EaafException("process.02", null); } diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/DefaultErrorService.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/DefaultErrorService.java new file mode 100644 index 00000000..e8be535c --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/DefaultErrorService.java @@ -0,0 +1,111 @@ +package at.gv.egiz.eaaf.core.impl.idp.auth.services; + +import java.text.MessageFormat; +import java.util.HashSet; + +import javax.annotation.PostConstruct; +import javax.servlet.http.HttpServletRequest; + +import org.springframework.beans.factory.annotation.Autowired; + +import at.gv.egiz.eaaf.core.api.IStatusMessenger; +import at.gv.egiz.eaaf.core.api.gui.ModifyableGuiBuilderConfiguration; +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.utils.KeyValueUtils; +import lombok.Builder; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class DefaultErrorService implements IErrorService { + 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 IConfiguration basicConfig; + @Autowired IStatusMessenger statusMessager; + + private final HashSet logOnInfoLevel = new HashSet<>(); + + @Override + public String getExternalCodeFromInternal(String internalCode) { + return statusMessager.mapInternalErrorToExternalError(internalCode); + + } + + @Override + public IHandleData createHandleData(Throwable throwable, boolean supportRedirctToSp) throws EaafException { + String internalErrorId = extractInternalErrorCode(throwable); + + return HandleData.builder() + .throwable(throwable) + .internalErrorCode(internalErrorId) + .actionType(ActionType.NO_TICKET) + .logLevel(logOnInfoLevel.contains(internalErrorId) ? LogLevel.INFO : LogLevel.WARN) + .build(); + + } + + @Override + public void displayErrorData(ModifyableGuiBuilderConfiguration c, IHandleData errorData, + HttpServletRequest httpReq) throws EaafException { + log.trace("Do nothing because Tickets are not supported by: {}", DefaultErrorService.class.getName()); + + } + + private String extractInternalErrorCode(Throwable throwable) { + Throwable originalException; + if (throwable instanceof TaskExecutionException + && ((TaskExecutionException) throwable).getOriginalException() != null) { + originalException = ((TaskExecutionException) throwable).getOriginalException(); + + } else { + originalException = throwable; + + } + + if (!(originalException instanceof EaafException)) { + return IStatusMessenger.CODES_INTERNAL_ERROR_GENERIC; + + } else { + return ((EaafException) originalException).getErrorId(); + + } + } + + @PostConstruct + private void initialize() throws EaafException { + log.info("initErrorTicketService"); + + logOnInfoLevel.addAll(KeyValueUtils.getListOfCsvValues( + basicConfig.getBasicConfiguration(CONFIG_PROP_LOGGER_ON_INFO_LEVEL))); + log.info("Set errorCodes={} to LogLevel:INFO", String.join(",", logOnInfoLevel)); + + } + + @Builder + static class HandleData implements IHandleData { + + @Getter + private String errorIdTokenForRedirect; + + @Getter + private final Throwable throwable; + + @Getter + private String internalErrorCode; + + @Getter + private ActionType actionType; + + @Getter + private LogLevel logLevel; + + public String getPreFormatedErrorMessage() { + return MessageFormat.format(TECH_LOG_MSG, internalErrorCode, throwable.getMessage()); + + } + + } +} 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 deleted file mode 100644 index 0834aa27..00000000 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/ErrorTicketService.java +++ /dev/null @@ -1,243 +0,0 @@ -package at.gv.egiz.eaaf.core.impl.idp.auth.services; - -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; - -import javax.annotation.PostConstruct; -import javax.servlet.http.HttpServletRequest; - -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 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; - -@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"), NOTICKET_AUTOREDIRECT( - "noticket_autoredirect"); - - 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 mapping not known"); - throw new EaafException("internal.configuration.00", - new Object[]{CONFIG_PROP_ERRORHANDLING_ACTION_PATH}); - } else { - - Properties getProperties = new Properties(); - String fullFilePath = null; - try { - - 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: could not found file.", e); - throw new EaafException("internal.configuration.01", - new Object[]{CONFIG_PROP_ERRORHANDLING_ACTION_PATH, "File for errorhandling-action mapping cloud " - + "not be found."}); - } - } - } - - /** - * creates error handling data. - * @param throwable error - * @param req http request - * @return eror handle Data - * @throws EaafException In case of an internal error - */ - public HandleData createHandleData(Throwable throwable, HttpServletRequest req) throws EaafException { - 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) throws EaafException { - - 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 if (action.equals(ActionType.NOTICKET_AUTOREDIRECT.toString())) { - data.actionType = ActionType.NOTICKET_AUTOREDIRECT; - - } else { // ActionType.NOTICKET_NOREDIRECT -> nothing to be done - data.actionType = ActionType.NOTICKET_NOREDIRECT; - - } - - } else { - data.generateSupportTicket(); - throw new EaafException("internal.configuration.00", - new Object[]{data.errorCode + " in on_error_action" + ".properties"}); - } - } - - static 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; - } - - /** - * Logs error to technical log. - */ - 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); - } - } - - /** - * Logs info to technical log. - */ - 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); - } - } - - /** - * Logs warn to technical log. - */ - 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/IErrorService.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/IErrorService.java index 4e04a87f..e545cb47 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/IErrorService.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/auth/services/IErrorService.java @@ -1,7 +1,5 @@ package at.gv.egiz.eaaf.core.impl.idp.auth.services; -import java.util.HashSet; - import javax.annotation.Nonnull; import javax.servlet.http.HttpServletRequest; @@ -9,13 +7,12 @@ import at.gv.egiz.eaaf.core.api.gui.ModifyableGuiBuilderConfiguration; import at.gv.egiz.eaaf.core.exceptions.EaafException; public interface IErrorService { + /** * Describes the kind of action that should be taken. */ enum ActionType { - TICKET_REDIRECT("ticket_redirect"), TICKET_NOREDIRECT("ticket_noredirect"), NOTICKET_REDIRECT( - "noticket_redirect"), NOTICKET_NOREDIRECT("noticket_noredirect"), NOTICKET_AUTOREDIRECT( - "noticket_autoredirect"); + TICKET("ticket"), NO_TICKET("no_ticket"); private final String name; @@ -23,12 +20,66 @@ public interface IErrorService { this.name = text; } + + /** + * Get flow type for error-handling from String representation. + * + * @param s Config parameter + * @return Error-handling flow + */ + public static ActionType fromString(final String s) { + try { + return ActionType.valueOf(s.toUpperCase()); + + } catch (IllegalArgumentException | NullPointerException e) { + return null; + + } + } + @Override public String toString() { return name; } } + /** + * Defines the LogLevel for this types of errors. + */ + enum LogLevel { + ERROR("error"), WARN("warn"), INFO("info"), DEBUG("debug"); + + private final String level; + + LogLevel(final String logLevel) { + this.level = logLevel; + + } + + + /** + * Get the log-level from String representation. + * + * @param s Config parameter + * @return Log-Level from configuration or ERROR as backup + */ + public static LogLevel fromString(final String s) { + try { + return LogLevel.valueOf(s.toUpperCase()); + + } catch (IllegalArgumentException | NullPointerException e) { + return LogLevel.ERROR; + + } + } + + @Override + public String toString() { + return level; + } + + } + String PARAM_GUI_TICKET = "supportTicket"; String PARAM_GUI_REDIRECT = "redirectLink"; @@ -38,33 +89,43 @@ public interface IErrorService { * @return external error code */ @Nonnull - String getExternalCodeFromInternal(String internalCode); + String getExternalCodeFromInternal(@Nonnull String internalCode); /** - * creates error handling data. + * Creates error handling data. * - * @param throwable error - * @param req http request - * @return eror handle Data + * @param throwable Error that should be handled + * @param supportRedirctToSp true if the current process-state supports redirect + * to Service-Provider, otherwise false + * @return Information how the error should be handled * @throws EaafException In case of an internal error */ @Nonnull - IHandleData createHandleData(Throwable throwable, HttpServletRequest req) throws EaafException; + IHandleData createHandleData(@Nonnull Throwable throwable, boolean supportRedirctToSp) throws EaafException; /** * Displays the error using suitable errordata. * * @param c guibuilder * @param errorData Data to handle + * @param httpReq Current HTTP request * @throws EaafException In case of an internal error */ - void displayErrorData(ModifyableGuiBuilderConfiguration c, IErrorService.IHandleData errorData) - throws EaafException; + void displayErrorData(@Nonnull ModifyableGuiBuilderConfiguration c, @Nonnull IErrorService.IHandleData errorData, + @Nonnull HttpServletRequest httpReq) throws EaafException; /** * Contains all the Model data for Error Handling. */ interface IHandleData { + + /** + * Get a new pendingReqId that can be used to store the error for SP forwarding. + * + * @return errorToken as pendingRequest + */ + String getErrorIdTokenForRedirect(); + /** * Describes the kind of action that should be taken. * @@ -85,12 +146,19 @@ public interface IErrorService { * @return causing throwable */ Throwable getThrowable(); - + /** - * Write a Exception to the MOA-ID-Auth internal technical log. - * - * @param logOnInfoLevel set of what to log on info logging lvl + * Get the log-level for this internal errorId. + * + * @return Level to Log the error + */ + LogLevel getLogLevel(); + + /** + * Get pre-formated text for log message. + * + * @return log message */ - void logExceptionToTechnicalLog(HashSet logOnInfoLevel); + String getPreFormatedErrorMessage(); } } 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 a64ad45e..4b2cbd0e 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 @@ -20,7 +20,6 @@ package at.gv.egiz.eaaf.core.impl.idp.auth.services; import java.io.IOException; -import java.util.HashSet; import javax.annotation.PostConstruct; import javax.naming.ConfigurationException; @@ -53,7 +52,6 @@ import at.gv.egiz.eaaf.core.api.gui.ModifyableGuiBuilderConfiguration; 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; @@ -75,20 +73,17 @@ 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.auth.services.IErrorService.ActionType; +import at.gv.egiz.eaaf.core.impl.idp.auth.services.IErrorService.IHandleData; +import at.gv.egiz.eaaf.core.impl.idp.auth.services.IErrorService.LogLevel; 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.KeyValueUtils; import at.gv.egiz.eaaf.core.impl.utils.ServletUtils; - - - @Service 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"; - @Autowired(required = true) private ApplicationContext applicationContext; @Autowired(required = true) @@ -103,8 +98,6 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer private IRequestStorage requestStorage; @Autowired(required = true) IPendingRequestIdGenerationStrategy pendingReqIdGenerationStrategy; - @Autowired - private IConfiguration basicConfig; @Autowired(required = true) private IErrorService errorTicketService; @@ -114,21 +107,15 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer @Autowired private IStatisticLogger statisticLogger; - + @Autowired private IRevisionLogger revisionsLogger; @Autowired(required = true) protected ITransactionStorage transactionStorage; - @Autowired - IPendingRequestIdGenerationStrategy requestIdValidationStragegy; - - private IGuiFormBuilder guiBuilder; - private final HashSet logOnInfoLevel = new HashSet<>(); - /* * (non-Javadoc) * @@ -153,7 +140,7 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer if (oaParam == null) { throw new EaafAuthenticationException(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_NOSPCONFIG, - new Object[]{pendingReq.getSpEntityId()}); + new Object[] { pendingReq.getSpEntityId() }); } if (authmanager.doAuthentication(req, resp, pendingReq)) { @@ -163,7 +150,8 @@ 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()); } @@ -197,7 +185,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, + new EaafAuthenticationException(IStatusMessenger.CODES_INTERNAL_ERROR_AUTH_USERSTOP, + new Object[] {}), req, resp, pendingReq); // check if pending-request are authenticated @@ -206,7 +195,8 @@ 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(), + log.warn("PendingRequest flag for 'authenticated':{} and 'needConsent':{}", pendingReq + .isAuthenticated(), pendingReq.isNeedUserConsent()); if (pendingReq.isNeedUserConsent()) { log.error("PendingRequest NEEDS user-consent. " @@ -228,65 +218,56 @@ 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 { try { - IErrorService.IHandleData errorData = errorTicketService.createHandleData(throwable, req); - if (errorData.getActionType().equals(IErrorService.ActionType.TICKET_REDIRECT) || errorData.getActionType() - .equals(IErrorService.ActionType.NOTICKET_REDIRECT)) { + final IErrorService.IHandleData errorData = errorTicketService.createHandleData(throwable, true); - // Put pending request - ExceptionContainer exceptionContainer = new ExceptionContainer(protocolRequest, throwable); - byte[] serialized = SerializationUtils.serialize(exceptionContainer); - // transactionStorage.put(req.getParameter(EaafConstants.PARAM_HTTP_ERROR_CODE), serialized, -1); - String errorId = requestIdValidationStragegy - .validateAndGetPendingRequestId(req.getParameter(EaafConstants.PARAM_HTTP_ERROR_CODE)); - transactionStorage.put(errorId, serialized, -1); + // log Error to technical log + logExceptionToTechnicalLog(errorData); - // log Error to technical log - errorData.logExceptionToTechnicalLog(logOnInfoLevel); + // log Error Message + statisticLogger.logErrorOperation(throwable, protocolRequest); - // log Error Message - statisticLogger.logErrorOperation(throwable, protocolRequest); + // write revision log entries + revisionsLogger.logEvent(protocolRequest, EventConstants.TRANSACTION_ERROR, + protocolRequest.getUniqueTransactionIdentifier()); - displayException(req, resp, errorData); + if (ActionType.TICKET.equals(errorData.getActionType())) { + // Put pending request + final ExceptionContainer exceptionContainer = new ExceptionContainer(protocolRequest, throwable); + final byte[] serialized = SerializationUtils.serialize(exceptionContainer); + transactionStorage.put(errorData.getErrorIdTokenForRedirect(), serialized, -1); - } else if (errorData.getActionType().equals(IErrorService.ActionType.NOTICKET_AUTOREDIRECT)) { - IModulInfo handlingModule = extractShibbolethHandling(protocolRequest, applicationContext); + // render GUI + displayException(req, resp, errorData); + } else { + final IModulInfo handlingModule = extractShibbolethHandling(protocolRequest, applicationContext); if (handlingModule.generateErrorMessage(throwable, req, resp, protocolRequest)) { - - // log Error to technical log - errorData.logExceptionToTechnicalLog(logOnInfoLevel); - - // log Error Message - statisticLogger.logErrorOperation(throwable, protocolRequest); - - // write revision log entries - revisionsLogger.logEvent(protocolRequest, EventConstants.TRANSACTION_ERROR, - protocolRequest.getUniqueTransactionIdentifier()); + log.debug("Error-response to SP successfully written"); } else { - throw throwable; //through it on to handleErrorNoRedirect + log.info("Error-response to SP FAILED. Writing error message into GUI ... "); + displayException(req, resp, errorData); } - - } else { - throw throwable; //through it on to handleErrorNoRedirect - } } catch (final Throwable e) { - // if building error response results in error, we try with with handleErrorNoRedirect - handleErrorNoRedirect(e, req, resp, true); + // if building error response results in error, we try with with + // handleErrorNoRedirect + log.error("ErrorHandling has an internel error. Show process-error in GUI ... ", e); + handleErrorNoRedirect(throwable, req, resp, false); + } } @@ -298,7 +279,8 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer * @return IModulInfo * @throws ClassNotFoundException If no shibboleth handling implementation found */ - public static IModulInfo extractShibbolethHandling(IRequest protocolRequest, ApplicationContext applicationContext) + public static IModulInfo extractShibbolethHandling(IRequest protocolRequest, + ApplicationContext applicationContext) throws ClassNotFoundException { final Class clazz = Class.forName(protocolRequest.requestedModule()); @@ -308,17 +290,16 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer "Requested protocol module Class is NULL or does not implement the IModulInfo interface."); } - + return (IModulInfo) applicationContext.getBean(clazz); } - @Override public void handleErrorNoRedirect(final Throwable throwable, final HttpServletRequest req, - final HttpServletResponse resp, final boolean writeExceptionToStatisticLog) throws EaafException, IOException { + final HttpServletResponse resp, final boolean writeExceptionToStatisticLog) throws EaafException, + IOException { - IErrorService.IHandleData errorData = null; - errorData = errorTicketService.createHandleData(throwable, req); + final IErrorService.IHandleData errorData = errorTicketService.createHandleData(throwable, true); // log Exception into statistic database if (writeExceptionToStatisticLog) { @@ -326,24 +307,45 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer } // write errror to console - errorData.logExceptionToTechnicalLog(logOnInfoLevel); + logExceptionToTechnicalLog(errorData); + + // render GUI + displayException(req, resp, errorData); + + } + + private void logExceptionToTechnicalLog(IHandleData errorData) { + // In case of a TaskExecutionException, which is only a container for + // process-errors, + // extract internal exception + + // Log exception + if (!(errorData.getThrowable() instanceof EaafException) + || LogLevel.ERROR.equals(errorData.getLogLevel())) { + log.error(errorData.getPreFormatedErrorMessage(), errorData.getThrowable()); + + } else if (LogLevel.WARN.equals(errorData.getLogLevel())) { + log.warn(errorData.getPreFormatedErrorMessage(), errorData.getThrowable()); + + } else if (LogLevel.INFO.equals(errorData.getLogLevel())) { + log.info(errorData.getPreFormatedErrorMessage(), errorData.getThrowable()); + + } else if (LogLevel.DEBUG.equals(errorData.getLogLevel())) { + log.debug(errorData.getPreFormatedErrorMessage(), errorData.getThrowable()); - if (errorData.getActionType().equals(IErrorService.ActionType.NOTICKET_NOREDIRECT) || errorData - .getActionType().equals(IErrorService.ActionType.TICKET_NOREDIRECT)) { - // return error to Web browser - displayException(req, resp, errorData); } else { - // TODO introduce separate error type? - throw new EaafException("internal.configuration.01", new Object[]{ - errorData.getInternalErrorCode() + " in on_error_action" + ".properties", "Erroraction mapping mismatch"}); + log.warn("Get unsupported LogLevelType: {}. Use {} as default", + errorData.getLogLevel(), LogLevel.ERROR); + log.error(errorData.getPreFormatedErrorMessage(), errorData.getThrowable()); + } } - @Override public void forwardToErrorHandler(Pair errorToHandle, String errorKey, final HttpServletRequest req, final HttpServletResponse resp) throws GuiBuildException { - final IGuiBuilderConfiguration parentHopGuiConfig = evaluateRequiredErrorHandlingMethod(errorToHandle.getFirst(), + final IGuiBuilderConfiguration parentHopGuiConfig = evaluateRequiredErrorHandlingMethod(errorToHandle + .getFirst(), errorKey); if (parentHopGuiConfig != null) { log.trace("iFrame to parent hop requested. Building GUI step for error handling ... "); @@ -372,7 +374,8 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer * @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, + protected void internalFinalizeAuthenticationProcess(final HttpServletRequest req, + final HttpServletResponse resp, final IRequest pendingReq) throws Exception { String newSsoSessionId = null; @@ -395,7 +398,8 @@ 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)) { @@ -422,9 +426,6 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer @PostConstruct private void initializer() { log.trace("Initializing {} ...", ProtocolAuthenticationService.class.getName()); - logOnInfoLevel - .addAll(KeyValueUtils.getListOfCsvValues(basicConfig.getBasicConfiguration(CONFIG_PROP_LOGGER_ON_INFO_LEVEL))); - log.info("Set errorCodes={} to LogLevel:INFO", String.join(",", logOnInfoLevel)); } @@ -439,12 +440,14 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer * @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."); @@ -454,20 +457,24 @@ 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); + "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 { - // this.writeHtmlErrorResponse(httpReq, httpResp, msg, errorCode, params, externalErrorCode, null, null); - // } - + // 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); + // } private void writeHtmlErrorResponse(@NonNull final HttpServletRequest httpReq, @NonNull final HttpServletResponse httpResp, @NonNull final String msg, @NonNull final String errorCode, @@ -480,7 +487,7 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer 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++) { @@ -495,16 +502,17 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer // add errorcode and errormessage if (config instanceof ModifyableGuiBuilderConfiguration) { - ModifyableGuiBuilderConfiguration c = (ModifyableGuiBuilderConfiguration) config; + final 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_ERRORCODE, + errorCode); // TODO: should we keep the internal errorcode secret? - c.putCustomParameter(AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG, PARAM_GUI_EXTERNAL_ERRORCODE, + c.putCustomParameter(AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG, + PARAM_GUI_EXTERNAL_ERRORCODE, externalErrorCode); c.putCustomParameterWithOutEscaption(AbstractGuiFormBuilderConfiguration.PARAM_GROUP_MSG, PARAM_GUI_ERRORCODEPARAMS, ArrayUtils.toString(errorCodeParams)); - errorTicketService.displayErrorData(c, errorData); - + errorTicketService.displayErrorData(c, errorData, httpReq); } else { log.info("Can not ADD error message, because 'GUIBuilderConfiguration' is not modifieable "); @@ -555,7 +563,8 @@ public class ProtocolAuthenticationService implements IProtocolAuthenticationSer private IGuiBuilderConfiguration evaluateRequiredErrorHandlingMethod(IRequest first, String errorId) { if (first != null && first.isProcessInIframe()) { return guiConfigFactory - .getDefaultIFrameParentHopGui(first, "/" + ProtocolFinalizationController.ENDPOINT_ERRORHANDLING, errorId); + .getDefaultIFrameParentHopGui(first, ProtocolFinalizationController.ENDPOINT_ERRORHANDLING, + errorId); } return null; 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 a8b0a961..dce2251a 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 @@ -105,14 +105,17 @@ public class ProtocolFinalizationController extends AbstractController { if (pendingReq != null) { IModulInfo handlingModule = ProtocolAuthenticationService .extractShibbolethHandling(pendingReq, applicationContext); - - handlingModule.generateErrorMessage(throwable, req, resp, pendingReq); + if (!handlingModule.generateErrorMessage(throwable, req, resp, pendingReq)) { + protAuthService.handleErrorNoRedirect(new EaafException("process.90", null), req, resp, false); + + } } } } } catch (Throwable e) { log.error(e.getMessage(), e); protAuthService.handleErrorNoRedirect(e, req, resp, false); + } finally { // remove pending-request if (pendingReq != null) { diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/RestartAuthProzessManagement.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/RestartAuthProzessManagement.java index 08bf588f..c3f3d32e 100644 --- a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/RestartAuthProzessManagement.java +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/RestartAuthProzessManagement.java @@ -82,7 +82,7 @@ public class RestartAuthProzessManagement extends AbstractAuthServletTask { if (processDefinitionId == null) { log.warn("No suitable authentication process found for SessionID " + pendingReq.getPendingRequestId()); - throw new EaafException("process.02", new Object[] { pendingReq.getPendingRequestId() }); + throw new EaafException("process.02", null); } final String processInstanceId = diff --git a/eaaf_core/src/main/resources/messages/eaaf_core_messages.properties b/eaaf_core/src/main/resources/messages/eaaf_core_messages.properties index ff0be478..c5cb1bb1 100644 --- a/eaaf_core/src/main/resources/messages/eaaf_core_messages.properties +++ b/eaaf_core/src/main/resources/messages/eaaf_core_messages.properties @@ -5,3 +5,15 @@ builder.30=Decrypted bPK target: {0} does not match to required target: {1} builder.31=Encrypted bPK has a suspect format and consists of #{0} elements builder.32=bPK-target format must be full URI builder.33=bPK caluclation not possible. Reason: {0} + + + +process.01=Can not execute authentication process +process.02=Find no applicable authentication process for current state or user-selection. +process.03=Can not resume the authentication process. Reason: {0} +process.04=Can not execute authentication process. Problem with an internal state + +process.90=Forward to service-provider not possible, because it's not supported. + +process.98=Not supported internal state. Reason: {0} +process.99=Validation of RequestId: {0} FAILED. Reason: {1} \ No newline at end of file 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 f110d50e..8def4e32 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,16 +19,18 @@ package at.gv.egiz.eaaf.core.api.idp.auth.services; +import java.io.IOException; + +import javax.annotation.Nonnull; +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"; @@ -49,8 +51,8 @@ public interface IProtocolAuthenticationService { * @throws IOException In case of a communication error * @throws EaafException In case of an application error */ - void performAuthentication(HttpServletRequest httpReq, HttpServletResponse httpResp, IRequest pendingReq) - throws IOException, EaafException; + void performAuthentication(@Nonnull HttpServletRequest httpReq, @Nonnull HttpServletResponse httpResp, + @Nonnull IRequest pendingReq) throws IOException, EaafException; /** * Finalize the requested protocol operation. @@ -62,8 +64,8 @@ public interface IProtocolAuthenticationService { * {@link HttpServletResponse} * @throws EaafException If an internal error occur */ - void finalizeAuthentication(HttpServletRequest httpReq, HttpServletResponse httpResp, IRequest pendingReq) - throws EaafException, IOException; + void finalizeAuthentication(@Nonnull HttpServletRequest httpReq, @Nonnull HttpServletResponse httpResp, + @Nonnull IRequest pendingReq) throws EaafException, IOException; /** * Build protocol-specific error message. @@ -76,8 +78,8 @@ public interface IProtocolAuthenticationService { * {@link HttpServletResponse} * @throws EaafException If an internal error occur */ - void buildProtocolSpecificErrorResponse(Throwable throwable, HttpServletRequest req, HttpServletResponse resp, - IRequest pendingReq) throws IOException, EaafException; + void buildProtocolSpecificErrorResponse(@Nonnull Throwable throwable, @Nonnull HttpServletRequest req, + @Nonnull HttpServletResponse resp, @Nonnull IRequest pendingReq) throws IOException, EaafException; /** * Handles all exceptions with no pending request. Therefore, the error is @@ -94,8 +96,8 @@ public interface IProtocolAuthenticationService { * {@link HttpServletResponse} * @throws EaafException If an internal error occure */ - void handleErrorNoRedirect(Throwable throwable, HttpServletRequest req, HttpServletResponse resp, - boolean writeExceptionToStatisticLog) throws IOException, EaafException; + void handleErrorNoRedirect(@Nonnull Throwable throwable, @Nonnull HttpServletRequest req, + @Nonnull HttpServletResponse resp, boolean writeExceptionToStatisticLog) throws IOException, EaafException; /** * Forward the process to error-handler in case of an error. @@ -106,8 +108,8 @@ public interface IProtocolAuthenticationService { * @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; + void forwardToErrorHandler(@Nonnull Pair errorToHandle, @Nonnull String errorKey, + @Nonnull HttpServletRequest req, @Nonnull HttpServletResponse resp) throws GuiBuildException; -- cgit v1.2.3