From bee5dd259a4438d45ecd1bcc26dfba12875236d6 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Tue, 26 Jun 2018 11:03:48 +0200 Subject: initial commit --- .../AbstractAuthProtocolModulController.java | 225 ++++++++++++ .../impl/idp/controller/AbstractController.java | 354 +++++++++++++++++++ .../AbstractProcessEngineSignalController.java | 97 ++++++ .../controller/ProtocolFinalizationController.java | 178 ++++++++++ .../impl/idp/controller/protocols/RequestImpl.java | 386 +++++++++++++++++++++ .../tasks/FinalizeAuthenticationTask.java | 57 +++ .../tasks/RestartAuthProzessManagement.java | 92 +++++ 7 files changed, 1389 insertions(+) create mode 100644 eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractAuthProtocolModulController.java create mode 100644 eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractController.java create mode 100644 eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractProcessEngineSignalController.java create mode 100644 eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/ProtocolFinalizationController.java create mode 100644 eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/protocols/RequestImpl.java create mode 100644 eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/FinalizeAuthenticationTask.java create mode 100644 eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/RestartAuthProzessManagement.java (limited to 'eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller') diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractAuthProtocolModulController.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractAuthProtocolModulController.java new file mode 100644 index 00000000..d72ee404 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractAuthProtocolModulController.java @@ -0,0 +1,225 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eaaf.core.impl.idp.controller; + +import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +import at.gv.egiz.components.eventlog.api.EventConstants; +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.api.IStatusMessager; +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.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; +import at.gv.egiz.eaaf.core.api.idp.slo.SLOInformationInterface; +import at.gv.egiz.eaaf.core.exceptions.EAAFAuthenticationException; +import at.gv.egiz.eaaf.core.exceptions.EAAFSSOException; + +/** + * @author tlenz + * + */ + +public abstract class AbstractAuthProtocolModulController extends AbstractController { + private static final Logger log = LoggerFactory.getLogger(AbstractAuthProtocolModulController.class); + + public static final String ENDPOINT_FINALIZEPROTOCOL = "finalizeAuthProtocol"; + public static final String ENDPOINT_ERRORHANDLING = "errorHandling"; + + + @Autowired(required=true) private IAuthenticationManager authmanager; + @Autowired(required=true) private IAuthenticationDataBuilder authDataBuilder; + @Autowired(required=false) private ISSOManager ssoManager; + + /** + * Initialize an authentication process for this protocol request + * + * @param httpReq HttpServletRequest + * @param httpResp HttpServletResponse + * @param protocolRequest Authentication request which is actually in process + * @throws IOException + */ + protected void performAuthentication(HttpServletRequest req, HttpServletResponse resp, + IRequest pendingReq) throws IOException { + try { + if (pendingReq.isNeedAuthentication()) { + //request needs authentication --> start authentication process ... + + //load Parameters from OnlineApplicationConfiguration + ISPConfiguration oaParam = pendingReq.getServiceProviderConfiguration(); + + if (oaParam == null) + throw new EAAFAuthenticationException( + IStatusMessager.CODES_INTERNAL_ERROR_AUTH_NOSPCONFIG, + new Object[] { pendingReq.getSPEntityId() }, + "No Service Provider configuration found."); + + if (authmanager.doAuthentication(req, resp, pendingReq)) { + //pending request is already authenticated --> protocol-specific postProcessing can start directly + finalizeAuthenticationProcess(req, resp, pendingReq); + + //transaction is finished, log transaction finished event + revisionsLogger.logEvent(EventConstants.TRANSACTION_DESTROYED, pendingReq.getUniqueTransactionIdentifier()); + + } + + } else { + executeProtocolSpecificAction(req, resp, pendingReq, null); + + } + + } catch (Exception e) { + buildProtocolSpecificErrorResponse(e, req, resp, pendingReq); + authmanager.performOnlyIDPLogOut(req, resp, pendingReq); + + } + } + + + /** + * 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 + * @throws Exception + */ + protected void finalizeAuthenticationProcess(HttpServletRequest req, HttpServletResponse resp, + IRequest pendingReq) throws Exception { + + String newSSOSessionId = null; + + //if Single Sign-On functionality is enabled for this request + if (pendingReq.needSingleSignOnFunctionality()) { + if (ssoManager != null) + newSSOSessionId = ssoManager.createNewSSOSessionCookie(req, resp, pendingReq); + else + log.warn("SSO is requested but there is not SSO Session-Manager available"); + + } + + //build authenticationdata from session information and OA configuration + IAuthData authData = authDataBuilder.buildAuthenticationData(pendingReq); + + //execute the protocol-specific action + SLOInformationInterface sloInformation = executeProtocolSpecificAction(req, resp, pendingReq, authData); + + //Store OA specific SSO session information if an SSO cookie is set + if (StringUtils.isNotEmpty(newSSOSessionId)) { + try { + //create new SSO session, if actually no SSO session exists + if (StringUtils.isEmpty(pendingReq.getSSOSessionIdentifier())) { + ssoManager.createNewSSOSession(pendingReq, newSSOSessionId, sloInformation); + + //MOA SSO-session already exists only update is required + } else { + ssoManager.updateSSOSession(pendingReq, newSSOSessionId, sloInformation); + + + } + + } catch (EAAFSSOException e) { + log.warn("SSO Session information can not be stored -> SSO is not enabled!"); + authmanager.performOnlyIDPLogOut(req, resp, pendingReq); + + } + + } else { + //remove MOASession from database + authmanager.performOnlyIDPLogOut(req, resp, pendingReq); + + } + + //Advanced statistic logging + statisticLogger.logSuccessOperation(pendingReq, authData, StringUtils.isNotEmpty(newSSOSessionId)); + + } + + /** + * 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 + * + * @return Return Single LogOut information or null if protocol supports no SSO + * + * @throws Exception + */ + private SLOInformationInterface executeProtocolSpecificAction(HttpServletRequest httpReq, HttpServletResponse httpResp, + IRequest pendingReq, IAuthData authData) throws Exception { + try { + // request needs no authentication --> start request processing + 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."); + throw new Exception("Requested protocol-action processing Class is NULL or does not implement the IAction interface."); + + } + + IAction protocolAction = (IAction) applicationContext.getBean(clazz); + return protocolAction.processRequest(pendingReq, httpReq, httpResp, authData); + + } catch (ClassNotFoundException e) { + log.error("Requested Auth. protocol processing Class is NULL or does not implement the IAction interface."); + throw new Exception("Requested Auth. protocol processing Class is NULL or does not implement the IAction interface."); + } + + } + + protected void buildProtocolSpecificErrorResponse(Throwable throwable, HttpServletRequest req, + HttpServletResponse resp, IRequest protocolRequest) throws IOException { + try { + + Class clazz = Class.forName(protocolRequest.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 Exception("Requested protocol module Class is NULL or does not implement the IModulInfo interface."); + + } + + IModulInfo handlingModule = (IModulInfo) applicationContext.getBean(clazz); + + if (handlingModule.generateErrorMessage( + throwable, req, resp, protocolRequest)) { + + //log Error to technical log + logExceptionToTechnicalLog(throwable); + + //log Error Message + statisticLogger.logErrorOperation(throwable, protocolRequest); + + //write revision log entries + revisionsLogger.logEvent(protocolRequest, EventConstants.TRANSACTION_ERROR, protocolRequest.getUniqueTransactionIdentifier()); + + return; + + } else { + handleErrorNoRedirect(throwable, req, resp, true); + + } + + } catch (Throwable e) { + handleErrorNoRedirect(throwable, req, resp, true); + + } + + } + +} 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 new file mode 100644 index 00000000..980d77ba --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractController.java @@ -0,0 +1,354 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eaaf.core.impl.idp.controller; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; + +import javax.naming.ConfigurationException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +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.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.IRequestStorage; +import at.gv.egiz.eaaf.core.api.IStatusMessager; +import at.gv.egiz.eaaf.core.api.data.EAAFConstants; +import at.gv.egiz.eaaf.core.api.data.ExceptionContainer; +import at.gv.egiz.eaaf.core.api.gui.IGUIBuilderConfiguration; +import at.gv.egiz.eaaf.core.api.gui.IGUIBuilderConfigurationFactory; +import at.gv.egiz.eaaf.core.api.gui.IGUIFormBuilder; +import at.gv.egiz.eaaf.core.api.gui.ModifyableGuiBuilderConfiguration; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.api.logging.IRevisionLogger; +import at.gv.egiz.eaaf.core.api.logging.IStatisticLogger; +import at.gv.egiz.eaaf.core.api.storage.ITransactionStorage; +import at.gv.egiz.eaaf.core.exceptions.AuthnRequestValidatorException; +import at.gv.egiz.eaaf.core.exceptions.EAAFException; +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.utils.HTTPUtils; +import at.gv.egiz.eaaf.core.impl.utils.Random; +import at.gv.egiz.eaaf.core.impl.utils.ServletUtils; + + +/** + * @author tlenz + * + */ +public abstract class AbstractController { + + private static final Logger log = LoggerFactory.getLogger(AbstractController.class); + + @Autowired(required=true) protected ApplicationContext applicationContext; + @Autowired(required=true) protected IConfiguration authConfig; + @Autowired(required=true) protected ITransactionStorage transactionStorage; + @Autowired(required=true) protected IRequestStorage requestStorage; + @Autowired(required=true) protected IGUIFormBuilder guiBuilder; + @Autowired(required=true) protected IGUIBuilderConfigurationFactory guiConfigFactory; + @Autowired(required=true) protected IStatusMessager statusMessager; + + @Autowired protected IStatisticLogger statisticLogger; + @Autowired protected IRevisionLogger revisionsLogger; + + + + + + @ExceptionHandler({EAAFException.class}) + public void MOAIDExceptionHandler(HttpServletRequest req, HttpServletResponse resp, Exception e) throws IOException { + log.error(e.getMessage() , e); + internalMOAIDExceptionHandler(req, resp, e, true); + + } + + @ExceptionHandler({Exception.class}) + public void GenericExceptionHandler(HttpServletResponse resp, Exception exception) throws IOException { + log.error("Internel Server Error." , exception); + resp.setContentType(EAAFConstants.CONTENTTYPE_HTML_UTF8); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Internal Server Error!" + + "(Errorcode=9199" + +" | Description=" + + StringEscapeUtils.escapeHtml4(StringEscapeUtils.escapeEcmaScript(exception.getMessage())) + + ")"); + return; + + } + + @ExceptionHandler({IOException.class}) + public void IOExceptionHandler(HttpServletResponse resp, Throwable exception) { + log.error("Internel Server Error." , exception); + resp.setContentType(EAAFConstants.CONTENTTYPE_HTML_UTF8); + resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + return; + + } + + protected void handleError(String errorMessage, Throwable exceptionThrown, + HttpServletRequest req, HttpServletResponse resp, IRequest pendingReq) throws IOException { + + String pendingRequestID = null; + if (pendingReq != null) + pendingRequestID = pendingReq.getPendingRequestId(); + + Throwable loggedException = null; + Throwable extractedException = extractOriginalExceptionFromProcessException(exceptionThrown); + + //extract pendingRequestID and originalException if it was a TaskExecutionException + if (extractedException instanceof TaskExecutionException) { + //set original exception + loggedException = ((TaskExecutionException) extractedException).getOriginalException(); + + //use TaskExecutionException directly, if no Original Exeception is included + if (loggedException == null) + loggedException = exceptionThrown; + + //set pending-request ID if it is set + String reqID = ((TaskExecutionException) extractedException).getPendingRequestID(); + if (StringUtils.isNotEmpty(reqID)) + pendingRequestID = reqID; + + } else + loggedException = exceptionThrown; + + try { + //switch to protocol-finalize method to generate a protocol-specific error message + + //log error directly in debug mode + if (log.isDebugEnabled()) + log.warn(loggedException.getMessage(), loggedException); + + + //put exception into transaction store for redirect + String key = Random.nextLongRandom(); + if (pendingReq != null) { + revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR); + transactionStorage.put(key, + new ExceptionContainer(pendingReq, loggedException), -1); + + } else { + transactionStorage.put(key, + new ExceptionContainer(null, loggedException), -1); + + } + + //build up redirect URL + String redirectURL = null; + redirectURL = ServletUtils.getBaseUrl(req); + redirectURL += "/"+AbstractAuthProtocolModulController.ENDPOINT_ERRORHANDLING + + "?" + EAAFConstants.PARAM_HTTP_ERROR_CODE + "=" + key; + +// //only add pending-request Id if it exists +// if (StringUtils.isNotEmpty(pendingRequestID)) +// redirectURL += "&" + EAAFConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID + "=" + pendingRequestID; + + resp.setContentType("text/html"); + resp.setStatus(302); + + resp.addHeader("Location", redirectURL); + log.debug("REDIRECT TO: " + redirectURL); + + return; + + } catch (Exception e) { + log.warn("Default error-handling FAILED. Exception can not be stored ....", e); + log.info("Switch to generic generic backup error-handling ... "); + handleErrorNoRedirect(loggedException, req, resp, true); + + } + + } + + /** + * Handles all exceptions with no pending request. + * Therefore, the error is written to the users browser + * + * @param throwable + * @param req + * @param resp + * @throws IOException + */ + protected void handleErrorNoRedirect(Throwable throwable, HttpServletRequest req, + HttpServletResponse resp, boolean writeExceptionToStatisticLog) throws IOException { + + //log Exception into statistic database + if (writeExceptionToStatisticLog) + statisticLogger.logErrorOperation(throwable); + + //write errror to console + logExceptionToTechnicalLog(throwable); + + //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 + String msg = statusMessager.getMessage(IStatusMessager.CODES_INTERNAL_ERROR_GENERIC, null); + writeHTMLErrorResponse(req, resp, msg, "9199", (Exception) throwable); + + } + + } + + /** + * Write a Exception to the MOA-ID-Auth internal technical log + * + * @param loggedException Exception to log + */ + protected void logExceptionToTechnicalLog(Throwable loggedException) { + if (!( loggedException instanceof EAAFException + || loggedException instanceof ProcessExecutionException )) { + log.error("Receive an internal error: Message=" + loggedException.getMessage(), loggedException); + + } else { + if (log.isDebugEnabled() || log.isTraceEnabled()) { + log.warn(loggedException.getMessage(), loggedException); + + } else { + log.warn(loggedException.getMessage()); + + } + } + } + + private void writeBadRequestErrorResponse(HttpServletRequest req, HttpServletResponse resp, EAAFException e) throws IOException { + String code = statusMessager.mapInternalErrorToExternalError(((InvalidProtocolRequestException)e).getErrorId()); + String descr = StringEscapeUtils.escapeHtml4(StringEscapeUtils.escapeEcmaScript(e.getMessage())); + resp.setContentType(EAAFConstants.CONTENTTYPE_HTML_UTF8); + resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "Protocol validation FAILED!" + + "(Errorcode=" + code + + " | Description=" + descr + ")"); + + } + + private void writeHTMLErrorResponse(HttpServletRequest req, HttpServletResponse httpResp, String msg, String errorCode, Exception error) throws IOException { + + try { + IGUIBuilderConfiguration config + = guiConfigFactory.getDefaultErrorGUI(HTTPUtils.extractAuthURLFromRequest(req)); + +// HTTPUtils.extractAuthURLFromRequest(req), +// DefaultGUIFormBuilderConfiguration.VIEW_ERRORMESSAGE, +// null); + + //add errorcode and errormessage + if (config instanceof ModifyableGuiBuilderConfiguration) { + ((ModifyableGuiBuilderConfiguration)config).putCustomParameter("errorMsg", msg); + ((ModifyableGuiBuilderConfiguration)config).putCustomParameter("errorCode", errorCode); + + //add stacktrace if debug is enabled + if (log.isTraceEnabled()) { + ((ModifyableGuiBuilderConfiguration)config).putCustomParameter("stacktrace", getStacktraceFromException(error)); + + } + + } else + log.info("Can not ADD error message, because 'GUIBuilderConfiguration' is not modifieable "); + + + + guiBuilder.build(httpResp, config, "Error-Message"); + + } catch (GUIBuildException e) { + log.warn("Can not build error-message GUI.", e); + GenericExceptionHandler(httpResp, e); + + } + + } + + private void writeHTMLErrorResponse(HttpServletRequest req, HttpServletResponse httpResp, Exception error) throws IOException { + writeHTMLErrorResponse(req, httpResp, + error.getMessage(), + statusMessager.getResponseErrorCode(error), + error); + } + + + private String getStacktraceFromException(Exception ex) { + StringWriter errors = new StringWriter(); + ex.printStackTrace(new PrintWriter(errors)); + return errors.toString(); + + } + + /** + * Extracts a TaskExecutionException of a ProcessExecutionExeception Stacktrace. + * + * @param exception + * @return Return the latest TaskExecutionExecption if exists, otherwise the latest ProcessExecutionException + */ + private Throwable extractOriginalExceptionFromProcessException(Throwable exception) { + Throwable exholder = exception; + TaskExecutionException taskExc = null; + + while(exholder != null + && exholder instanceof ProcessExecutionException) { + ProcessExecutionException procExc = (ProcessExecutionException) exholder; + if (procExc.getCause() != null && + procExc.getCause() instanceof TaskExecutionException) { + taskExc = (TaskExecutionException) procExc.getCause(); + exholder = taskExc.getOriginalException(); + + } else + break; + + } + + if (taskExc == null) + return exholder; + + else + return taskExc; + } + + private void internalMOAIDExceptionHandler(HttpServletRequest req, HttpServletResponse resp, Exception e, boolean writeExceptionToStatisicLog) throws IOException { + if (e instanceof ProtocolNotActiveException) { + resp.getWriter().write(e.getMessage()); + resp.setContentType(EAAFConstants.CONTENTTYPE_HTML_UTF8); + resp.sendError(HttpServletResponse.SC_FORBIDDEN, + StringEscapeUtils.escapeHtml4(StringEscapeUtils.escapeEcmaScript(e.getMessage()))); + + } else if (e instanceof AuthnRequestValidatorException) { + AuthnRequestValidatorException ex = (AuthnRequestValidatorException)e; + //log Error Message + if (writeExceptionToStatisicLog) + statisticLogger.logErrorOperation(ex, ex.getErrorRequest()); + + //write error message + writeBadRequestErrorResponse(req, resp, (EAAFException) e); + + } else if (e instanceof InvalidProtocolRequestException) { + //send error response + writeBadRequestErrorResponse(req, resp, (EAAFException) e); + + } else if (e instanceof ConfigurationException) { + //send HTML formated error message + writeHTMLErrorResponse(req, resp, (EAAFException) e); + + } else if (e instanceof EAAFException) { + //send HTML formated error message + writeHTMLErrorResponse(req, resp, e); + + } else if (e instanceof ProcessExecutionException) { + //send HTML formated error message + writeHTMLErrorResponse(req, resp, e); + + } + + } + +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractProcessEngineSignalController.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractProcessEngineSignalController.java new file mode 100644 index 00000000..a4a86ca2 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/AbstractProcessEngineSignalController.java @@ -0,0 +1,97 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eaaf.core.impl.idp.controller; + +import java.io.IOException; + +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 at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.api.IStatusMessager; +import at.gv.egiz.eaaf.core.api.data.EAAFConstants; +import at.gv.egiz.eaaf.core.api.idp.process.ProcessEngine; +import at.gv.egiz.eaaf.core.exceptions.EAAFException; +import at.gv.egiz.eaaf.core.exceptions.EAAFIllegalStateException; +import at.gv.egiz.eaaf.core.impl.utils.TransactionIDUtils; + +/** + * Servlet that resumes a suspended process (in case of asynchronous tasks). + * + * @author tknall + * + */ +public abstract class AbstractProcessEngineSignalController extends AbstractController { + private static final Logger log = LoggerFactory.getLogger(AbstractProcessEngineSignalController.class); + + @Autowired protected ProcessEngine processEngine; + + protected void signalProcessManagement(HttpServletRequest req, HttpServletResponse resp) throws IOException { + String pendingRequestID = StringEscapeUtils.escapeHtml4(getPendingRequestId(req)); + IRequest pendingReq = null; + try { + if (pendingRequestID == null) { + new EAAFException( + IStatusMessager.CODES_INTERNAL_ERROR_AUTH_NOPENDIGREQID, + null, + "NO PendingRequestId found" + ); + + } + + pendingReq = requestStorage.getPendingRequest(pendingRequestID); + if (pendingReq == null) { + log.info("No PendingRequest with Id: " + pendingRequestID + " Maybe, a transaction timeout occure."); + throw new EAAFException(IStatusMessager.CODES_INTERNAL_ERROR_AUTH_TIMEOUT, new Object[]{pendingRequestID}, + "No PendingRequest with Id: \" + pendingRequestID + \" Maybe, a transaction timeout occure.\""); + + } + + //change pending-request ID + requestStorage.changePendingRequestID(pendingReq); + pendingRequestID = pendingReq.getPendingRequestId(); + + // process instance is mandatory + if (pendingReq.getProcessInstanceId() == null) { + throw new EAAFIllegalStateException(new Object[]{"MOA session does not provide process instance id."}, + "No execution environemnt found for this pending request"); + + } + + // wake up next task + processEngine.signal(pendingReq); + + } catch (Exception ex) { + handleError(null, ex, req, resp, pendingReq); + + } finally { + //MOASessionDBUtils.closeSession(); + TransactionIDUtils.removeAllLoggingVariables(); + + } + + + } + + /** + * Retrieves the current pending-request id from the HttpServletRequest parameter + * + *

+ * Note that this class/method can be overwritten by modules providing their own strategy of retrieving the + * respective pending-request id. + * + * @param request + * The unterlying HttpServletRequest. + * @return The current pending-request id. + */ + public String getPendingRequestId(HttpServletRequest request) { + return StringEscapeUtils.escapeHtml4(request.getParameter(EAAFConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID)); + + } + +} 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 new file mode 100644 index 00000000..3659ff4f --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/ProtocolFinalizationController.java @@ -0,0 +1,178 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eaaf.core.impl.idp.controller; + +import java.io.IOException; + +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.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import at.gv.egiz.components.eventlog.api.EventConstants; +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.api.IStatusMessager; +import at.gv.egiz.eaaf.core.api.data.EAAFConstants; +import at.gv.egiz.eaaf.core.api.data.ExceptionContainer; +import at.gv.egiz.eaaf.core.exceptions.EAAFAuthenticationException; +import at.gv.egiz.eaaf.core.exceptions.EAAFException; + +/** + * @author tlenz + * + */ +@Controller +public class ProtocolFinalizationController extends AbstractAuthProtocolModulController { + private static final Logger log = LoggerFactory.getLogger(ProtocolFinalizationController.class); + + @RequestMapping(value = ENDPOINT_ERRORHANDLING, method = {RequestMethod.GET}) + public void errorHandling(HttpServletRequest req, HttpServletResponse resp) throws EAAFException, IOException { + //receive an authentication error + String errorid = StringEscapeUtils.escapeHtml4(req.getParameter(EAAFConstants.PARAM_HTTP_ERROR_CODE)); + if (errorid != null) { + IRequest pendingReq = null; + try { + //load stored exception from database + ExceptionContainer container = transactionStorage.get(errorid, ExceptionContainer.class); + if (container != null) { + //remove exception if it was found + transactionStorage.remove(errorid); + + Throwable throwable = container.getExceptionThrown(); + pendingReq = container.getPendingRequest(); + + if (pendingReq != null) { + //build protocol-specific error message if possible + buildProtocolSpecificErrorResponse(throwable, req, resp, pendingReq); + + //remove active user-session + transactionStorage.remove(pendingReq.getPendingRequestId()); + + return; + + } else { + handleErrorNoRedirect(throwable, req, resp, true); + + } + } else { + handleErrorNoRedirect( + new EAAFException( + IStatusMessager.CODES_INTERNAL_ERROR_AUTH_NOPENDIGREQID, + null, + "NO Error with this Id found" + ), req, resp, false); + + } + + } catch (Throwable e) { + log.error(e.getMessage(), e); + handleErrorNoRedirect(e, req, resp, false); + + } finally { + //remove pending-request + if (pendingReq != null) { + requestStorage.removePendingRequest(pendingReq.getPendingRequestId()); + revisionsLogger.logEvent(EventConstants.TRANSACTION_DESTROYED, pendingReq.getUniqueTransactionIdentifier()); + + } + + } + + } else { + log.debug("Request contains NO ErrorId"); + handleErrorNoRedirect( + new EAAFException( + IStatusMessager.CODES_INTERNAL_ERROR_AUTH_NOPENDIGREQID, + null, + "Request containts NO error id." + ), req, resp, false); + + } + + } + + + @RequestMapping(value = ENDPOINT_FINALIZEPROTOCOL, method = {RequestMethod.GET}) + public void finalizeAuthProtocol(HttpServletRequest req, HttpServletResponse resp) throws EAAFException, IOException { + + //read pendingRequest from http request + Object idObject = StringEscapeUtils.escapeHtml4(req.getParameter(EAAFConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID)); + IRequest pendingReq = null; + String pendingRequestID = null; + if (idObject != null && (idObject instanceof String)) { + pendingRequestID = (String) idObject; + pendingReq = requestStorage.getPendingRequest(pendingRequestID); + + } + + if (pendingReq == null) { + log.error("No PendingRequest with ID " + pendingRequestID + " found.!"); + handleErrorNoRedirect( + new EAAFException( + IStatusMessager.CODES_INTERNAL_ERROR_AUTH_TIMEOUT, + new Object[]{pendingRequestID, + }, + "No pendigReq with Id: " + pendingRequestID), req, resp, false); + + } else { + try { + log.debug("Finalize PendingRequest with ID " + pendingRequestID); + + //check if pending-request has 'abortedByUser' flag set + if (pendingReq.isAbortedByUser()) { + //send authentication aborted error to Service Provider + buildProtocolSpecificErrorResponse( + new EAAFAuthenticationException( + IStatusMessager.CODES_INTERNAL_ERROR_AUTH_USERSTOP, + new Object[] {}, + "User stops authentication process"), + req, resp, pendingReq); + + //do not remove the full active SSO-Session + // in case of only one Service-Provider authentication request is aborted + if ( !pendingReq.needSingleSignOnFunctionality()) { + transactionStorage.remove(pendingReq.getPendingRequestId()); + + } + + //check if pending-request are authenticated + } else if (pendingReq.isAuthenticated()) { + finalizeAuthenticationProcess(req, resp, pendingReq); + + } else { + //suspect state: pending-request is not aborted but also are not authenticated + log.error("PendingRequest is NOT authenticated --> Abort authentication process!"); + handleErrorNoRedirect( + new EAAFException( + "auth.20", + null, + "PendingRequest is NOT authenticated --> Abort authentication process!" + ), req, resp, true); + + } + + } catch (Exception e) { + log.error("Finalize authentication protocol FAILED." , e); + buildProtocolSpecificErrorResponse(e, req, resp, pendingReq); + + if (pendingReq != null) + transactionStorage.remove(pendingReq.getPendingRequestId()); + + } + } + + //remove pending-request + if (pendingReq != null) { + requestStorage.removePendingRequest(pendingReq.getPendingRequestId()); + revisionsLogger.logEvent(EventConstants.TRANSACTION_DESTROYED, pendingReq.getUniqueTransactionIdentifier()); + + } + + } + +} 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 new file mode 100644 index 00000000..6a7f4440 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/protocols/RequestImpl.java @@ -0,0 +1,386 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eaaf.core.impl.idp.controller.protocols; + +import java.io.Serializable; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import javax.naming.ConfigurationException; +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.api.data.EAAFConstants; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EAAFAuthenticationException; +import at.gv.egiz.eaaf.core.exceptions.EAAFException; +import at.gv.egiz.eaaf.core.exceptions.EAAFStorageException; +import at.gv.egiz.eaaf.core.impl.utils.HTTPUtils; +import at.gv.egiz.eaaf.core.impl.utils.Random; +import at.gv.egiz.eaaf.core.impl.utils.TransactionIDUtils; + +public abstract class RequestImpl implements IRequest, Serializable{ + + private static final Logger log = LoggerFactory.getLogger(RequestImpl.class); + + public static final String DATAID_REQUESTER_IP_ADDRESS = "reqestImpl_requesterIPAddr"; + + private static final long serialVersionUID = 1L; + + private String module = null; + private String action = null; + + private String pendingRequestId; + private String processInstanceId; + private String ssoSessionId; + + private String uniqueTransactionIdentifer; + private String uniqueSessionIdentifer; + + private String requestedServiceProviderIdentifer; + private String idpAuthURL = null; + + private ISPConfiguration spConfiguration = null; + + private boolean passiv = false; + private boolean force = false; + private boolean isAbortedByUser = false; + + //every request needs authentication by default + private boolean needAuthentication = true; + + //every request is not authenticated by default + private boolean isAuthenticated = false; + + //every request needs no SSO by default + private boolean needSSO = false; + + private boolean needUserConsent = false; + + private Map genericDataStorage = new HashMap(); + + + + /** + * @throws ConfigurationException + * + */ + public final void initialize(HttpServletRequest req, IConfiguration authConfig) throws EAAFException { + //set pendingRequestId + pendingRequestId = Random.nextLongRandom(); + + //set unique transaction identifier for logging + uniqueTransactionIdentifer = Random.nextLongRandom(); + TransactionIDUtils.setTransactionId(uniqueTransactionIdentifer); + + //initialize session object + genericDataStorage.put(EAAFConstants.AUTH_DATA_CREATED, new Date()); + //genericDataStorage.put(EAAFConstants.VALUE_SESSIONID, Random.nextLongRandom()); + + //check if End-Point is valid + String authURLString = HTTPUtils.extractAuthURLFromRequest(req); + URL authReqURL; + try { + authReqURL = new URL(authURLString); + + } catch (MalformedURLException e) { + log.error("IDP AuthenticationServiceURL Prefix is not a valid URL." + authURLString, e); + throw new EAAFAuthenticationException("errorId", new Object[]{authURLString}, + "IDP AuthenticationServiceURL Prefix is not a valid URL.", e); + + } + this.idpAuthURL = authConfig.validateIDPURL(authReqURL); + if (this.idpAuthURL == null) { + log.warn("Extract AuthenticationServiceURL: " + authReqURL + " is NOT found in configuration."); + throw new EAAFAuthenticationException("errorId", new Object[]{authURLString}, + "Extract AuthenticationServiceURL: " + authReqURL + " is NOT found in configuration."); + + } + + //set unique session identifier + String uniqueID = (String) req.getAttribute(EAAFConstants.UNIQUESESSIONIDENTIFIER); + if (StringUtils.isNotEmpty(uniqueID)) + this.uniqueSessionIdentifer = uniqueID; + + else { + log.debug("Create new sessionIdentifier for this pendingRequest ... "); + this.uniqueSessionIdentifer = Random.nextLongRandom(); + + } + + //set requester's IP address + try { + setGenericDataToSession(DATAID_REQUESTER_IP_ADDRESS, req.getRemoteAddr()); + + } catch (EAAFStorageException e) { + log.info("Can NOT store remote IP address into 'pendingRequest'." , e); + + } + + } + +// /** +// * This method map the protocol specific requested attributes to PVP 2.1 attributes. +// * +// * @return List of PVP 2.1 attribute names with maps all protocol specific attributes +// */ +// public abstract Collection getRequestedAttributes(MetadataProvider metadataProvider); + + public final void setSPEntityId(String spIdentifier) { + this.requestedServiceProviderIdentifer = spIdentifier; + } + + public final String getSPEntityId() { + return this.requestedServiceProviderIdentifer; + } + + public final boolean isPassiv() { + return passiv; + } + + public final boolean forceAuth() { + return force; + } + + public final void setPassiv(boolean passiv) { + this.passiv = passiv; + } + + public final void setForce(boolean force) { + this.force = force; + } + + public final String requestedAction() { + return action; + } + + public final void setAction(String action) { + this.action = action; + } + + public final String requestedModule() { + return module; + } + + public final void setModule(String module) { + this.module = module; + } + + public final void setPendingRequestId(String pendingReqId) { + this.pendingRequestId = pendingReqId; + + } + + public final String getPendingRequestId() { + return pendingRequestId; + } + + public final String getSSOSessionIdentifier() { + return this.ssoSessionId; + } + + public final void setSSOSessionIdentifier(String internalSSOSessionId) { + this.ssoSessionId = internalSSOSessionId; + + } + + public final Map genericFullDataStorage() { + return this.genericDataStorage; + + } + + public final ISPConfiguration getServiceProviderConfiguration() { + return this.spConfiguration; + + + } + + public T getServiceProviderConfiguration(final Class decorator) { + if (this.spConfiguration != null) { + if (decorator.isAssignableFrom(this.spConfiguration.getClass())) { + return (T) this.spConfiguration; + + } else + log.error("Can not decorate SP configuration by '" + decorator.getName() + "'."); + throw new RuntimeException("Can not decorate SP configuration by '" + decorator.getName() + "'."); + + } + + return null; + + } + + public void setOnlineApplicationConfiguration(ISPConfiguration spConfig) { + this.spConfiguration = spConfig; + + } + + public final String getUniqueTransactionIdentifier() { + return this.uniqueTransactionIdentifer; + + } + + public final String getUniqueSessionIdentifier() { + return this.uniqueSessionIdentifer; + + } + + public final String getProcessInstanceId() { + return this.processInstanceId; + + } + + public final void setUniqueTransactionIdentifier(String id) { + this.uniqueTransactionIdentifer = id; + + } + + public final void setUniqueSessionIdentifier(String id) { + this.uniqueSessionIdentifer = id; + + } + + public void setProcessInstanceId(String id) { + this.processInstanceId = id; + + } + + public final String getAuthURL() { + return this.idpAuthURL; + } + + public final String getAuthURLWithOutSlash() { + if (this.idpAuthURL.endsWith("/")) + return this.idpAuthURL.substring(0, this.idpAuthURL.length()-1); + else + return this.idpAuthURL; + + } + + public final boolean isNeedAuthentication() { + return needAuthentication; + } + + public final void setNeedAuthentication(boolean needAuthentication) { + this.needAuthentication = needAuthentication; + } + + public final boolean isAuthenticated() { + return isAuthenticated; + } + + public final void setAuthenticated(boolean isAuthenticated) { + this.isAuthenticated = isAuthenticated; + } + + public final boolean needSingleSignOnFunctionality() { + return needSSO; + } + public final void setNeedSingleSignOnFunctionality(boolean needSSO) { + this.needSSO = needSSO; + + } + + public final boolean isNeedUserConsent() { + return this.needUserConsent; + + } + + public final void setNeedUserConsent(boolean needConsent) { + this.needUserConsent = needConsent; + + } + + public final boolean isAbortedByUser() { + return this.isAbortedByUser; + } + + public final void setAbortedByUser(boolean isAborted) { + this.isAbortedByUser = isAborted; + + } + + public final Object getGenericData(String key) { + if (StringUtils.isNotEmpty(key)) { + return genericDataStorage.get(key); + + } + + log.info("Can not load generic request-data with key='null'"); + return null; + } + + public final T getGenericData(String key, final Class clazz) { + if (StringUtils.isNotEmpty(key)) { + Object data = genericDataStorage.get(key); + + if (data == null) + return null; + + try { + @SuppressWarnings("unchecked") + T test = (T) data; + return test; + + } catch (Exception e) { + log.warn("Generic request-data object can not be casted to requested type", e); + return null; + + } + + } + + log.info("Can not load generic request-data with key='null'"); + return null; + + } + + @Override + public final void setGenericDataToSession(String key, Object object) throws EAAFStorageException { + if (StringUtils.isEmpty(key)) { + log.info("Generic request-data can not be stored with a 'null' key"); + throw new EAAFStorageException("Generic request-data can not be stored with a 'null' key", null); + + } + + if (object != null) { + if (!Serializable.class.isInstance(object)) { + log.warn("Generic request-data can only store objects which implements the 'Seralizable' interface"); + throw new EAAFStorageException("Generic request-data can only store objects which implements the 'Seralizable' interface", null); + + } + } + + if (genericDataStorage.containsKey(key)) + log.trace("Overwrite generic request-data with key:" + key); + else + log.trace("Add generic request-data with key:" + key + " to session."); + + genericDataStorage.put(key, object); + + } + + @Override + public final void setGenericDataToSession(Map map) throws EAAFStorageException { + if (map == null) { + log.info("Generic request-data can not be stored with a 'null' map"); + throw new EAAFStorageException("Generic request-data can not be stored with a 'null' map", null); + + } + + //validate and store values + for (Entry el : map.entrySet()) + setGenericDataToSession(el.getKey(), el.getValue()); + + } + +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/FinalizeAuthenticationTask.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/FinalizeAuthenticationTask.java new file mode 100644 index 00000000..4ab63503 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/FinalizeAuthenticationTask.java @@ -0,0 +1,57 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eaaf.core.impl.idp.controller.tasks; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import at.gv.egiz.eaaf.core.api.data.EAAFConstants; +import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; +import at.gv.egiz.eaaf.core.exceptions.EAAFException; +import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; +import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; + +/** + * @author tlenz + * + */ +@Component("FinalizeAuthenticationTask") +public class FinalizeAuthenticationTask extends AbstractAuthServletTask { + + private static final Logger log = LoggerFactory.getLogger(FinalizeAuthenticationTask.class); + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.process.springweb.MoaIdTask#execute(at.gv.egovernment.moa.id.process.api.ExecutionContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + public void execute(ExecutionContext executionContext, + HttpServletRequest request, HttpServletResponse response) + throws TaskExecutionException { + + try { + //set pending request to authenticated + pendingReq.setAuthenticated(true); + requestStoreage.storePendingRequest(pendingReq); + + log.info("AuthProcess finished. Redirect to Protocol Dispatcher."); + performRedirectToProtocolFinialization(pendingReq, response); + + } catch (EAAFException e) { + throw new TaskExecutionException(pendingReq, e.getMessage(), e); + + } catch (Exception e) { + log.warn("FinalizeAuthenticationTask has an internal error", e); + throw new TaskExecutionException(pendingReq, e.getMessage(), e); + + } finally { + executionContext.remove(EAAFConstants.PROCESS_ENGINE_PENDINGREQUESTID); + + } + + } + +} 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 new file mode 100644 index 00000000..2e5f49ed --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/idp/controller/tasks/RestartAuthProzessManagement.java @@ -0,0 +1,92 @@ +/******************************************************************************* + *******************************************************************************/ +package at.gv.egiz.eaaf.core.impl.idp.controller.tasks; + +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; +import at.gv.egiz.eaaf.core.api.idp.process.ProcessEngine; +import at.gv.egiz.eaaf.core.exceptions.EAAFException; +import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; +import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; +import at.gv.egiz.eaaf.core.impl.idp.auth.modules.ModuleRegistration; +import at.gv.egiz.eaaf.core.impl.idp.controller.protocols.RequestImpl; +import at.gv.egiz.eaaf.core.impl.idp.process.ExecutionContextImpl; + +/** + * @author tlenz + * + */ +@Component("RestartAuthProzessManagement") +public class RestartAuthProzessManagement extends AbstractAuthServletTask { + private static final Logger log = LoggerFactory.getLogger(RestartAuthProzessManagement.class); + + @Autowired ProcessEngine processEngine; + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.process.springweb.MoaIdTask#execute(at.gv.egovernment.moa.id.process.api.ExecutionContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) + throws TaskExecutionException { + try { + //create a new execution context and copy all elements to new context + ExecutionContext newec = new ExecutionContextImpl(); + Set entries = executionContext.keySet(); + for (String key : entries) { + newec.put(key, executionContext.get(key)); + + } + + log.debug("Select new auth.-process and restart restart process-engine ... "); + + // select and create new process instance + String processDefinitionId = ModuleRegistration.getInstance().selectProcess(newec); + if (processDefinitionId == null) { + log.warn("No suitable authentication process found for SessionID " + pendingReq.getPendingRequestId()); + throw new EAAFException("process.02", new Object[] { pendingReq.getPendingRequestId()}, + "No suitable authentication process found for SessionID \" + pendingReq.getPendingRequestId()"); + } + + String processInstanceId = processEngine.createProcessInstance(processDefinitionId, newec); + + // keep process instance id in moa session + ((RequestImpl)pendingReq).setProcessInstanceId(processInstanceId); + + // make sure pending request has been persisted before running the process + try { + requestStoreage.storePendingRequest(pendingReq); + + } catch (EAAFException e) { + log.error("Database Error! MOASession is not stored!"); + throw new EAAFException("init.04", new Object[] { pendingReq.getPendingRequestId() }, + "Database Error! MOASession is not stored!"); + + } + + log.info("Restart process-engine with auth.process:" + processDefinitionId); + + // start process + processEngine.start(pendingReq); + + + } catch (EAAFException e) { + throw new TaskExecutionException(pendingReq, e.getMessage(), e); + + } catch (Exception e) { + log.warn("RestartAuthProzessManagement has an internal error", e); + throw new TaskExecutionException(pendingReq, e.getMessage(), e); + + } + + } + +} -- cgit v1.2.3