/* * 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.auth.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.opensaml.saml2.core.LogoutResponse; import org.opensaml.saml2.metadata.SingleLogoutService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; import at.gv.egovernment.moa.id.auth.frontend.builder.DefaultGUIFormBuilderConfiguration; import at.gv.egovernment.moa.id.auth.frontend.exception.GUIBuildException; import at.gv.egovernment.moa.id.commons.MOAIDAuthConstants; import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException; import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; import at.gv.egovernment.moa.id.commons.utils.MOAIDMessageProvider; import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; import at.gv.egovernment.moa.id.data.ISLOInformationContainer; import at.gv.egovernment.moa.id.data.SLOInformationContainer; import at.gv.egovernment.moa.id.moduls.AuthenticationManager; import at.gv.egovernment.moa.id.moduls.SSOManager; import at.gv.egovernment.moa.id.protocols.pvp2x.builder.SingleLogOutBuilder; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NOSLOServiceDescriptorException; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NoMetadataInformationException; import at.gv.egovernment.moa.id.storage.IAuthenticationSessionStoreage; import at.gv.egovernment.moa.id.util.HTTPUtils; import at.gv.egovernment.moa.id.util.Random; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; import at.gv.egovernment.moa.util.URLEncoder; /** * @author tlenz * */ @Controller public class IDPSingleLogOutServlet extends AbstractController { @Autowired SSOManager ssoManager; @Autowired AuthenticationManager authManager; @Autowired IAuthenticationSessionStoreage authenicationStorage; @Autowired SingleLogOutBuilder sloBuilder; @RequestMapping(value = "/idpSingleLogout", method = {RequestMethod.GET}) public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Logger.debug("Receive IDP-initiated SingleLogOut"); String authURL = HTTPUtils.extractAuthURLFromRequest(req); try { if (!AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix().contains(authURL)) { Logger.warn("Requested URL " + authURL + " is not in PublicPrefix Configuration"); resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Request not allowed"); return; } } catch (MOAIDException e) { Logger.error("Internal Server Error.", e); resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Internal Server Error"); return; } String ssoid = ssoManager.getSSOSessionID(req); Object restartProcessObj = req.getParameter(MOAIDAuthConstants.PARAM_SLORESTART); Object tokkenObj = req.getParameter(MOAIDAuthConstants.PARAM_SLOSTATUS); String tokken = null; String status = null; if (tokkenObj != null && tokkenObj instanceof String) { tokken = (String) tokkenObj; try { status = transactionStorage.get(tokken, String.class); if (MiscUtil.isNotEmpty(status)) { transactionStorage.remove(tokken); } DefaultGUIFormBuilderConfiguration config = new DefaultGUIFormBuilderConfiguration( authURL, DefaultGUIFormBuilderConfiguration.VIEW_SINGLELOGOUT, null); if (MOAIDAuthConstants.SLOSTATUS_SUCCESS.equals(status)) config.putCustomParameter("successMsg", MOAIDMessageProvider.getInstance().getMessage("slo.00", null)); else config.putCustomParameter("errorMsg", MOAIDMessageProvider.getInstance().getMessage("slo.01", null)); guiBuilder.build(resp, config, "Single-LogOut GUI"); } catch (GUIBuildException e) { handleErrorNoRedirect(e, req, resp, false); } catch (MOADatabaseException e) { handleErrorNoRedirect(e, req, resp, false); } return; } else if (MiscUtil.isNotEmpty(ssoid)) { try { if (ssoManager.isValidSSOSession(ssoid, null)) { AuthenticationSession authSession = authenicationStorage.getInternalMOASessionWithSSOID(ssoid); if(authSession != null) { authManager.performSingleLogOut(req, resp, authSession, authURL); return; } } } catch (Exception e) { handleErrorNoRedirect(e, req, resp, false); } } else if (restartProcessObj != null && restartProcessObj instanceof String) { String restartProcess = (String) restartProcessObj; if (MiscUtil.isNotEmpty(restartProcess)) { Logger.info("Restart Single LogOut process after timeout ... "); try { ISLOInformationContainer sloContainer = transactionStorage.get(restartProcess, SLOInformationContainer.class); if (sloContainer.hasFrontChannelOA()) sloContainer.putFailedOA("differntent OAs"); String redirectURL = null; if (sloContainer.getSloRequest() != null) { //send SLO response to SLO request issuer SingleLogoutService sloService = sloBuilder.getResponseSLODescriptor(sloContainer.getSloRequest()); LogoutResponse message = sloBuilder.buildSLOResponseMessage(sloService, sloContainer.getSloRequest(), sloContainer.getSloFailedOAs()); redirectURL = sloBuilder.getFrontChannelSLOMessageURL(sloService, message, req, resp, sloContainer.getSloRequest().getRequest().getRelayState()); } else { //print SLO information directly redirectURL = HTTPUtils.extractAuthURLFromRequest(req) + "/idpSingleLogout"; String artifact = Random.nextRandom(); String statusCode = null; if (sloContainer.getSloFailedOAs() == null || sloContainer.getSloFailedOAs().size() == 0) statusCode = MOAIDAuthConstants.SLOSTATUS_SUCCESS; else statusCode = MOAIDAuthConstants.SLOSTATUS_ERROR; transactionStorage.put(artifact, statusCode, -1); redirectURL = HTTPUtils.addURLParameter(redirectURL, MOAIDAuthConstants.PARAM_SLOSTATUS, artifact); } //redirect to Redirect Servlet String url = authURL + "/RedirectServlet"; url = HTTPUtils.addURLParameter(url, RedirectServlet.REDIRCT_PARAM_URL, URLEncoder.encode(redirectURL, "UTF-8")); url = resp.encodeRedirectURL(url); resp.setContentType("text/html"); resp.setStatus(302); resp.addHeader("Location", url); return; } catch (MOADatabaseException e) { Logger.info("Find no SLO information with processingID " + restartProcess); } catch (NoMetadataInformationException e) { Logger.warn("Build SLO respone FAILED.", e); } catch (NOSLOServiceDescriptorException e) { Logger.warn("Build SLO respone FAILED.", e); } catch (MOAIDException e) { Logger.warn("Build SLO respone FAILED.", e); } try { DefaultGUIFormBuilderConfiguration config = new DefaultGUIFormBuilderConfiguration( authURL, DefaultGUIFormBuilderConfiguration.VIEW_SINGLELOGOUT, null); config.putCustomParameter("errorMsg", MOAIDMessageProvider.getInstance().getMessage("slo.01", null)); guiBuilder.build(resp, config, "Single-LogOut GUI"); } catch (GUIBuildException e) { e.printStackTrace(); } return; } } try { DefaultGUIFormBuilderConfiguration config = new DefaultGUIFormBuilderConfiguration( authURL, DefaultGUIFormBuilderConfiguration.VIEW_SINGLELOGOUT, null); config.putCustomParameter("successMsg", MOAIDMessageProvider.getInstance().getMessage("slo.02", null)); guiBuilder.build(resp, config, "Single-LogOut GUI"); } catch (GUIBuildException e) { e.printStackTrace(); } } }