at.gv.egovernment.moa.id.moduls.SSOManager.java Source code

Java tutorial

Introduction

Here is the source code for at.gv.egovernment.moa.id.moduls.SSOManager.java

Source

/*******************************************************************************
 * 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.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
import java.net.URI;
import java.util.Date;
import java.util.List;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.hibernate.Query;
import org.hibernate.Session;

import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants;
import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
import at.gv.egovernment.moa.id.commons.db.MOASessionDBUtils;
import at.gv.egovernment.moa.id.commons.db.dao.session.AuthenticatedSessionStore;
import at.gv.egovernment.moa.id.commons.db.dao.session.InterfederationSessionStore;
import at.gv.egovernment.moa.id.commons.db.dao.session.OldSSOSessionIDStore;
import at.gv.egovernment.moa.id.config.ConfigurationException;
import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
import at.gv.egovernment.moa.id.util.Random;
import at.gv.egovernment.moa.id.util.VelocityProvider;
import at.gv.egovernment.moa.logging.Logger;
import at.gv.egovernment.moa.util.MiscUtil;

public class SSOManager {

    private static final String HTMLTEMPLATESDIR = "htmlTemplates/";
    private static final String HTMLTEMPLATEFULL = "slo_template.html";

    private static final String SSOCOOKIE = "MOA_ID_SSO";
    private static final String SSOINTERFEDERATION = "MOA_INTERFEDERATION_SSO";

    private static final int DEFAULTSSOTIMEOUT = 15 * 60; // sec

    private static final int INTERFEDERATIONCOOKIEMAXAGE = 5 * 60;// sec

    private static SSOManager instance = null;
    private static int sso_timeout;

    public static SSOManager getInstance() {
        if (instance == null) {
            instance = new SSOManager();

            try {
                sso_timeout = (int) AuthConfigurationProvider.getInstance().getTimeOuts().getMOASessionUpdated()
                        .longValue();

            } catch (ConfigurationException e) {
                Logger.info("SSO Timeout can not be loaded from MOA-ID configuration. Use default Timeout with "
                        + DEFAULTSSOTIMEOUT);
                sso_timeout = DEFAULTSSOTIMEOUT;
            }

        }

        return instance;
    }

    public void checkInterfederationIsRequested(HttpServletRequest httpReq, HttpServletResponse httpResp,
            IRequest protocolRequest) {
        String interIDP = httpReq.getParameter(MOAIDAuthConstants.INTERFEDERATION_IDP);

        if (MiscUtil.isNotEmpty(protocolRequest.getRequestedIDP())) {
            Logger.info("Protocolspecific preprocessing already set interfederation IDP "
                    + protocolRequest.getRequestedIDP());
            return;

        }

        if (protocolRequest instanceof RequestImpl) {
            //check if IDP is requested                           
            RequestImpl moaReq = (RequestImpl) protocolRequest;
            if (MiscUtil.isNotEmpty(interIDP)) {
                Logger.info("Receive SSO request for interfederation IDP " + interIDP);
                moaReq.setRequestedIDP(interIDP);

            } else {
                //check if IDP cookie is set
                String cookie = getValueFromCookie(httpReq, SSOINTERFEDERATION);
                if (MiscUtil.isNotEmpty(cookie)) {
                    Logger.info("Receive SSO request for interfederated IDP from Cookie " + cookie);
                    moaReq.setRequestedIDP(cookie);

                    deleteCookie(httpReq, httpResp, SSOINTERFEDERATION);
                }
            }

        } else {
            Logger.warn("Request is not of type RequestImpl");

        }
    }

    public void setInterfederationIDPCookie(HttpServletRequest httpReq, HttpServletResponse httpResp,
            String value) {
        setCookie(httpReq, httpResp, SSOINTERFEDERATION, value, INTERFEDERATIONCOOKIEMAXAGE);

    }

    public boolean isValidSSOSession(String ssoSessionID, IRequest protocolRequest) throws ConfigurationException {

        // search SSO Session
        if (ssoSessionID == null) {
            Logger.info("No SSO Session cookie found.");
            return false;
        }

        AuthenticatedSessionStore storedSession = AuthenticationSessionStoreage
                .isValidSessionWithSSOID(ssoSessionID, null);

        if (storedSession == null)
            return false;

        else {

            //check if session is out of lifetime
            Date now = new Date();
            long maxSSOSessionTime = AuthConfigurationProvider.getInstance().getTimeOuts().getMOASessionCreated()
                    .longValue() * 1000;
            Date ssoSessionValidTo = new Date(storedSession.getCreated().getTime() + maxSSOSessionTime);
            if (now.after(ssoSessionValidTo)) {
                Logger.info("Found outdated SSO session information. Start reauthentication process ... ");
                return false;
            }

            //check if request starts an interfederated SSO session
            if (protocolRequest != null && protocolRequest instanceof RequestImpl
                    && storedSession.isInterfederatedSSOSession() && !storedSession.isAuthenticated()) {

                if (MiscUtil.isEmpty(((RequestImpl) protocolRequest).getRequestedIDP())) {
                    InterfederationSessionStore selectedIDP = AuthenticationSessionStoreage
                            .searchInterfederatedIDPFORSSOWithMOASession(storedSession.getSessionid());

                    if (selectedIDP != null) {
                        //no local SSO session exist -> request interfederated IDP
                        ((RequestImpl) protocolRequest).setRequestedIDP(selectedIDP.getIdpurlprefix());

                    } else {
                        Logger.warn(
                                "MOASession is marked as interfederated SSO session but no interfederated IDP is found. Switch to local authentication ...");
                        MOASessionDBUtils.delete(storedSession);

                    }
                }

                return false;

            }

            return true;
        }

    }

    public String getMOASession(String ssoSessionID) {
        return AuthenticationSessionStoreage.getMOASessionSSOID(ssoSessionID);

    }

    public String existsOldSSOSession(String ssoId) {

        Logger.trace("Check that the SSOID has already been used");
        Session session = MOASessionDBUtils.getCurrentSession();

        List<OldSSOSessionIDStore> result;

        synchronized (session) {

            session.beginTransaction();
            Query query = session.getNamedQuery("getSSOSessionWithOldSessionID");
            query.setParameter("sessionid", ssoId);
            result = query.list();

            // send transaction

        }

        Logger.trace("Found entries: " + result.size());

        // Assertion requires an unique artifact
        if (result.size() == 0) {
            session.getTransaction().commit();
            return null;
        }

        OldSSOSessionIDStore oldSSOSession = result.get(0);

        AuthenticatedSessionStore correspondingMoaSession = oldSSOSession.getMoasession();

        if (correspondingMoaSession == null) {
            Logger.info("Get request with old SSO SessionID but no corresponding SSO Session is found.");
            return null;
        }

        String moasessionid = correspondingMoaSession.getSessionid();

        session.getTransaction().commit();

        return moasessionid;

    }

    public String createSSOSessionInformations(String moaSessionID, String OAUrl) {

        String newSSOId = Random.nextRandom();

        if (MiscUtil.isEmpty(moaSessionID) || MiscUtil.isEmpty(OAUrl)) {
            Logger.warn("MoaSessionID or OAUrl are empty -> SSO is not enabled!");
            return null;
        }

        return newSSOId;

    }

    public void setSSOSessionID(HttpServletRequest httpReq, HttpServletResponse httpResp, String ssoId) {
        setCookie(httpReq, httpResp, SSOCOOKIE, ssoId, sso_timeout);

    }

    public String getSSOSessionID(HttpServletRequest httpReq) {
        return getValueFromCookie(httpReq, SSOCOOKIE);

    }

    public void deleteSSOSessionID(HttpServletRequest httpReq, HttpServletResponse httpResp) {
        deleteCookie(httpReq, httpResp, SSOCOOKIE);
    }

    /**
     * @param entityID
     * @param request
     */
    public boolean removeInterfederatedSSOIDP(String entityID, HttpServletRequest request) {

        String ssoSessionID = getSSOSessionID(request);

        if (MiscUtil.isNotEmpty(ssoSessionID)) {

            AuthenticatedSessionStore storedSession = AuthenticationSessionStoreage
                    .isValidSessionWithSSOID(ssoSessionID, null);

            if (storedSession == null)
                return false;

            InterfederationSessionStore selectedIDP = AuthenticationSessionStoreage
                    .searchInterfederatedIDPFORSSOWithMOASessionIDPID(storedSession.getSessionid(), entityID);

            if (selectedIDP != null) {
                //no local SSO session exist -> request interfederated IDP
                Logger.info("Delete interfederated IDP " + selectedIDP.getIdpurlprefix() + " from MOASession "
                        + storedSession.getSessionid());
                MOASessionDBUtils.delete(selectedIDP);

            } else {
                Logger.warn(
                        "MOASession is marked as interfederated SSO session but no interfederated IDP is found. Switch to local authentication ...");

            }

            return true;

        } else
            return false;

    }

    public void printSingleLogOutInfo(VelocityContext context, HttpServletResponse httpResp) throws MOAIDException {
        try {
            Logger.trace("Initialize VelocityEngine...");

            InputStream is = null;
            String pathLocation = null;
            try {
                String rootconfigdir = AuthConfigurationProvider.getInstance().getRootConfigFileDir();
                pathLocation = rootconfigdir + HTMLTEMPLATESDIR + HTMLTEMPLATEFULL;
                File file = new File(new URI(pathLocation));
                is = new FileInputStream(file);
                evaluateSLOTemplate(context, httpResp, is);

            } catch (Exception e) {
                Logger.warn("SLO Template is not found in configuration directory (" + pathLocation
                        + "). Load template from project library ... ");

                try {
                    pathLocation = "resources/templates/" + HTMLTEMPLATEFULL;
                    is = Thread.currentThread().getContextClassLoader().getResourceAsStream(pathLocation);
                    evaluateSLOTemplate(context, httpResp, is);

                } catch (Exception e1) {
                    Logger.error("Single LogOut form can not created.", e);
                    throw new MOAIDException("Create Single LogOut information FAILED.", null, e);
                }

            } finally {
                if (is != null)
                    is.close();

            }

        } catch (Exception e) {
            Logger.error("Single LogOut form can not created.", e);
            throw new MOAIDException("Create Single LogOut information FAILED.", null, e);
        }

    }

    private void evaluateSLOTemplate(VelocityContext context, HttpServletResponse httpResp, InputStream is)
            throws Exception {

        VelocityEngine engine = VelocityProvider.getClassPathVelocityEngine();

        BufferedReader reader = new BufferedReader(new InputStreamReader(is));

        //set default elements to velocity context
        context.put("contextpath", AuthConfigurationProvider.getInstance().getPublicURLPrefix());

        StringWriter writer = new StringWriter();
        //velocityEngine.evaluate(context, writer, "SLO_Template", reader);         
        engine.evaluate(context, writer, "SLO Template", reader);

        httpResp.setContentType("text/html;charset=UTF-8");
        httpResp.getOutputStream().write(writer.toString().getBytes("UTF-8"));

    }

    private String getValueFromCookie(HttpServletRequest httpReq, String cookieName) {
        Cookie[] cookies = httpReq.getCookies();

        if (cookies != null) {
            for (Cookie cookie : cookies) {

                // funktioniert nicht, da Cookie seltsamerweise immer unsecure bertragen wird
                // (firefox)
                // if (cookie.getName().equals(SSOCOOKIE) && cookie.getSecure()) {

                if (cookie.getName().equals(cookieName)) {
                    return cookie.getValue();
                }
            }
        }
        return null;
    }

    private void setCookie(HttpServletRequest httpReq, HttpServletResponse httpResp, String cookieName,
            String cookieValue, int maxAge) {

        Cookie cookie = new Cookie(cookieName, cookieValue);
        cookie.setMaxAge(maxAge);
        cookie.setSecure(true);

        //TODO: could be a problem if the IDP is accessible from different contextPaths or Domains
        cookie.setPath(httpReq.getContextPath());

        httpResp.addCookie(cookie);
    }

    private void deleteCookie(HttpServletRequest httpReq, HttpServletResponse httpResp, String cookieName) {
        setCookie(httpReq, httpResp, cookieName, "", 1);
    }

}