/******************************************************************************* * Copyright 2014 Federal Chancellery Austria * MOA-ID has been developed in a cooperation between BRZ, the Federal * Chancellery Austria - ICT staff unit, and Graz University of Technology. * * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by * the European Commission - subsequent versions of the EUPL (the "Licence"); * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: * http://www.osor.eu/eupl/ * * Unless required by applicable law or agreed to in writing, software * distributed under the Licence is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and * limitations under the Licence. * * This product combines work with different licenses. See the "NOTICE" text * file for details on the various modules and licenses. * The "NOTICE" text file is part of the distribution. Any derivative works * that you distribute must include a readable copy of the "NOTICE" text file. *******************************************************************************/ package at.gv.egovernment.moa.id.moduls; import java.util.Enumeration; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang3.StringUtils; import org.opensaml.saml2.core.LogoutRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import at.gv.egiz.eaaf.core.api.IRequest; import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; import at.gv.egiz.eaaf.core.api.idp.slo.ISLOInformationContainer; import at.gv.egiz.eaaf.core.exceptions.EAAFException; import at.gv.egiz.eaaf.core.impl.idp.auth.AbstractAuthenticationManager; import at.gv.egiz.eaaf.core.impl.idp.controller.protocols.RequestImpl; import at.gv.egiz.eaaf.core.impl.utils.Random; import at.gv.egiz.eaaf.modules.pvp2.idp.impl.PVPSProfilePendingRequest; import at.gv.egiz.eaaf.modules.pvp2.impl.message.PVPSProfileRequest; import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionExtensions; import at.gv.egovernment.moa.id.commons.MOAIDAuthConstants; import at.gv.egovernment.moa.id.commons.api.AuthConfiguration; 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.data.SLOInformationContainer; import at.gv.egovernment.moa.id.protocols.pvp2x.builder.SingleLogOutBuilder; import at.gv.egovernment.moa.id.storage.IAuthenticationSessionStoreage; import at.gv.egovernment.moa.id.util.ParamValidatorUtils; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; @Service("MOAID_AuthenticationManager") public class AuthenticationManager extends AbstractAuthenticationManager { public static final String eIDAS_GENERIC_REQ_DATA_LEVELOFASSURENCE = "eIDAS_LoA"; public static final String DATAID_REQUESTED_ATTRIBUTES = "requestedAttributes"; public static final String MOA_SESSION = "MoaAuthenticationSession"; public static final String MOA_AUTHENTICATED = "MoaAuthenticated"; @Autowired private IAuthenticationSessionStoreage authenticatedSessionStore; @Autowired private SingleLogOutBuilder sloBuilder;; @Override public ISLOInformationContainer performSingleLogOut(HttpServletRequest httpReq, HttpServletResponse httpResp, IRequest pendingReq, String internalSSOId) throws EAAFException { String pvpSLOIssuer = null; String uniqueSessionIdentifier = "notSet"; String uniqueTransactionIdentifier = "notSet"; PVPSProfilePendingRequest pvpReq = null; Logger.debug("Start technical Single LogOut process ... "); if (pendingReq != null) { uniqueSessionIdentifier = pendingReq.getUniqueSessionIdentifier(); uniqueTransactionIdentifier = pendingReq.getUniqueTransactionIdentifier(); if (pendingReq instanceof PVPSProfileRequest) { pvpReq = ((PVPSProfilePendingRequest)pendingReq); PVPSProfileRequest samlReq = (PVPSProfileRequest) pvpReq.getRequest(); LogoutRequest logOutReq = (LogoutRequest) samlReq.getSamlRequest(); pvpSLOIssuer = logOutReq.getIssuer().getValue(); } if (MiscUtil.isEmpty(internalSSOId)) internalSSOId = pendingReq.getInternalSSOSessionIdentifier(); } else { AuthenticationSessionExtensions sessionExt; try { sessionExt = authenticatedSessionStore.getAuthenticationSessionExtensions(internalSSOId); if (sessionExt != null) uniqueSessionIdentifier = sessionExt.getUniqueSessionId(); } catch (MOADatabaseException e) { Logger.error("Error during database communication. Can not evaluate 'uniqueSessionIdentifier'", e); } uniqueTransactionIdentifier = Random.nextLongRandom(); revisionsLogger.logEvent(uniqueSessionIdentifier, uniqueTransactionIdentifier, MOAIDEventConstants.AUTHPROCESS_IDP_SLO_REQUESTED); } //store active OAs to SLOContaine List dbOAs = authenticatedSessionStore.getAllActiveOAFromMOASession(internalSSOId); List dbIDPs = authenticatedSessionStore.getAllActiveIDPsFromMOASession(internalSSOId); SLOInformationContainer sloContainer = new SLOInformationContainer(); sloContainer.setTransactionID(uniqueTransactionIdentifier); sloContainer.setSessionID(uniqueSessionIdentifier); sloContainer.setSloRequest(pvpReq); sloBuilder.parseActiveIDPs(sloContainer, dbIDPs, pvpSLOIssuer); sloBuilder.parseActiveOAs(sloContainer, dbOAs, pvpSLOIssuer); Logger.debug("Active SSO Service-Provider: " + " BackChannel:" + sloContainer.getActiveBackChannelOAs().size() + " FrontChannel:" + sloContainer.getActiveFrontChannalOAs().size() + " NO_SLO_Support:" + sloContainer.getSloFailedOAs().size()); //terminate MOASession try { authenticatedSessionStore.destroyInternalSSOSession(internalSSOId); ssoManager.destroySSOSessionOnIDPOnly(httpReq, httpResp, pendingReq); revisionsLogger.logEvent(MOAIDEventConstants.SESSION_DESTROYED, uniqueSessionIdentifier); Logger.debug("Active SSO Session on IDP is remove."); } catch (MOADatabaseException e) { Logger.warn("Delete MOASession FAILED."); sloContainer.putFailedOA(pvpReq.getAuthURL()); } return sloContainer; } @Override protected void populateExecutionContext(ExecutionContext executionContext, RequestImpl pendingReq, HttpServletRequest httpReq) throws EAAFException { //is legacy allowed boolean legacyallowed = false; if (authConfig instanceof AuthConfiguration) { List legacyallowed_prot = ((AuthConfiguration)authConfig).getLegacyAllowedProtocols(); legacyallowed = legacyallowed_prot.contains(pendingReq.requestedModule()); } else Logger.info("Base configuration is NOT of type 'AuthConfiguration'. LegacyMode is disabled"); //check legacy request parameter boolean legacyparamavail = ParamValidatorUtils.areAllLegacyParametersAvailable(httpReq); //set interfederation authentication flag executionContext.put(MOAIDAuthConstants.PROCESSCONTEXT_PERFORM_INTERFEDERATION_AUTH, MiscUtil.isNotEmpty( pendingReq.getRawData(SSOManager.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.getRawData(SSOManager.DATAID_INTERFEDERATIOIDP_URL, String.class))); //add additional http request parameter to context if (leagacyMode) { Enumeration reqParamNames = httpReq.getParameterNames(); while(reqParamNames.hasMoreElements()) { String paramName = reqParamNames.nextElement(); if (StringUtils.isNotEmpty(paramName) && MOAIDAuthConstants.LEGACYPARAMETERWHITELIST.contains(paramName) ) executionContext.put(paramName, StringEscapeUtils.escapeHtml(httpReq.getParameter(paramName))); } } } }