/******************************************************************************* *******************************************************************************/ 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); } } }