org.guanxi.sp.engine.service.generic.GenericProfileService.java Source code

Java tutorial

Introduction

Here is the source code for org.guanxi.sp.engine.service.generic.GenericProfileService.java

Source

//: "The contents of this file are subject to the Mozilla Public License
//: Version 1.1 (the "License"); you may not use this file except in
//: compliance with the License. You may obtain a copy of the License at
//: http://www.mozilla.org/MPL/
//:
//: Software distributed under the License is distributed on an "AS IS"
//: basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
//: License for the specific language governing rights and limitations
//: under the License.
//:
//: The Original Code is Guanxi (http://www.guanxi.uhi.ac.uk).
//:
//: The Initial Developer of the Original Code is Alistair Young alistair@codebrane.com
//: All Rights Reserved.
//:

package org.guanxi.sp.engine.service.generic;

import org.apache.log4j.Logger;
import org.guanxi.common.GuanxiException;
import org.guanxi.common.definitions.Guanxi;
import org.guanxi.common.definitions.SAML;
import org.guanxi.common.entity.EntityFarm;
import org.guanxi.common.entity.EntityManager;
import org.guanxi.common.metadata.Metadata;
import org.guanxi.sp.Util;
import org.guanxi.xal.saml2.metadata.GuardRoleDescriptorExtensions;
import org.guanxi.xal.saml_2_0.metadata.EndpointType;
import org.guanxi.xal.saml_2_0.metadata.EntityDescriptorType;
import org.springframework.context.MessageSource;
import org.springframework.web.context.ServletContextAware;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;

/**
 * Generic profile service for selecting a profile based on metadata
 *
 * @author alistair
 */
public class GenericProfileService extends MultiActionController implements ServletContextAware {
    /** Our logger */
    private static final Logger logger = Logger.getLogger(GenericProfileService.class.getName());
    /** The marker in our entityID map for the one to use as the default entityID */
    private static final String DEFAULT_ENTITYID_MARKER = "__DEFAULT__";
    /** The localised messages to use */
    private MessageSource messages = null;
    /** The JSP to use to display any errors */
    private String errorView = null;
    /** The request attribute that holds the error message for the error view */
    private String errorViewDisplayVar = null;
    /** The Shibboleth profile service to use */
    private ProfileService shibbolethProfileService = null;
    /** The SAML2 profile service to use */
    private ProfileService saml2ProfileService = null;
    /** The SAML2 Discovery profile service to use */
    private ProfileService saml2DiscoveryProfileService = null;
    /** The list of Guard to entityID mappings */
    private HashMap<String, String> entityIDs = null;
    /** Whether to use the SAML2 Discovery Service */
    private boolean useDiscoveryService;

    public void init() {
    }

    public ModelAndView gps(HttpServletRequest request, HttpServletResponse response) {
        String guardID = request.getParameter(Guanxi.WAYF_PARAM_GUARD_ID);
        String guardSessionID = request.getParameter(Guanxi.WAYF_PARAM_SESSION_ID);

        // Optional entityID
        String idpEntityID = request.getParameter("entityID");

        // If the Guard hasn't specified an entityID, see if it has one registered for it
        if (idpEntityID == null) {
            if (entityIDs != null) {
                String entityIDForGuard = null;
                String defaultEntityID = null;

                // Find out which entityID to use for this Guard
                for (String registeredGuardID : entityIDs.keySet()) {
                    if (registeredGuardID.equals(DEFAULT_ENTITYID_MARKER)) {
                        defaultEntityID = entityIDs.get(registeredGuardID);
                    }
                    if (guardID.equals(registeredGuardID)) {
                        entityIDForGuard = entityIDs.get(registeredGuardID);
                    }
                }

                idpEntityID = (entityIDForGuard != null) ? entityIDForGuard : defaultEntityID;
                logger.info("Guard '" + guardID + "' obtained entityID : " + idpEntityID);
            }
        } else {
            logger.info("Guard '" + guardID + "' specified entityID : " + idpEntityID);
        }

        // If no IdP entityID, see if it's coming from the discovery service
        if ((idpEntityID == null) && (useDiscoveryService)) {
            idpEntityID = request.getParameter("edsEntityID");
        }

        // Get the Guard's metadata, previously loaded by the Bootstrapper
        EntityDescriptorType guardEntityDescriptor = (EntityDescriptorType) getServletContext()
                .getAttribute(guardID);
        if (guardEntityDescriptor == null) {
            logger.error("Guard '" + guardID + "' not found in metadata repository");
            ModelAndView mAndV = new ModelAndView();
            mAndV.setViewName(errorView);
            mAndV.getModel().put(errorViewDisplayVar,
                    messages.getMessage("engine.error.no.guard.metadata", null, request.getLocale()));
            return mAndV;
        }

        // Load the GuanxiGuardService node from the metadata
        GuardRoleDescriptorExtensions guardNativeMetadata = Util.getGuardNativeMetadata(guardEntityDescriptor);

        /* Convert the Guard's session ID to an Engine session ID and store the Guard's GuanxiGuardService
         * node under it. This will be deleted from the context once the SAML round trip has been processed
         * and the attributes sent to the Guard.
         */
        getServletContext().setAttribute(guardSessionID.replaceAll("GUARD", "ENGINE"), guardEntityDescriptor);

        EntityFarm farm = (EntityFarm) getServletContext().getAttribute(Guanxi.CONTEXT_ATTR_ENGINE_ENTITY_FARM);
        try {
            return getProfileService(request, farm, idpEntityID).doProfile(request, guardID, guardSessionID,
                    guardNativeMetadata, idpEntityID, farm);
        } catch (GuanxiException ge) {
            logger.error("Profile Service error: ", ge);
            ModelAndView mAndV = new ModelAndView();
            mAndV.setViewName(errorView);
            mAndV.getModel().put(errorViewDisplayVar, ge.getMessage());
            return mAndV;
        }
    }

    /**
     * Selects a profile to use
     *
     * @param request the request
     * @param farm entity farm
     * @param idpEntityID entityID of the IdP or null if there isn't one
     * @return ProfileService instance which defaults to Shibboleth
     * @throws GuanxiException if an error occurs
     */
    private ProfileService getProfileService(HttpServletRequest request, EntityFarm farm, String idpEntityID)
            throws GuanxiException {
        if (idpEntityID == null) {
            // Check to see if the Discovery Service has anything for us
            if (useDiscoveryService) {
                if (request.getParameter("edsEntityID") != null) {
                    idpEntityID = request.getParameter("edsEntityID");
                } else if (request.getParameter("edsEntityID") == null) {
                    // Use the Embedded Discovery Service to get an IdP entityID
                    return saml2DiscoveryProfileService;
                }
            } else {
                // No entityID so assume Shibboleth
                return shibbolethProfileService;
            }
        }

        // By now we have an IdP entityID

        // Load the metadata for the IdP
        EntityManager manager = farm.getEntityManagerForID(idpEntityID);
        if (manager == null) {
            throw new GuanxiException("Could not find manager for IdP '" + idpEntityID);
        }
        Metadata entityMetadata = manager.getMetadata(idpEntityID);
        if (entityMetadata == null) {
            throw new GuanxiException("Could not find metadata for IdP " + idpEntityID);
        }
        EntityDescriptorType saml2Metadata = (EntityDescriptorType) entityMetadata.getPrivateData();

        // Look for SAML2 endpoints
        EndpointType[] ssos = saml2Metadata.getIDPSSODescriptorArray(0).getSingleSignOnServiceArray();
        for (EndpointType sso : ssos) {
            String binding = sso.getBinding();
            if ((binding.equals(SAML.SAML2_BINDING_HTTP_POST))
                    || (binding.equals(SAML.SAML2_BINDING_HTTP_REDIRECT))) {
                return saml2ProfileService;
            }
        }

        // If we get here, SAML2 isn't supported so use Shibboleth
        return shibbolethProfileService;
    }

    // Setters
    public void setMessages(MessageSource messages) {
        this.messages = messages;
    }

    public void setErrorView(String errorView) {
        this.errorView = errorView;
    }

    public void setErrorViewDisplayVar(String errorViewDisplayVar) {
        this.errorViewDisplayVar = errorViewDisplayVar;
    }

    public void setShibbolethProfileService(ProfileService shibbolethProfileService) {
        this.shibbolethProfileService = shibbolethProfileService;
    }

    public void setSaml2ProfileService(ProfileService saml2ProfileService) {
        this.saml2ProfileService = saml2ProfileService;
    }

    public void setSaml2DiscoveryProfileService(ProfileService saml2DiscoveryProfileService) {
        this.saml2DiscoveryProfileService = saml2DiscoveryProfileService;
    }

    public void setEntityIDs(HashMap<String, String> entityIDs) {
        this.entityIDs = entityIDs;
    }

    public void setUseDiscoveryService(boolean useDiscoveryService) {
        this.useDiscoveryService = useDiscoveryService;
    }
}