org.josso.gateway.SSOGatewayImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.josso.gateway.SSOGatewayImpl.java

Source

/*
 * JOSSO: Java Open Single Sign-On
 *
 * Copyright 2004-2009, Atricore, Inc.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 *
 */
package org.josso.gateway;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.josso.Lookup;
import org.josso.SecurityDomain;
import org.josso.auth.Authenticator;
import org.josso.auth.Credential;
import org.josso.auth.exceptions.AuthenticationFailureException;
import org.josso.auth.exceptions.SSOAuthenticationException;
import org.josso.gateway.assertion.AuthenticationAssertion;
import org.josso.gateway.assertion.AssertionManager;
import org.josso.gateway.event.security.SSOSecurityEventManager;
import org.josso.gateway.identity.SSORole;
import org.josso.gateway.identity.SSOUser;
import org.josso.gateway.identity.exceptions.NoSuchDomainException;
import org.josso.gateway.identity.exceptions.SSOIdentityException;
import org.josso.gateway.identity.service.SSOIdentityManager;
import org.josso.gateway.identity.service.SSOIdentityProvider;
import org.josso.gateway.session.SSOSession;
import org.josso.gateway.session.exceptions.NoSuchSessionException;
import org.josso.gateway.session.exceptions.SSOSessionException;
import org.josso.gateway.session.service.SSOSessionManager;

import java.security.Principal;
import java.util.ArrayList;
import java.util.List;

/**
 * This is the default SSO Gateway implementation.
 *
 * @org.apache.xbean.XBean element="gateway"
 * description="JOSSO Gateway implementation"
 *
 * @author <a href="mailto:sgonzalez@josso.org">Sebastian Gonzalez Oyuela</a>
 * @version $Id: SSOGatewayImpl.java 620 2008-09-23 13:40:36Z sgonzalez $
 */
public class SSOGatewayImpl implements SSOGateway {

    private static final Log logger = LogFactory.getLog(SSOGatewayImpl.class);

    private boolean _initialized;

    private List<SecurityDomain> securityDomains = new ArrayList<SecurityDomain>();

    private SSOSecurityDomainSelector securityDomainSelector;

    private SecurityDomainRegistry securityDomainRegistry;

    public SSOGatewayImpl() {

    }

    /**
     * Initializes the SSO gateway.
     * Default implementations of optionall components will be used if necessary.
     * <p/>
     * The proper security domain name will be configured for specific components.
     */
    public synchronized void initialize() {

        if (_initialized) {
            throw new IllegalStateException("SSOGateway already initialized");
        }

        // Perform some initialization logic, default implementations of optionall components will be used when necessary

        // ------------------------------------------------------------------------------------------
        // Finishing Gateway seutp !!
        // -------------------------------------------------------------------------------------------

        // Check security domain selector
        if (securityDomainSelector == null) {
            logger.info("Finishing setup, using default SecurityDomainSelector");

            try {
                securityDomainSelector = (SSOSecurityDomainSelector) loadClass(
                        "org.josso.gateway.DomainSelectorImpl").newInstance();
            } catch (Exception e) {
                logger.error("Cannot instantiate default security domain selector : " + e.getMessage(), e);
            }

        }

        // Check security domain registry
        if (securityDomainRegistry == null) {
            logger.info("Finishing setup, using default SecurityDomainRegistry");
            try {
                securityDomainRegistry = (SecurityDomainRegistry) loadClass(
                        "org.josso.gateway.SecurityDomainRegistryImpl").newInstance();
            } catch (Exception e) {
                logger.error("Cannot instantiate default security domain registry : " + e.getMessage(), e);
            }
        }

        for (int i = 0; i < securityDomains.size(); i++) {
            SecurityDomain sd = securityDomains.get(i);

            String name = sd.getName();

            // Check assertion manager
            if (sd.getIdentityProvider() == null) {
                logger.info("Finishing setup [" + name + "], using default IdentityProvider");
                try {
                    sd.setIdentityProvider((SSOIdentityProvider) loadClass(
                            "org.josso.gateway.identity.service.SSOIdentityProviderImpl").newInstance());
                } catch (Exception e) {
                    logger.error("Cannot create default identity provider : " + e.getMessage(), e);
                }
            }

            // Check assertion manager
            if (sd.getAssertionManager() == null) {
                logger.info("Finishing setup [" + name + "], using default AssertionManager");
                try {
                    sd.setAssertionManager(
                            (AssertionManager) loadClass("org.josso.gateway.assertion.AssertionManagerImpl")
                                    .newInstance());
                } catch (Exception e) {
                    logger.error("Cannot create default assertion manager : " + e.getMessage(), e);
                }
            }

            // Check SecurityDomain Matcher
            if (sd.getMatchers().size() == 0) {
                logger.info("Finishing setup [" + name + "], using default SecurityDomainMatcher");
                try {
                    sd.getMatchers()
                            .add((SecurityDomainMatcher) loadClass("org.josso.gateway.SimpleSecurityDomainMatcher")
                                    .newInstance());
                } catch (Exception e) {
                    logger.error("Cannot instantiate default security domain matcher : " + e.getMessage(), e);
                }
            }

        }

        // ------------------------------------------------------------------------------------------
        // Initializing components
        // -------------------------------------------------------------------------------------------

        for (int i = 0; i < securityDomains.size(); i++) {
            SecurityDomain sd = securityDomains.get(i);

            String name = sd.getName();

            securityDomainRegistry.register(sd);

            // This compoment should be initialized first ...
            logger.info("Initializing [" + name + " ] SSOEventManager ...");
            sd.getEventManager().initialize();
            logger.info("Initializing [" + name + " ] SSOEventManager ... DONE");

            logger.info("Initializing [" + name + " ] SSOAssertionManager ...");
            sd.getAssertionManager().setSecurityDomainName(name);
            sd.getAssertionManager().initialize();
            logger.info("Initializing [" + name + " ] SSOAssertionManager ... DONE");

            logger.info("Initializing [" + name + " ] SSOAssertionManager ...");
            sd.getIdentityProvider().initialize();
            logger.info("Initializing [" + name + " ] SSOAssertionManager ... DONE");

            logger.info("Initializing [" + name + " ] SSOIdentityManager ...");
            sd.getIdentityManager().initialize();
            logger.info("Initializing [" + name + " ] SSOIdentityManager ... DONE");

            logger.info("Initializing [" + name + " ] SSOSessionManager ...");
            sd.getSessionManager().setSecurityDomainName(name);
            sd.getSessionManager().initialize();
            logger.info("Initializing [" + name + " ] SSOSessionManager ... DONE");

            logger.info("Initializing [" + name + " ] SSOAuditManager ...");
            sd.getAuditManager().initialize();
            logger.info("Initializing [" + name + " ] SSOAuditManager ... DONE");

            if (sd.getProtocolManager() != null) {
                logger.info("Initializing [" + name + " ] SSOProtocolManager ...");
                sd.getProtocolManager().initialize();
                logger.info("Initializing [" + name + " ] SSOProtocolManager ... DONE");
            }

            for (SecurityDomainMatcher matcher : sd.getMatchers()) {
                logger.info("Initializing [" + name + " ] SecurityDomainMatcher ...");
                matcher.init();
                logger.info("Initializing [" + name + " ] SecurityDomainMatcher ... DONE");
            }

            if (sd.getSSOWebConfiguration().getTrustedHosts().size() == 0) {
                logger.warn("No trusted hosts defined, any 'back_to' value will be accepted!");
            } else {
                for (String trustedHost : sd.getSSOWebConfiguration().getTrustedHosts()) {
                    logger.info("Trusted HOST : [" + trustedHost + "]");
                }
            }
        }

        _initialized = true;
    }

    public boolean isInitialized() {
        return _initialized;
    }

    public void destroy() {
        for (int i = 0; i < securityDomains.size(); i++) {
            SecurityDomain sd = securityDomains.get(i);
            String name = sd.getName();

            logger.info("Destroying [" + name + " ] SSOAssertionManager ...");
            sd.getAssertionManager().destroy();
            logger.info("Destroying [" + name + " ] SSOAssertionManager ... DONE");

            logger.info("Destroying [" + name + " ] SSOSessionManager ...");
            sd.getSessionManager().destroy();
            logger.info("Destroying [" + name + " ] SSOSessionManager ... DONE");
        }

        _initialized = false;
    }

    public SSOContext prepareSSOContext(SSORequest req) throws NoSuchDomainException {
        MutableSSOContext ctx = new MutableSSOContext();
        ctx.setUserLocation(req.getUserLocation());

        // TODO : This properties should be populated later ... or based on ssorequest ?!
        ctx.setScheme("unknown");
        ctx.setSecurityDomain(this.securityDomainSelector.selectDomain(req, securityDomains));

        if (logger.isDebugEnabled())
            logger.debug("SSOContext created from request for SecurityDomain "
                    + (ctx.getSecurityDomain() != null ? ctx.getSecurityDomain().getName() : "null"));

        return ctx;
    }

    public SSOContext prepareSSOContext(String tokenType, String tokenValue) {

        if (tokenType == null || "".equals(tokenType)) {
            throw new IllegalArgumentException("TokenType cannot be null");
        }
        if (tokenValue == null || "".equals(tokenValue)) {
            throw new IllegalArgumentException("TokenValue cannot be null");
        }

        SecurityDomain sd = this.securityDomainRegistry.lookup(tokenType, tokenValue);
        if (sd == null) {
            sd = prepareDefaultSSOContext().getSecurityDomain();
            logger.debug("No security domain found for token : [" + tokenType + "/" + tokenValue
                    + "], using default one : " + sd.getName());
        }

        MutableSSOContext ctx = new MutableSSOContext();
        ctx.setSecurityDomain(sd);

        if (logger.isDebugEnabled())
            logger.debug("SSOContext created from token " + tokenType + "/" + tokenValue + " for SecurityDomain "
                    + (ctx.getSecurityDomain() != null ? ctx.getSecurityDomain().getName() : "null"));

        if (tokenType.equals(SSOSessionManager.TOKEN_TYPE)) {
            try {
                SSOSessionManager sm = sd.getSessionManager();
                SSOSession session = sm.getSession(tokenValue);
                ctx.setCurrentSession(session);
            } catch (Exception e) {
                // ignore all errors
            }
        }

        return ctx;
    }

    public SSOContext prepareSSOContext(String securityDomainName) throws NoSuchDomainException {

        if (securityDomainName == null) {
            throw new IllegalArgumentException("SecurityDomanName cannot be null");
        }
        MutableSSOContext ctx = new MutableSSOContext();
        SecurityDomain sd = getSecurityDomain(securityDomainName);
        ctx.setSecurityDomain(sd);

        return ctx;
    }

    public SSOContext prepareDefaultSSOContext() {

        MutableSSOContext ctx = new MutableSSOContext();
        SecurityDomain sd = securityDomains.get(0);
        ctx.setSecurityDomain(sd);

        return ctx;
    }

    public SecurityDomain getSecurityDomain(String name) throws NoSuchDomainException {
        for (int i = 0; i < securityDomains.size(); i++) {
            SecurityDomain securityDomain = securityDomains.get(i);
            if (securityDomain.getName().equals(name))
                return securityDomain;
        }

        throw new NoSuchDomainException(name);
    }

    /**
     * This method logins a user into de SSO infrastructure.
     *
     * @param cred   the user credentials used as user identity proof.
     * @param scheme the authentication scheme name to be used for logging in the user.
     * @throws SSOAuthenticationException if authentication fails.
     * @throws SSOException               if an error occurs.
     */
    public SSOSession login(Credential[] cred, String scheme) throws SSOException, SSOAuthenticationException {

        try {
            SSOIdentityProvider ip = Lookup.getInstance().lookupSSOIdentityProvider();

            return ip.login(cred, scheme);

        } catch (AuthenticationFailureException e) {
            throw e;
        } catch (SSOAuthenticationException e) {
            throw e;
        } catch (SSOIdentityException e) {
            throw new SSOException(e.getMessage(), e);
        } catch (SSOSessionException e) {
            throw new SSOException(e.getMessage(), e);
        } catch (Exception e) {
            throw new SSOException(e.getMessage(), e);
        }
    }

    /**
     * Create an authentication assertion based on the supplied credentials. If assertion is successful a new session
     * is created for the subject which can be referenced through the corresponding assertion identifier.
     *
     * @param credentials
     * @param scheme
     * @return
     * @throws SSOException
     * @throws SSOAuthenticationException
     */
    public AuthenticationAssertion assertIdentity(Credential[] credentials, String scheme)
            throws SSOException, SSOAuthenticationException {

        try {
            SSOIdentityProvider ip = Lookup.getInstance().lookupSSOIdentityProvider();
            return ip.assertIdentity(credentials, scheme);
        } catch (AuthenticationFailureException e) {
            throw e;
        } catch (SSOAuthenticationException e) {
            throw e;
        } catch (Exception e) {
            throw new SSOException(e.getMessage(), e);
        }

    }

    /**
     * Create an authentication assertion from a previous existing and valid one.
     *
     * @param sessionId SSO session identifier for the session to be bound to the new assertion.
     * @return
     * @throws SSOException
     */
    public AuthenticationAssertion assertIdentity(String sessionId) throws SSOException {

        try {
            if (sessionId == null || sessionId.equals("")) {
                throw new SSOException("Session ID is empty!");
            }
            SSOIdentityProvider ip = Lookup.getInstance().lookupSSOIdentityProvider();
            return ip.assertIdentity(sessionId);
        } catch (Exception e) {
            throw new SSOException(e.getMessage(), e);
        }

    }

    /**
     * Logouts a user from the SSO infrastructure.
     *
     * @throws SSOException
     */
    public void logout() throws SSOException {

        try {

            SSOIdentityProvider ip = Lookup.getInstance().lookupSSOIdentityProvider();
            ip.logout();
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new SSOException(e.getMessage(), e);
        }
    }

    public Credential newCredential(String schemeName, String name, Object value)
            throws SSOAuthenticationException {
        try {

            SecurityDomain domain = Lookup.getInstance().lookupSecurityDomain();
            Authenticator au = domain.getAuthenticator();

            return au.newCredential(schemeName, name, value);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return null;
        }
    }

    public String getPrincipalName(String schemeName, Credential[] creds) throws SSOAuthenticationException {
        try {

            SecurityDomain domain = Lookup.getInstance().lookupSecurityDomain();
            Authenticator au = domain.getAuthenticator();

            Principal p = au.getPrincipal(schemeName, creds);
            if (p != null)
                return p.getName();

        } catch (Exception e) {
            logger.error(e.getMessage(), e);

        }
        return null;
    }

    /**
     * Finds a user associated to the given session.
     *
     * @param sessionId
     * @throws SSOException
     */
    public SSOUser findUserInSession(String sessionId) throws SSOException {
        try {

            if (sessionId == null || sessionId.equals("")) {
                throw new NoSuchSessionException("Session ID is empty!");
            }
            SecurityDomain domain = Lookup.getInstance().lookupSecurityDomain();
            SSOIdentityManager im = domain.getIdentityManager();
            return im.findUserInSession(sessionId);

        } catch (NoSuchSessionException e) {
            // Session is not valid ... (we could signal it with a specific exception)
            if (logger.isDebugEnabled())
                logger.debug(e.getMessage(), e);

            throw new SSOException(e.getMessage(), e);

        } catch (SSOIdentityException e) {
            if (logger.isDebugEnabled())
                logger.debug(e.getMessage(), e);

            throw new SSOException(e.getMessage(), e);

        } catch (Exception e) {
            logger.error(e.getMessage(), e);

            throw new SSOException(e.getMessage(), e);
        }
    }

    public SSORole[] findRolesByUsername(String username) throws SSOException {
        try {

            if (username == null || username.equals("")) {
                throw new SSOIdentityException("Username is empty!");
            }
            SecurityDomain domain = Lookup.getInstance().lookupSecurityDomain();
            SSOIdentityManager im = domain.getIdentityManager();
            return im.findRolesByUsername(username);

        } catch (SSOIdentityException e) {
            if (logger.isDebugEnabled())
                logger.debug(e.getMessage(), e);

            throw new SSOException(e.getMessage(), e);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new SSOException(e.getMessage(), e);
        }
    }

    public SSOSession findSession(String jossoSessionId) throws SSOException, NoSuchSessionException {
        try {
            if (jossoSessionId == null || jossoSessionId.equals("")) {
                throw new NoSuchSessionException("Session ID is empty!");
            }
            SecurityDomain domain = Lookup.getInstance().lookupSecurityDomain();
            SSOSessionManager sm = domain.getSessionManager();
            return sm.getSession(jossoSessionId);
        } catch (NoSuchSessionException e) {
            throw e;

        } catch (SSOIdentityException e) {
            if (logger.isDebugEnabled())
                logger.debug(e.getMessage(), e);

            throw new SSOException(e.getMessage(), e);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new SSOException(e.getMessage(), e);
        }
    }

    protected void notifyLoginFailed(SSOContext ctx, Credential[] credentials, String scheme, Throwable error) {
        try {
            // We expect a spetial Event Manager ...
            SSOSecurityEventManager em = (SSOSecurityEventManager) Lookup.getInstance().lookupSecurityDomain()
                    .getEventManager();
            em.fireAuthenticationFailureEvent(ctx.getUserLocation(), scheme, credentials, error);

        } catch (Exception e) {
            logger.error("Can't notify login failure : " + e.getMessage(), e);
        }
    }

    protected void notifyLoginSuccess(SSOContext ctx, String username, SSOSession session, String scheme) {
        try {
            // We expect a spetial Event Manager ...
            SSOSecurityEventManager em = (SSOSecurityEventManager) Lookup.getInstance().lookupSecurityDomain()
                    .getEventManager();
            em.fireAuthenticationSuccessEvent(ctx.getUserLocation(), scheme, username, session.getId());

        } catch (Exception e) {
            logger.error("Can't notify login success : " + e.getMessage(), e);
        }
    }

    private void notifyLogoutFail(SSOContext ctx, Throwable error) {
        try {
            // We expect a spetial Event Manager ...
            SSOSecurityEventManager em = (SSOSecurityEventManager) Lookup.getInstance().lookupSecurityDomain()
                    .getEventManager();
            em.fireLogoutFailureEvent(ctx.getUserLocation(), ctx.getSession().getUsername(),
                    ctx.getSession().getId(), error);

        } catch (Exception e) {
            logger.error("Can't notify login success : " + e.getMessage(), e);
        }
    }

    protected void notifyLogoutSuccess(SSOContext ctx) {
        try {
            // We expect a spetial Event Manager ...
            SSOSecurityEventManager em = (SSOSecurityEventManager) Lookup.getInstance().lookupSecurityDomain()
                    .getEventManager();
            em.fireLogoutSuccessEvent(ctx.getUserLocation(), ctx.getSession().getUsername(),
                    ctx.getSession().getId());

        } catch (Exception e) {
            logger.error("Can't notify login success : " + e.getMessage(), e);
        }

    }

    public SSOSecurityDomainSelector getSecurityDomainSelector() {
        return securityDomainSelector;
    }

    /**
     * @org.apache.xbean.Property alias="sso-domain-selector"
     *
     * @param securityDomainSelector
     */
    public void setSecurityDomainSelector(SSOSecurityDomainSelector securityDomainSelector) {
        this.securityDomainSelector = securityDomainSelector;
    }

    /**
     * @org.apache.xbean.Property alias="sso-domains-registry"
     *
     * @return
     */
    public SecurityDomainRegistry getSecurityDomainRegistry() {
        return securityDomainRegistry;
    }

    public void setSecurityDomainRegistry(SecurityDomainRegistry securityDomainRegistry) {
        this.securityDomainRegistry = securityDomainRegistry;
    }

    public void setSecurityDomains(List<SecurityDomain> sds) {
        securityDomains = sds;

        if (_initialized) {
            for (SecurityDomain sd : sds) {
                this.securityDomainRegistry.register(sd);
            }
        }

    }

    /**
     * @org.apache.xbean.Property alias="domains" nestedType="org.josso.SecurityDomain"
     */
    public List<SecurityDomain> getSecurityDomains() {
        return securityDomains;
    }

    protected Class loadClass(String fqcn) throws ClassNotFoundException {

        Class c = null;

        try {
            c = this.getClass().getClassLoader().loadClass(fqcn);
            return c;
        } catch (ClassNotFoundException e) {

        }

        try {
            c = Thread.currentThread().getContextClassLoader().loadClass(fqcn);
            return c;
        } catch (ClassNotFoundException e) {

        }

        try {
            Class.forName(fqcn);
            return c;
        } catch (ClassNotFoundException e) {

        }

        throw new ClassNotFoundException(fqcn);
    }

}