diff options
Diffstat (limited to 'id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java')
-rw-r--r-- | id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java | 876 |
1 files changed, 356 insertions, 520 deletions
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java index c38bbc68f..22561e435 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java @@ -23,9 +23,6 @@ package at.gv.egovernment.moa.id.moduls; import java.io.IOException; -import java.io.PrintWriter; -import java.lang.reflect.InvocationTargetException; -import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Collection; import java.util.Enumeration; @@ -37,148 +34,406 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.commons.lang.StringEscapeUtils; import org.apache.velocity.VelocityContext; -import org.joda.time.DateTime; -import org.opensaml.common.impl.SecureRandomIdentifierGenerator; -import org.opensaml.common.xml.SAMLConstants; -import org.opensaml.saml2.core.AuthnContextClassRef; -import org.opensaml.saml2.core.AuthnContextComparisonTypeEnumeration; -import org.opensaml.saml2.core.AuthnRequest; -import org.opensaml.saml2.core.Issuer; import org.opensaml.saml2.core.LogoutRequest; import org.opensaml.saml2.core.LogoutResponse; -import org.opensaml.saml2.core.NameID; -import org.opensaml.saml2.core.NameIDPolicy; -import org.opensaml.saml2.core.NameIDType; -import org.opensaml.saml2.core.RequestedAuthnContext; import org.opensaml.saml2.core.StatusCode; -import org.opensaml.saml2.metadata.EntityDescriptor; import org.opensaml.saml2.metadata.SingleLogoutService; -import org.opensaml.saml2.metadata.SingleSignOnService; -import org.opensaml.saml2.metadata.provider.MetadataProviderException; -import org.opensaml.ws.message.encoder.MessageEncodingException; import org.opensaml.ws.soap.common.SOAPException; import org.opensaml.xml.XMLObject; import org.opensaml.xml.security.SecurityException; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; import at.gv.egovernment.moa.id.advancedlogging.MOAReversionLogger; import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; -import at.gv.egovernment.moa.id.auth.builder.LoginFormBuilder; -import at.gv.egovernment.moa.id.auth.builder.SendAssertionFormBuilder; import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionExtensions; -import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; -import at.gv.egovernment.moa.id.auth.exception.BuildException; import at.gv.egovernment.moa.id.auth.exception.InvalidProtocolRequestException; import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.auth.modules.SingleSignOnConsentsModuleImpl; import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; import at.gv.egovernment.moa.id.auth.modules.registration.ModuleRegistration; import at.gv.egovernment.moa.id.commons.db.dao.session.InterfederationSessionStore; import at.gv.egovernment.moa.id.commons.db.dao.session.OASessionStore; import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; -import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; -import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; +import at.gv.egovernment.moa.id.config.auth.AuthConfiguration; +import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters; import at.gv.egovernment.moa.id.data.SLOInformationContainer; import at.gv.egovernment.moa.id.data.SLOInformationImpl; import at.gv.egovernment.moa.id.process.ExecutionContextImpl; import at.gv.egovernment.moa.id.process.ProcessEngine; import at.gv.egovernment.moa.id.process.ProcessExecutionException; import at.gv.egovernment.moa.id.process.api.ExecutionContext; -import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; import at.gv.egovernment.moa.id.protocols.pvp2x.PVPTargetConfiguration; -import at.gv.egovernment.moa.id.protocols.pvp2x.binding.IEncoder; -import at.gv.egovernment.moa.id.protocols.pvp2x.binding.PostBinding; -import at.gv.egovernment.moa.id.protocols.pvp2x.binding.RedirectBinding; import at.gv.egovernment.moa.id.protocols.pvp2x.builder.SingleLogOutBuilder; -import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration; import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest; -import at.gv.egovernment.moa.id.protocols.pvp2x.metadata.MOAMetadataProvider; import at.gv.egovernment.moa.id.protocols.pvp2x.utils.MOASAMLSOAPClient; -import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils; import at.gv.egovernment.moa.id.protocols.pvp2x.verification.SAMLVerificationEngine; import at.gv.egovernment.moa.id.protocols.pvp2x.verification.TrustEngineFactory; -import at.gv.egovernment.moa.id.storage.AssertionStorage; -import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage; +import at.gv.egovernment.moa.id.storage.IAuthenticationSessionStoreage; +import at.gv.egovernment.moa.id.storage.ITransactionStorage; import at.gv.egovernment.moa.id.util.MOAIDMessageProvider; -import at.gv.egovernment.moa.id.util.PVPtoSTORKMapper; import at.gv.egovernment.moa.id.util.ParamValidatorUtils; import at.gv.egovernment.moa.id.util.Random; +import at.gv.egovernment.moa.id.util.legacy.LegacyHelper; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; +@Service("MOAID_AuthenticationManager") public class AuthenticationManager extends MOAIDAuthConstants { - private static final AuthenticationManager INSTANCE = new AuthenticationManager(); public static final String MOA_SESSION = "MoaAuthenticationSession"; public static final String MOA_AUTHENTICATED = "MoaAuthenticated"; public static final int SLOTIMEOUT = 30 * 1000; //30 sec - @Autowired - private ProcessEngine processEngine; - - private AuthenticationManager() { + @Autowired private ProcessEngine processEngine; + @Autowired private SSOManager ssoManager; + @Autowired private IRequestStorage requestStoreage; + @Autowired private ITransactionStorage transactionStorage; + @Autowired private IAuthenticationSessionStoreage authenticatedSessionStore; + @Autowired private MOAReversionLogger revisionsLogger; + @Autowired protected AuthConfiguration authConfig; + @Autowired private SingleLogOutBuilder sloBuilder; + @Autowired private SAMLVerificationEngine samlVerificationEngine; + + public void performSingleLogOut(HttpServletRequest httpReq, + HttpServletResponse httpResp, AuthenticationSession session, PVPTargetConfiguration pvpReq) throws MOAIDException { + performSingleLogOut(httpReq, httpResp, session, pvpReq, null); + } - public static AuthenticationManager getInstance() { - return INSTANCE; + public void performSingleLogOut(HttpServletRequest httpReq, + HttpServletResponse httpResp, AuthenticationSession session, String authURL) throws MOAIDException { + performSingleLogOut(httpReq, httpResp, session, null, authURL); + } + public void performOnlyIDPLogOut(HttpServletRequest request, + HttpServletResponse response, String moaSessionID) { + Logger.info("Logout"); + + if(moaSessionID == null) { + moaSessionID = (String) request.getParameter(PARAM_SESSIONID); + } + + if(moaSessionID == null) { + Logger.info("NO MOA Session to logout"); + return; + } + + AuthenticationSession authSession; + try { + authSession = authenticatedSessionStore.getSession(moaSessionID); + + if(authSession == null) { + Logger.info("NO MOA Authentication data for ID " + moaSessionID); + return; + } + + authSession.setAuthenticated(false); + //HTTPSessionUtils.setHTTPSessionString(session, MOA_SESSION, null); // remove moa session from HTTP Session + + //log Session_Destroy to reversionslog + AuthenticationSessionExtensions sessionExtensions = authenticatedSessionStore.getAuthenticationSessionExtensions(moaSessionID); + revisionsLogger.logEvent(MOAIDEventConstants.SESSION_DESTROYED, sessionExtensions.getUniqueSessionId()); + + authenticatedSessionStore.destroySession(moaSessionID); + + //session.invalidate(); + + } catch (MOADatabaseException e) { + Logger.info("NO MOA Authentication data for ID " + moaSessionID); + return; + } + + } + + /** - * Checks if this request can authenticate a MOA Session + * Authenticates the authentication request {pendingReq}, which is actually processed + * + * @param httpReq HttpServletRequest + * @param httpResp HttpServletResponse + * @param protocolRequest Authentication request which is actually in process + * + * @return Return already authenticated MOASession if exists, otherwise return null + * @throws MOADatabaseException + * @throws MOAIDException + * @throws IOException + * @throws ServletException * - * @param request - * @param response - * @return */ - public boolean tryPerformAuthentication(HttpServletRequest request, - HttpServletResponse response) { + public AuthenticationSession doAuthentication(HttpServletRequest httpReq, + HttpServletResponse httpResp, RequestImpl pendingReq) throws MOADatabaseException, ServletException, IOException, MOAIDException { + + //generic authentication request validation + if (pendingReq.isPassiv() + && pendingReq.forceAuth()) { + // conflict! + throw new NoPassivAuthenticationException(); + } - String sessionID = (String) request.getParameter(PARAM_SESSIONID); - if (sessionID != null) { - Logger.debug("Find MOASession: " + sessionID); - AuthenticationSession authSession; - try { - authSession = AuthenticationSessionStoreage.getSession(sessionID); - - if (authSession != null) { - Logger.info("MOASession found! A: " - + authSession.isAuthenticated() + ", AU " - + authSession.isAuthenticatedUsed()); - if (authSession.isAuthenticated() - && !authSession.isAuthenticatedUsed()) { - authSession.setAuthenticatedUsed(true); - - AuthenticationSessionStoreage.storeSession(authSession); - - return true; // got authenticated - } - } + //get SSO cookie from http request + String ssoId = ssoManager.getSSOSessionID(httpReq); + + //check if interfederation IDP is requested + ssoManager.checkInterfederationIsRequested(httpReq, httpResp, pendingReq); + + //check if SSO session cookie is already used + if (ssoId != null) { + String correspondingMOASession = ssoManager.existsOldSSOSession(ssoId); - } catch (MOADatabaseException e) { - return false; - } catch (BuildException e) { + if (correspondingMOASession != null) { + Logger.warn("Request sends an old SSO Session ID("+ssoId+")! " + + "Invalidate the corresponding MOASession with ID="+ correspondingMOASession); + + revisionsLogger.logEvent(pendingReq.getOnlineApplicationConfiguration(), + pendingReq, MOAIDEventConstants.AUTHPROCESS_SSO_INVALID); + + authenticatedSessionStore.destroySession(correspondingMOASession); + ssoManager.deleteSSOSessionID(httpReq, httpResp); + } + } + + //check if SSO Session is valid + boolean isValidSSOSession = ssoManager.isValidSSOSession(ssoId, pendingReq); + + // check if Service-Provider allows SSO sessions + IOAAuthParameters oaParam = pendingReq.getOnlineApplicationConfiguration(); + boolean useSSOOA = oaParam.useSSO() || oaParam.isInderfederationIDP(); + + revisionsLogger.logEvent(oaParam, + pendingReq, MOAIDEventConstants.AUTHPROCESS_SERVICEPROVIDER, pendingReq.getOAURL()); + + //if a legacy request is used SSO should not be allowed in case of mandate authentication + boolean isUseMandateRequested = LegacyHelper.isUseMandateRequested(httpReq); + + //check if SSO is allowed for the actually executed request + //INFO: Actually, useMandate disables SSO functionality!!!!! + boolean isSSOAllowed = (useSSOOA && !isUseMandateRequested); + pendingReq.setNeedSingleSignOnFunctionality(isSSOAllowed); + + //get MOASession from SSO-Cookie if SSO is allowed + AuthenticationSession moaSession = null; + if (isValidSSOSession && isSSOAllowed) { + String moasessionID = ssoManager.getMOASession(ssoId); + moaSession = authenticatedSessionStore.getSession(moasessionID); + + if (moaSession == null) + Logger.info("No MOASession FOUND with provided SSO-Cookie."); + + else { + Logger.debug("Found authenticated MOASession with provided SSO-Cookie."); + revisionsLogger.logEvent(oaParam, pendingReq, MOAIDEventConstants.AUTHPROCESS_SSO); + + } + } + + //check if session is already authenticated + boolean isSessionAuthenticated = tryPerformAuthentication((RequestImpl) pendingReq, moaSession); + + //force new authentication authentication process + if (pendingReq.forceAuth()) { + startAuthenticationProcess(httpReq, httpResp, pendingReq); + return null; + + //perform SSO-Consents evaluation if it it required + } else if (isSessionAuthenticated && oaParam.useSSOQuestion()) { + sendSingleSignOnConsentsEvaluation(httpReq, httpResp, pendingReq); + return null; + + } else if (pendingReq.isPassiv()) { + if (isSessionAuthenticated) { + // Passive authentication ok! + revisionsLogger.logEvent(oaParam, pendingReq, MOAIDEventConstants.AUTHPROCESS_FINISHED); + return moaSession; + + } else { + throw new NoPassivAuthenticationException(); + + } + } else { + if (isSessionAuthenticated) { + // Is authenticated .. proceed + revisionsLogger.logEvent(oaParam, + pendingReq, MOAIDEventConstants.AUTHPROCESS_FINISHED); + return moaSession; + + } else { + // Start authentication! + startAuthenticationProcess(httpReq, httpResp, pendingReq); + return null; + } + } + } + + /** + * Checks if a authenticated MOASession already exists and if {protocolRequest} is authenticated + * + * @param protocolRequest Authentication request which is actually in process + * @param moaSession MOASession with authentication information or null if no active MOASession exists + * + * @return true if session is already authenticated, otherwise false + * @throws MOAIDException + */ + private boolean tryPerformAuthentication(RequestImpl protocolRequest, AuthenticationSession moaSession) { + + //if no MOASession exist -> authentication is required + if (moaSession == null) { + return false; + + } else { + //if MOASession is Found but not authenticated --> authentication is required + if (!moaSession.isAuthenticated()) { return false; } + + //if MOASession is already authenticated and protocol-request is authenticated + // --> no authentication is required any more + else if (moaSession.isAuthenticated() && protocolRequest.isAuthenticated()) { + return true; + + // if MOASession is authenticated and SSO is allowed --> authenticate pendingRequest + } else if (!protocolRequest.isAuthenticated() + && moaSession.isAuthenticated() && protocolRequest.needSingleSignOnFunctionality()) { + Logger.debug("Found active MOASession and SSO is allowed --> pendingRequest is authenticted"); + protocolRequest.setAuthenticated(true); + protocolRequest.setMOASessionIdentifier(moaSession.getSessionID()); + return true; + + } + + // force authentication as backup solution + else { + Logger.warn("Authentication-required check find an unsuspected state --> force authentication"); + return false; + + } } - return false; } - public void performSingleLogOut(HttpServletRequest httpReq, - HttpServletResponse httpResp, AuthenticationSession session, PVPTargetConfiguration pvpReq) throws MOAIDException { - performSingleLogOut(httpReq, httpResp, session, pvpReq, null); + private void startAuthenticationProcess(HttpServletRequest httpReq, + HttpServletResponse httpResp, RequestImpl pendingReq) + throws ServletException, IOException, MOAIDException { + + Logger.info("Starting authentication ..."); + revisionsLogger.logEvent(pendingReq.getOnlineApplicationConfiguration(), + pendingReq, MOAIDEventConstants.AUTHPROCESS_START); + + //is legacy allowed + List<String> legacyallowed_prot = authConfig.getLegacyAllowedProtocols(); + boolean legacyallowed = legacyallowed_prot.contains(pendingReq.requestedModule()); + + //check legacy request parameter + boolean legacyparamavail = ParamValidatorUtils.areAllLegacyParametersAvailable(httpReq); + + //create MOASession object + AuthenticationSession moasession; + try { + moasession = authenticatedSessionStore.createSession(pendingReq); + pendingReq.setMOASessionIdentifier(moasession.getSessionID()); + + } catch (MOADatabaseException e1) { + Logger.error("Database Error! MOASession can not be created!"); + throw new MOAIDException("init.04", new Object[] {}); + + } + + //create authentication process execution context + ExecutionContext executionContext = new ExecutionContextImpl(); + + //set interfederation authentication flag + executionContext.put(MOAIDAuthConstants.PROCESSCONTEXT_PERFORM_INTERFEDERATION_AUTH, + MiscUtil.isNotEmpty( + pendingReq.getGenericData(RequestImpl.DATAID_INTERFEDERATIOIDP_URL, String.class))); + + //set legacy mode or BKU-selection flags + boolean leagacyMode = (legacyallowed && legacyparamavail); + executionContext.put(MOAIDAuthConstants.PROCESSCONTEXT_ISLEGACYREQUEST, leagacyMode); + executionContext.put(MOAIDAuthConstants.PROCESSCONTEXT_PERFORM_BKUSELECTION, !leagacyMode + && MiscUtil.isEmpty(pendingReq.getGenericData(RequestImpl.DATAID_INTERFEDERATIOIDP_URL, String.class))); + + //add leagcy parameters to context + if (leagacyMode) { + Enumeration<String> reqParamNames = httpReq.getParameterNames(); + while(reqParamNames.hasMoreElements()) { + String paramName = reqParamNames.nextElement(); + if (MiscUtil.isNotEmpty(paramName) && + MOAIDAuthConstants.LEGACYPARAMETERWHITELIST.contains(paramName)) + executionContext.put(paramName, + StringEscapeUtils.escapeHtml(httpReq.getParameter(paramName))); + + } + } + + //start process engine + startProcessEngine(pendingReq, executionContext); } - - public void performSingleLogOut(HttpServletRequest httpReq, - HttpServletResponse httpResp, AuthenticationSession session, String authURL) throws MOAIDException { - performSingleLogOut(httpReq, httpResp, session, null, authURL); + + private void sendSingleSignOnConsentsEvaluation(HttpServletRequest request, + HttpServletResponse response, RequestImpl pendingReq) + throws ServletException, IOException, MOAIDException { + + Logger.info("Start SSO user-consents evaluation ..."); + //set authenticated flag to false, because user consents is required + pendingReq.setAuthenticated(false); + + //create execution context + ExecutionContext executionContext = new ExecutionContextImpl(); + executionContext.put(SingleSignOnConsentsModuleImpl.PARAM_SSO_CONSENTS_EVALUATION, true); + + //start process engine + startProcessEngine(pendingReq, executionContext); + } + private void startProcessEngine(RequestImpl pendingReq, ExecutionContext executionContext) throws MOAIDException { + try { + //put pending-request ID on execurtionContext + executionContext.put(MOAIDAuthConstants.PARAM_TARGET_PENDINGREQUESTID, pendingReq.getRequestID()); + + // create process instance + String processDefinitionId = ModuleRegistration.getInstance().selectProcess(executionContext); + + if (processDefinitionId == null) { + Logger.warn("No suitable process found for SessionID " + pendingReq.getRequestID() ); + throw new MOAIDException("process.02",new Object[] { + pendingReq.getRequestID()}); + } + + String processInstanceId = processEngine.createProcessInstance(processDefinitionId, executionContext); + + // keep process instance id in protocol pending-request + pendingReq.setProcessInstanceId(processInstanceId); + + //store pending-request + requestStoreage.storePendingRequest(pendingReq); + + // start process + processEngine.start(pendingReq); + + } catch (ProcessExecutionException e) { + Throwable cause = e.getCause(); + if (cause != null && cause instanceof TaskExecutionException) { + Throwable taskCause = cause.getCause(); + if (taskCause != null && taskCause instanceof MOAIDException) { + MOAIDException moaTaskCause = (MOAIDException) taskCause; + Logger.warn(taskCause); + throw moaTaskCause; + + } + } + + throw new MOAIDException("process.01", new Object[] { pendingReq.getProcessInstanceId(), pendingReq.getRequestID() }, e); + } + } private void performSingleLogOut(HttpServletRequest httpReq, HttpServletResponse httpResp, AuthenticationSession session, PVPTargetConfiguration pvpReq, String authURL) throws MOAIDException { @@ -193,20 +448,18 @@ public class AuthenticationManager extends MOAIDAuthConstants { } - SSOManager ssomanager = SSOManager.getInstance(); - //store active OAs to SLOContaine - List<OASessionStore> dbOAs = AuthenticationSessionStoreage.getAllActiveOAFromMOASession(session); - List<InterfederationSessionStore> dbIDPs = AuthenticationSessionStoreage.getAllActiveIDPsFromMOASession(session); + List<OASessionStore> dbOAs = authenticatedSessionStore.getAllActiveOAFromMOASession(session); + List<InterfederationSessionStore> dbIDPs = authenticatedSessionStore.getAllActiveIDPsFromMOASession(session); SLOInformationContainer sloContainer = new SLOInformationContainer(); - sloContainer.setSloRequest(pvpReq); - sloContainer.parseActiveIDPs(dbIDPs, pvpSLOIssuer); - sloContainer.parseActiveOAs(dbOAs, pvpSLOIssuer); + sloContainer.setSloRequest(pvpReq); + sloBuilder.parseActiveIDPs(sloContainer, dbIDPs, pvpSLOIssuer); + sloBuilder.parseActiveOAs(sloContainer, dbOAs, pvpSLOIssuer); //terminate MOASession try { - AuthenticationSessionStoreage.destroySession(session.getSessionID()); - ssomanager.deleteSSOSessionID(httpReq, httpResp); + authenticatedSessionStore.destroySession(session.getSessionID()); + ssoManager.deleteSSOSessionID(httpReq, httpResp); } catch (MOADatabaseException e) { Logger.warn("Delete MOASession FAILED."); @@ -218,7 +471,7 @@ public class AuthenticationManager extends MOAIDAuthConstants { Iterator<String> nextOAInterator = sloContainer.getNextBackChannelOA(); while (nextOAInterator.hasNext()) { SLOInformationImpl sloDescr = sloContainer.getBackChannelOASessionDescripten(nextOAInterator.next()); - LogoutRequest sloReq = SingleLogOutBuilder.buildSLORequestMessage(sloDescr); + LogoutRequest sloReq = sloBuilder.buildSLORequestMessage(sloDescr); try { List<XMLObject> soapResp = MOASAMLSOAPClient.send(sloDescr.getServiceURL(), sloReq); @@ -235,13 +488,12 @@ public class AuthenticationManager extends MOAIDAuthConstants { sloContainer.putFailedOA(sloReq.getIssuer().getValue()); } else { - SAMLVerificationEngine engine = new SAMLVerificationEngine(); - engine.verifySLOResponse(sloResp, + samlVerificationEngine.verifySLOResponse(sloResp, TrustEngineFactory.getSignatureKnownKeysTrustEngine()); } - SingleLogOutBuilder.checkStatusCode(sloContainer, sloResp); + sloBuilder.checkStatusCode(sloContainer, sloResp); } catch (SOAPException e) { Logger.warn("Single LogOut for OA " + sloReq.getIssuer().getValue() @@ -264,9 +516,9 @@ public class AuthenticationManager extends MOAIDAuthConstants { Collection<Entry<String, SLOInformationImpl>> sloDescr = sloContainer.getFrontChannelOASessionDescriptions(); List<String> sloReqList = new ArrayList<String>(); for (Entry<String, SLOInformationImpl> el : sloDescr) { - LogoutRequest sloReq = SingleLogOutBuilder.buildSLORequestMessage(el.getValue()); + LogoutRequest sloReq = sloBuilder.buildSLORequestMessage(el.getValue()); try { - sloReqList.add(SingleLogOutBuilder.getFrontChannelSLOMessageURL(el.getValue().getServiceURL(), el.getValue().getBinding(), + sloReqList.add(sloBuilder.getFrontChannelSLOMessageURL(el.getValue().getServiceURL(), el.getValue().getBinding(), sloReq, httpReq, httpResp, relayState)); } catch (Exception e) { @@ -276,7 +528,8 @@ public class AuthenticationManager extends MOAIDAuthConstants { } } - AssertionStorage.getInstance().put(relayState, sloContainer); + //put SLO process-information into transaction storage + transactionStorage.put(relayState, sloContainer); if (MiscUtil.isEmpty(authURL)) authURL = pvpReq.getAuthURL(); @@ -289,15 +542,15 @@ public class AuthenticationManager extends MOAIDAuthConstants { context.put("redirectURLs", sloReqList); context.put("timeoutURL", timeOutURL); context.put("timeout", SLOTIMEOUT); - ssomanager.printSingleLogOutInfo(context, httpResp); + ssoManager.printSingleLogOutInfo(context, httpResp); } else { if (pvpReq != null) { //send SLO response to SLO request issuer - SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(pvpReq); - LogoutResponse message = SingleLogOutBuilder.buildSLOResponseMessage(sloService, pvpReq, sloContainer.getSloFailedOAs()); - SingleLogOutBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, inboundRelayState); + SingleLogoutService sloService = sloBuilder.getResponseSLODescriptor(pvpReq); + LogoutResponse message = sloBuilder.buildSLOResponseMessage(sloService, pvpReq, sloContainer.getSloFailedOAs()); + sloBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, inboundRelayState); } else { //print SLO information directly @@ -309,7 +562,7 @@ public class AuthenticationManager extends MOAIDAuthConstants { else context.put("errorMsg", MOAIDMessageProvider.getInstance().getMessage("slo.01", null)); - ssomanager.printSingleLogOutInfo(context, httpResp); + ssoManager.printSingleLogOutInfo(context, httpResp); } @@ -318,16 +571,16 @@ public class AuthenticationManager extends MOAIDAuthConstants { } catch (MOADatabaseException e) { Logger.error("MOA AssertionDatabase ERROR", e); if (pvpReq != null) { - SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(pvpReq); - LogoutResponse message = SingleLogOutBuilder.buildSLOErrorResponse(sloService, pvpReq, StatusCode.RESPONDER_URI); - SingleLogOutBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, inboundRelayState); + SingleLogoutService sloService = sloBuilder.getResponseSLODescriptor(pvpReq); + LogoutResponse message = sloBuilder.buildSLOErrorResponse(sloService, pvpReq, StatusCode.RESPONDER_URI); + sloBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, inboundRelayState); }else { //print SLO information directly VelocityContext context = new VelocityContext(); context.put("errorMsg", MOAIDMessageProvider.getInstance().getMessage("slo.01", null)); - ssomanager.printSingleLogOutInfo(context, httpResp); + ssoManager.printSingleLogOutInfo(context, httpResp); } @@ -336,421 +589,4 @@ public class AuthenticationManager extends MOAIDAuthConstants { e.printStackTrace(); } } - - public void performOnlyIDPLogOut(HttpServletRequest request, - HttpServletResponse response, String moaSessionID) { - Logger.info("Logout"); - - if(moaSessionID == null) { - moaSessionID = (String) request.getParameter(PARAM_SESSIONID); - } - - if(moaSessionID == null) { - Logger.info("NO MOA Session to logout"); - return; - } - - AuthenticationSession authSession; - try { - authSession = AuthenticationSessionStoreage - .getSession(moaSessionID); - - if(authSession == null) { - Logger.info("NO MOA Authentication data for ID " + moaSessionID); - return; - } - - authSession.setAuthenticated(false); - //HTTPSessionUtils.setHTTPSessionString(session, MOA_SESSION, null); // remove moa session from HTTP Session - - //log Session_Destroy to reversionslog - AuthenticationSessionExtensions sessionExtensions = AuthenticationSessionStoreage.getAuthenticationSessionExtensions(moaSessionID); - MOAReversionLogger.getInstance().logEvent(MOAIDEventConstants.SESSION_DESTROYED, sessionExtensions.getUniqueSessionId()); - - AuthenticationSessionStoreage.destroySession(moaSessionID); - - //session.invalidate(); - - } catch (MOADatabaseException e) { - Logger.info("NO MOA Authentication data for ID " + moaSessionID); - return; - } - - } - - public void doAuthentication(HttpServletRequest request, - HttpServletResponse response, IRequest target) - throws ServletException, IOException, MOAIDException { - - Logger.info("Starting authentication ..."); - MOAReversionLogger.getInstance().logEvent(target.getOnlineApplicationConfiguration(), - target, MOAIDEventConstants.AUTHPROCESS_START); - - if (MiscUtil.isEmpty(target.getRequestedIDP())) { - perfomLocalAuthentication(request, response, target); - - } else { - Logger.info("Use IDP " + target.getRequestedIDP() + " for authentication ..."); - MOAReversionLogger.getInstance().logEvent(target.getOnlineApplicationConfiguration(), - target, MOAIDEventConstants.AUTHPROCESS_INTERFEDERATION); - buildPVP21AuthenticationRequest(request, response, target); - - } - } - - public void sendTransmitAssertionQuestion(HttpServletRequest request, - HttpServletResponse response, IRequest target, OAAuthParameter oaParam) - throws ServletException, IOException, MOAIDException { - - String form = SendAssertionFormBuilder.buildForm(target.requestedModule(), - target.requestedAction(), target.getRequestID(), oaParam, - target.getAuthURL()); - - MOAReversionLogger.getInstance().logEvent(target.getOnlineApplicationConfiguration(), - target, MOAIDEventConstants.AUTHPROCESS_SSO_ASK_USER_START); - - response.setContentType("text/html;charset=UTF-8"); - PrintWriter out = new PrintWriter(response.getOutputStream()); - out.print(form); - out.flush(); - } - - private void buildPVP21AuthenticationRequest(HttpServletRequest request, - HttpServletResponse response, IRequest target) - throws ServletException, IOException, MOAIDException { - - boolean requiredLocalAuthentication = true; - - Logger.debug("Build PVP 2.1 authentication request"); - - //get IDP metadata - - OAAuthParameter idp = AuthConfigurationProviderFactory.getInstance().getOnlineApplicationParameter(target.getRequestedIDP()); - OAAuthParameter sp = AuthConfigurationProviderFactory.getInstance().getOnlineApplicationParameter(target.getOAURL()); - - if (!idp.isInderfederationIDP() || !idp.isInboundSSOInterfederationAllowed()) { - Logger.info("Requested interfederation IDP " + target.getRequestedIDP() + " is not valid for interfederation."); - Logger.debug("isInderfederationIDP:" + String.valueOf(idp.isInderfederationIDP()) - + " isInboundSSOAllowed:" + String.valueOf(idp.isInboundSSOInterfederationAllowed())); - Logger.info("Switch to local authentication on this IDP ... "); - - perfomLocalAuthentication(request, response, target); - return; - - } - - try { - EntityDescriptor idpEntity = MOAMetadataProvider.getInstance(). - getEntityDescriptor(target.getRequestedIDP()); - - if (idpEntity != null ) { - - //fetch endpoint from IDP metadata - SingleSignOnService redirectEndpoint = null; - for (SingleSignOnService sss : - idpEntity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS).getSingleSignOnServices()) { - - // use POST binding as default if it exists - //TODO: maybe use RedirectBinding as default - if (sss.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) { - redirectEndpoint = sss; - - } else if ( sss.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI) && - redirectEndpoint == null ) - redirectEndpoint = sss; - } - - if (redirectEndpoint != null) { - - AuthnRequest authReq = SAML2Utils - .createSAMLObject(AuthnRequest.class); - SecureRandomIdentifierGenerator gen = new SecureRandomIdentifierGenerator(); - authReq.setID(gen.generateIdentifier()); - - //send passive AuthnRequest - authReq.setIsPassive(idp.isPassivRequestUsedForInterfederation()); - - authReq.setAssertionConsumerServiceIndex(0); - authReq.setIssueInstant(new DateTime()); - Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class); - String serviceURL = PVPConfiguration.getInstance().getIDPPublicPath().get(0); - issuer.setValue(serviceURL); - - issuer.setFormat(NameIDType.ENTITY); - authReq.setIssuer(issuer); - NameIDPolicy policy = SAML2Utils - .createSAMLObject(NameIDPolicy.class); - policy.setAllowCreate(true); - policy.setFormat(NameID.TRANSIENT); - authReq.setNameIDPolicy(policy); - - authReq.setDestination(redirectEndpoint.getLocation()); - - RequestedAuthnContext reqAuthContext = - SAML2Utils.createSAMLObject(RequestedAuthnContext.class); - - AuthnContextClassRef authnClassRef = - SAML2Utils.createSAMLObject(AuthnContextClassRef.class); - - //check if STORK protocol module is in ClassPath - Class<?> storkRequstTemplate = null; - Integer storkSecClass = null; - try { - storkRequstTemplate = Class.forName("at.gv.egovernment.moa.id.protocols.stork2.MOASTORKRequest"); - if (storkRequstTemplate != null && - storkRequstTemplate.isInstance(target)) { - Object storkAuthnRequest = target.getClass().getMethod("getStorkAuthnRequest", null).invoke(target, null); - storkSecClass = (Integer) storkAuthnRequest.getClass().getMethod("getQaa", null).invoke(storkAuthnRequest, null); - - } - - } catch (ClassNotFoundException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | java.lang.SecurityException ex) { - - - } - - if (sp != null && sp.isSTORKPVPGateway()) { - //use PVP SecClass instead of STORK QAA level - String secClass = null; - if (storkRequstTemplate != null && - storkRequstTemplate.isInstance(target)) { - - try { - secClass = PVPtoSTORKMapper.getInstance().mapToSecClass( - PVPConstants.STORK_QAA_PREFIX + String.valueOf(storkSecClass)); - - } catch (Exception e) { - Logger.warn("STORK-QAA level can not read from STORK request. Use default QAA 4", e); - - } - } - - if (MiscUtil.isNotEmpty(secClass)) - authnClassRef.setAuthnContextClassRef(secClass); - else - authnClassRef.setAuthnContextClassRef("http://www.ref.gv.at/ns/names/agiz/pvp/secclass/0-3"); - - } else { - if (storkRequstTemplate != null && - storkRequstTemplate.isInstance(target)) { - //use requested QAA level from STORK request - try { - authnClassRef.setAuthnContextClassRef( - PVPConstants.STORK_QAA_PREFIX + String.valueOf(storkSecClass)); - Logger.debug("Use STORK-QAA level " + authnClassRef.getAuthnContextClassRef() - + " from STORK request"); - - } catch (Exception e) { - Logger.warn("STORK-QAA level can not read from STORK request. Use default QAA 4", e); - - } - - } - - if (MiscUtil.isEmpty(authnClassRef.getAuthnContextClassRef())) - //TODO: switch to eIDAS QAA-levels - authnClassRef.setAuthnContextClassRef("http://www.stork.gov.eu/1.0/citizenQAALevel/4"); - - } - - reqAuthContext.setComparison(AuthnContextComparisonTypeEnumeration.MINIMUM); - reqAuthContext.getAuthnContextClassRefs().add(authnClassRef); - authReq.setRequestedAuthnContext(reqAuthContext); - - IEncoder binding = null; - if (redirectEndpoint.getBinding().equals( - SAMLConstants.SAML2_REDIRECT_BINDING_URI)) { - binding = new RedirectBinding(); - - } else if (redirectEndpoint.getBinding().equals( - SAMLConstants.SAML2_POST_BINDING_URI)) { - binding = new PostBinding(); - - } - - binding.encodeRequest(request, response, authReq, - redirectEndpoint.getLocation(), target.getRequestID()); - - //build and send request without an error - requiredLocalAuthentication = false; - - MOAReversionLogger.getInstance().logEvent(target.getOnlineApplicationConfiguration(), - target, MOAIDEventConstants.AUTHPROCESS_INTERFEDERATION_IDP, idpEntity.getEntityID()); - - - } else { - Logger.warn("Requested IDP " + target.getRequestedIDP() - + " does not support POST or Redirect Binding."); - - } - - } else { - Logger.warn("Requested IDP " + target.getRequestedIDP() - + " is not found in InterFederation configuration"); - - } - - } catch (MetadataProviderException e) { - Logger.error("IDP metadata error." , e); - - } catch (NoSuchAlgorithmException e) { - Logger.error("Build IDP authentication request FAILED.", e); - - } catch (MessageEncodingException e) { - Logger.error("Build IDP authentication request FAILED.", e); - - } catch (SecurityException e) { - Logger.error("Build IDP authentication request FAILED.", e); - - } - - if (requiredLocalAuthentication) { - Logger.info("Switch to local authentication on this IDP ... "); - if (idp.isPerformLocalAuthenticationOnInterfederationError()) - perfomLocalAuthentication(request, response, target); - - else - throw new AuthenticationException("auth.29", new String[]{target.getRequestedIDP()}); - } - } - - - private void perfomLocalAuthentication(HttpServletRequest request, - HttpServletResponse response, IRequest target) - throws ServletException, IOException, MOAIDException { - Logger.debug("Starting authentication on this IDP ..."); - - response.setHeader(MOAIDAuthConstants.HEADER_EXPIRES, MOAIDAuthConstants.HEADER_VALUE_EXPIRES); - response.setHeader(MOAIDAuthConstants.HEADER_PRAGMA, MOAIDAuthConstants.HEADER_VALUE_PRAGMA); - response.setHeader(MOAIDAuthConstants.HEADER_CACHE_CONTROL, MOAIDAuthConstants.HEADER_VALUE_CACHE_CONTROL); - response.addHeader(MOAIDAuthConstants.HEADER_CACHE_CONTROL, MOAIDAuthConstants.HEADER_VALUE_CACHE_CONTROL_IE); - - List<String> legacyallowed_prot = AuthConfigurationProviderFactory.getInstance().getLegacyAllowedProtocols(); - - //is legacy allowed - boolean legacyallowed = legacyallowed_prot.contains(target.requestedModule()); - - //check legacy request parameter - boolean legacyparamavail = ParamValidatorUtils.areAllLegacyParametersAvailable(request); - - AuthenticationSession moasession; - try { - //check if an MOASession exists and if not create an new MOASession - //moasession = getORCreateMOASession(request); - moasession = AuthenticationSessionStoreage.createSession(target); - - } catch (MOADatabaseException e1) { - Logger.error("Database Error! MOASession can not be created!"); - throw new MOAIDException("init.04", new Object[] {}); - } - - try { - - if (legacyallowed && legacyparamavail) { - - // create execution context - ExecutionContext executionContext = new ExecutionContextImpl(); - executionContext.put(MOAIDAuthConstants.PARAM_SESSIONID, moasession.getSessionID()); - executionContext.put("pendingRequestID", target.getRequestID()); - - executionContext.put("isLegacyRequest", true); - - Enumeration<String> reqParamNames = request.getParameterNames(); - while(reqParamNames.hasMoreElements()) { - String paramName = reqParamNames.nextElement(); - if (MiscUtil.isNotEmpty(paramName)) - executionContext.put(paramName, request.getParameter(paramName)); - - } - - // create process instance - String processDefinitionId = ModuleRegistration.getInstance().selectProcess(executionContext); - - if (processDefinitionId == null) { - Logger.warn("No suitable process found for SessionID " + moasession.getSessionID() ); - throw new MOAIDException("process.02",new Object[] { - moasession.getSessionID()}); - } - - String processInstanceId = processEngine.createProcessInstance(processDefinitionId, executionContext); - - // keep process instance id in moa session - moasession.setProcessInstanceId(processInstanceId); - - // make sure moa session has been persisted before running the process - try { - AuthenticationSessionStoreage.storeSession(moasession); - } catch (MOADatabaseException e) { - Logger.error("Database Error! MOASession is not stored!"); - throw new MOAIDException("init.04", new Object[] { - moasession.getSessionID()}); - } - - // start process - processEngine.start(processInstanceId); - - } else { - MOAReversionLogger.getInstance().logEvent(target.getOnlineApplicationConfiguration(), - target, MOAIDEventConstants.AUTHPROCESS_BKUSELECTION_INIT); - - //load Parameters from OnlineApplicationConfiguration - OAAuthParameter oaParam = AuthConfigurationProviderFactory.getInstance() - .getOnlineApplicationParameter(target.getOAURL()); - - if (oaParam == null) { - throw new AuthenticationException("auth.00", new Object[] { target.getOAURL() }); - } - - else { - - //check if an MOASession exists and if not create an new MOASession - //moasession = getORCreateMOASession(request); - - //set OnlineApplication configuration in Session - moasession.setOAURLRequested(target.getOAURL()); - moasession.setAction(target.requestedAction()); - moasession.setModul(target.requestedModule()); - } - - //Build authentication form - - - String publicURLPreFix = target.getAuthURL(); - if (publicURLPreFix.endsWith("/")) - publicURLPreFix = publicURLPreFix.substring(0, publicURLPreFix.length() - 1); - String loginForm = LoginFormBuilder.buildLoginForm(target.requestedModule(), - target.requestedAction(), oaParam, publicURLPreFix, moasession.getSessionID()); - - //store MOASession - try { - AuthenticationSessionStoreage.storeSession(moasession, target.getRequestID()); - } catch (MOADatabaseException e) { - Logger.error("Database Error! MOASession is not stored!"); - throw new MOAIDException("init.04", new Object[] { - moasession.getSessionID()}); - } - - //set MOAIDSession - //request.getSession().setAttribute(MOA_SESSION, moasession.getSessionID()); - - response.setContentType("text/html;charset=UTF-8"); - PrintWriter out = new PrintWriter(response.getOutputStream()); - out.print(loginForm); - out.flush(); - } - } catch (ProcessExecutionException e) { - Throwable cause = e.getCause(); - if (cause != null && cause instanceof TaskExecutionException) { - Throwable taskCause = cause.getCause(); - if (taskCause != null && taskCause instanceof MOAIDException) { - MOAIDException moaTaskCause = (MOAIDException) taskCause; - Logger.warn(taskCause); - throw moaTaskCause; - - } - } - - throw new MOAIDException("process.01", new Object[] { moasession.getProcessInstanceId(), moasession }, e); - } - } } |