com.alfaariss.oa.sso.authentication.web.AuthenticationManager.java Source code

Java tutorial

Introduction

Here is the source code for com.alfaariss.oa.sso.authentication.web.AuthenticationManager.java

Source

/*
 * Asimba Server
 * 
 * Copyright (C) 2012 Asimba
 * Copyright (C) 2007-2008 Alfa & Ariss B.V.
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program 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 Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see www.gnu.org/licenses
 * 
 * Asimba - Serious Open Source SSO - More information on www.asimba.org
 * 
 */
package com.alfaariss.oa.sso.authentication.web;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Element;

import com.alfaariss.oa.OAException;
import com.alfaariss.oa.SystemErrors;
import com.alfaariss.oa.api.IComponent;
import com.alfaariss.oa.api.attribute.ISessionAttributes;
import com.alfaariss.oa.api.authentication.IAuthenticationMethod;
import com.alfaariss.oa.api.authentication.IAuthenticationProfile;
import com.alfaariss.oa.api.configuration.IConfigurationManager;
import com.alfaariss.oa.api.session.ISession;
import com.alfaariss.oa.api.session.SessionState;
import com.alfaariss.oa.engine.core.authentication.AuthenticationMethod;
import com.alfaariss.oa.sso.SSOException;

/**
 * Manager for loading authentication methods and executing 
 * authentication profiles.
 *
 * This manager is called by the engine. At start-up, this manager
 * is responsible for loading the classes for the different authentication
 * methods that are defined in the OpenASelect main configuration
 * file. At run-time, the manager can be asked to run an authentication
 * profile. It will load the authentication profile details and delegate
 * the actual authentication steps to the corresponding authentication methods.
 * 
 * @author MHO
 * @author JRE
 * @author Alfa & Ariss
 *
 */
public class AuthenticationManager implements IComponent {
    private final static String ATTRIBUTE_CURRENT_METHOD = "CURRENT_METHOD";
    private Map<String, IWebAuthenticationMethod> _mapAuthenticationMethods;
    private Log _logger;
    private IConfigurationManager _configManager;

    /**
     * AuthenticationManager default constructor.
     */
    public AuthenticationManager() {
        _logger = LogFactory.getLog(AuthenticationManager.class);
        _mapAuthenticationMethods = new HashMap<String, IWebAuthenticationMethod>();
    }

    /**
     * Authenticates a user by an authentication profile.
     *
     * @param oSelectedAuthNProfile The Authentication profile selected by the user.
     * @param oRequest The servlet request.
     * @param oResponse The servlet response.
     * @param oSession The user session object.
     * @throws SSOException if authentication fails 
     *  due to internal error in manager itself.
     * @throws OAException if authentication fails due to internal error.
     */
    public void authenticate(IAuthenticationProfile oSelectedAuthNProfile, HttpServletRequest oRequest,
            HttpServletResponse oResponse, ISession oSession) throws SSOException, OAException {
        try {
            if (oSelectedAuthNProfile == null)
                throw new IllegalArgumentException("No selected authN profile supplied");

            if (!oSelectedAuthNProfile.isEnabled()) {
                _logger.error("Authentication profile is disabled: " + oSelectedAuthNProfile.getID());
                throw new SSOException(SystemErrors.ERROR_INTERNAL);
            }

            List<IAuthenticationMethod> listMethods = oSelectedAuthNProfile.getAuthenticationMethods();

            IAuthenticationMethod oAuthMethodBean = null;
            ISessionAttributes oAttributes = oSession.getAttributes();

            SessionState oState = oSession.getState();
            if (oState == SessionState.AUTHN_SELECTION_OK) {//get first authentication method which is enabled
                oAuthMethodBean = getAuthenticationMethod(listMethods, oAuthMethodBean,
                        oSelectedAuthNProfile.getID());
                oAttributes.put(AuthenticationManager.class, ATTRIBUTE_CURRENT_METHOD, oAuthMethodBean);
                oSession.setState(SessionState.AUTHN_IN_PROGRESS);
            } else if (oState == SessionState.AUTHN_IN_PROGRESS) {//get authentication method which previously returned AUTHN_IN_PROGRESS
                oAuthMethodBean = (AuthenticationMethod) oAttributes.get(AuthenticationManager.class,
                        ATTRIBUTE_CURRENT_METHOD);
            } else {
                _logger.error("Session state invalid: " + oState);
                throw new SSOException(SystemErrors.ERROR_INTERNAL);
            }

            IWebAuthenticationMethod oWebAuthMethod = _mapAuthenticationMethods.get(oAuthMethodBean.getID());
            if (oWebAuthMethod == null) {
                _logger.error("No authentication method found with id: " + oAuthMethodBean.getID());
                throw new SSOException(SystemErrors.ERROR_INTERNAL);
            }

            while (oSession.getState() == SessionState.AUTHN_IN_PROGRESS) {
                if (!oWebAuthMethod.isEnabled()) {
                    _logger.error("Authentication method is disabled: " + oWebAuthMethod.getID());
                    throw new SSOException(SystemErrors.ERROR_INTERNAL);
                }

                switch (oWebAuthMethod.authenticate(oRequest, oResponse, oSession)) {
                case AUTHN_METHOD_SUCCESSFUL: {
                    oAuthMethodBean = getAuthenticationMethod(listMethods, oAuthMethodBean,
                            oSelectedAuthNProfile.getID());
                    if (oAuthMethodBean != null) {
                        oAttributes.put(AuthenticationManager.class, ATTRIBUTE_CURRENT_METHOD, oAuthMethodBean);
                        if (!_mapAuthenticationMethods.containsKey(oAuthMethodBean.getID())) {
                            _logger.error("Authentication method not available: " + oAuthMethodBean.getID());
                            throw new SSOException(SystemErrors.ERROR_INTERNAL);
                        }
                        oWebAuthMethod = _mapAuthenticationMethods.get(oAuthMethodBean.getID());
                    } else
                        oSession.setState(SessionState.AUTHN_OK);

                    break;
                }
                case AUTHN_METHOD_IN_PROGRESS: {
                    return;
                }
                case USER_UNKNOWN: {
                    oSession.setState(SessionState.USER_UNKNOWN);
                    break;
                }
                case USER_DISABLED: {
                    oSession.setState(SessionState.USER_BLOCKED);
                    break;
                }
                case USER_CANCELLED: {
                    oSession.setState(SessionState.USER_CANCELLED);
                    break;
                }
                case AUTHN_METHOD_NOT_REGISTERED:
                case AUTHN_METHOD_NOT_SUPPORTED: {
                    oSession.setState(SessionState.AUTHN_NOT_SUPPORTED);
                    break;
                }
                case REQUEST_INVALID:
                default: {
                    oSession.setState(SessionState.AUTHN_FAILED);
                }
                }
            }
        } catch (OAException e) {
            throw e;
        } catch (Exception e) {
            _logger.error("Internal error during authentication", e);
            throw new SSOException(SystemErrors.ERROR_INTERNAL);
        }
    }

    /**
     * @see IComponent#restart(org.w3c.dom.Element)
     */
    @Override
    public void restart(Element eConfig) throws OAException {
        synchronized (this) {
            stop();
            start(_configManager, eConfig);
        }
    }

    /**
     * @see IComponent#start(IConfigurationManager, org.w3c.dom.Element)
     */
    @Override
    public void start(IConfigurationManager oConfigurationManager, Element eConfig) throws OAException {
        try {
            _configManager = oConfigurationManager;

            Element eMethods = _configManager.getSection(eConfig, "methods");
            if (eMethods == null) {
                _logger.error("No 'methods' section found in configuration");
                throw new OAException(SystemErrors.ERROR_CONFIG_READ);
            }

            Element eMethod = _configManager.getSection(eMethods, "method");
            while (eMethod != null) {
                IWebAuthenticationMethod oAuthenticationMethod = createAuthenticationMethod(eMethod);
                if (!oAuthenticationMethod.isEnabled()) {
                    _logger.debug("Authentication method is disabled: " + oAuthenticationMethod.getID());
                } else {
                    if (_mapAuthenticationMethods.containsKey(oAuthenticationMethod.getID())) {
                        _logger.error("Authentication method is not unique: " + oAuthenticationMethod.getID());
                        throw new OAException(SystemErrors.ERROR_CONFIG_READ);
                    }

                    _mapAuthenticationMethods.put(oAuthenticationMethod.getID(), oAuthenticationMethod);
                }

                eMethod = _configManager.getNextSection(eMethod);
            }
        } catch (OAException e) {
            throw e;
        } catch (Exception e) {
            _logger.fatal("Internal error during object creation", e);
            throw new OAException(SystemErrors.ERROR_INTERNAL);
        }
    }

    /**
     * @see IComponent#stop()
     */
    @Override
    public void stop() {
        if (_mapAuthenticationMethods != null) {
            for (IWebAuthenticationMethod oMethod : _mapAuthenticationMethods.values())
                oMethod.stop();

            _mapAuthenticationMethods.clear();
        }
    }

    /**
     * Returns all Authentication Methods. 
     * @return An unmodifyable collection with Authentication Methods.
     * @since 1.4
     */
    public Map<String, IWebAuthenticationMethod> getAuthenticationMethods() {
        return Collections.unmodifiableMap(_mapAuthenticationMethods);
    }

    private IWebAuthenticationMethod createAuthenticationMethod(Element eMethod) throws SSOException {
        IWebAuthenticationMethod oAuthenticationMethod = null;
        try {
            String sClass = _configManager.getParam(eMethod, "class");
            if (sClass == null) {
                _logger.error("No 'class' item found in 'methods' section found in configuration");
                throw new SSOException(SystemErrors.ERROR_CONFIG_READ);
            }

            Class cMethod = null;
            try {
                cMethod = Class.forName(sClass);
            } catch (Exception e) {
                _logger.error("Class not found: " + sClass, e);
                throw new SSOException(SystemErrors.ERROR_CONFIG_READ);
            }

            try {
                oAuthenticationMethod = (IWebAuthenticationMethod) cMethod.newInstance();
            } catch (Exception e) {
                _logger.error("Could not create instance of " + sClass, e);
                throw new SSOException(SystemErrors.ERROR_CONFIG_READ);
            }

            oAuthenticationMethod.start(_configManager, eMethod);
        } catch (SSOException e) {
            throw e;
        } catch (Exception e) {
            _logger.fatal("Internal error during object creation", e);
            throw new SSOException(SystemErrors.ERROR_INTERNAL);
        }
        return oAuthenticationMethod;
    }

    private IAuthenticationMethod getAuthenticationMethod(List<IAuthenticationMethod> listMethods,
            IAuthenticationMethod currentMethod, String sAuthNProfile) throws SSOException {
        IAuthenticationMethod oMethod = null;
        int iCurrentMethod = 0;
        int iMax = listMethods.size();
        if (iMax == 0) {
            _logger.error("No authentication methods available in pool: " + sAuthNProfile);
            throw new SSOException(SystemErrors.ERROR_INTERNAL);
        }

        if (currentMethod != null) {
            iCurrentMethod = listMethods.indexOf(currentMethod);
            if (iCurrentMethod == -1) {
                _logger.error("Current authentication method unavailable: " + currentMethod.getID());
                throw new SSOException(SystemErrors.ERROR_INTERNAL);
            }
            iCurrentMethod++;
        }
        if (iCurrentMethod < iMax)
            oMethod = listMethods.get(iCurrentMethod);

        return oMethod;
    }
}