com.alfaariss.oa.authentication.identifying.IdentifyingAuthenticationMethod.java Source code

Java tutorial

Introduction

Here is the source code for com.alfaariss.oa.authentication.identifying.IdentifyingAuthenticationMethod.java

Source

/*
 * Asimba Server
 * 
 * Copyright (C) 2012 Asimba
 * Copyright (C) 2007-2009 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.authentication.identifying;

import java.util.List;
import java.util.Vector;

import javax.servlet.RequestDispatcher;
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.DetailedUserException;
import com.alfaariss.oa.OAException;
import com.alfaariss.oa.SystemErrors;
import com.alfaariss.oa.UserEvent;
import com.alfaariss.oa.UserException;
import com.alfaariss.oa.api.IComponent;
import com.alfaariss.oa.api.attribute.ISessionAttributes;
import com.alfaariss.oa.api.configuration.IConfigurationManager;
import com.alfaariss.oa.api.logging.IAuthority;
import com.alfaariss.oa.api.session.ISession;
import com.alfaariss.oa.api.session.SessionState;
import com.alfaariss.oa.api.user.IUser;
import com.alfaariss.oa.engine.core.Engine;
import com.alfaariss.oa.engine.core.server.Server;
import com.alfaariss.oa.engine.core.user.factory.IUserFactory;
import com.alfaariss.oa.sso.authentication.service.IServiceAuthenticationMethod;
import com.alfaariss.oa.sso.authentication.web.IWebAuthenticationMethod;
import com.alfaariss.oa.util.logging.UserEventLogItem;

/**
 * The identifying authentication method is a method that authenticates users 
 * that are known in the user factory. 
 * 
 * @author EVB
 * @author MHO
 * @author JVG
 * @author Alfa & Ariss
 * 
 */
public class IdentifyingAuthenticationMethod implements IWebAuthenticationMethod, IServiceAuthenticationMethod {
    private final static String AUTHORITY_NAME = "IdentifyingAuthenticationMethod_";
    private final static String TEMPLATE_ID_PARAM = "user_id";
    private static final String DEFAULT_JSP_IDENTIFYING = "/ui/sso/authn/identifying/identifying.jsp";
    private Log _logger;
    private Log _eventLogger;

    private String _sMethodID;
    private boolean _bEnabled;
    private String _sFriendlyName;

    private String _sTemplatePath;

    private IConfigurationManager _configurationManager;
    private IUserFactory _oUserFactory;
    private Engine _oaEngine;
    private int _iMaxRetries;

    /**
     * Creates an object instance.
     */
    public IdentifyingAuthenticationMethod() {
        _logger = LogFactory.getLog(IdentifyingAuthenticationMethod.class);
        _eventLogger = LogFactory.getLog(Engine.EVENT_LOGGER);
    }

    /**
     * Restarts the method.
     * @see com.alfaariss.oa.api.IComponent#restart(org.w3c.dom.Element)
     */
    @Override
    public void restart(Element eConfig) throws OAException {
        synchronized (this) {
            stop();
            start(_configurationManager, eConfig);
        }
    }

    /**
     * Starts the method.
     * @see IComponent#start(IConfigurationManager, org.w3c.dom.Element)
     */
    @Override
    public void start(IConfigurationManager oConfigurationManager, Element eConfig) throws OAException {
        try {
            if (eConfig == null || oConfigurationManager == null) {
                _bEnabled = false;
                _logger.error("No configuration supplied");
                throw new OAException(SystemErrors.ERROR_CONFIG_READ);
            }
            _configurationManager = oConfigurationManager;

            _sMethodID = _configurationManager.getParam(eConfig, "id");
            if (_sMethodID == null || _sMethodID.equals("")) {
                _logger.error("No 'id' found in 'method' section in configuration");
                throw new OAException(SystemErrors.ERROR_CONFIG_READ);
            }

            _sFriendlyName = _configurationManager.getParam(eConfig, "friendlyname");
            if (_sFriendlyName == null) {
                _logger.error("No 'friendlyname' parameter found in configuration");
                throw new OAException(SystemErrors.ERROR_CONFIG_READ);
            }

            _bEnabled = true;
            String sEnabled = _configurationManager.getParam(eConfig, "enabled");
            if (sEnabled != null) {
                if (sEnabled.equalsIgnoreCase("FALSE"))
                    _bEnabled = false;
                else if (!sEnabled.equalsIgnoreCase("TRUE")) {
                    _logger.error("Unknown value in 'enabled' configuration item: " + sEnabled);
                    throw new OAException(SystemErrors.ERROR_CONFIG_READ);
                }
            }

            if (_bEnabled) {
                _oaEngine = Engine.getInstance();

                _oUserFactory = _oaEngine.getUserFactory();
                if (_oUserFactory == null || !_oUserFactory.isEnabled()) {
                    _logger.error("User Factory is disabled");
                    throw new OAException(SystemErrors.ERROR_CONFIG_READ);
                }

                String sRetries = _configurationManager.getParam(eConfig, "retries");
                if (sRetries == null) {
                    _logger.error("No 'retries' item found in 'method' configuration with id: " + _sMethodID);
                    throw new OAException(SystemErrors.ERROR_CONFIG_READ);
                }

                try {
                    _iMaxRetries = Integer.parseInt(sRetries);
                    if (_iMaxRetries < -1) {
                        _logger.error("Invalid 'retries' item found in 'method' configuration: " + sRetries);
                        throw new OAException(SystemErrors.ERROR_CONFIG_READ);
                    }
                } catch (NumberFormatException e) {
                    _logger.error("Invalid 'retries' item found in 'method' configuration: " + sRetries);
                    throw new OAException(SystemErrors.ERROR_CONFIG_READ);
                }

                _logger.info("Configured retries: " + _iMaxRetries);

                Element eTemplate = _configurationManager.getSection(eConfig, "template");
                if (eTemplate == null) {
                    _sTemplatePath = DEFAULT_JSP_IDENTIFYING;
                    _logger.warn("No optional 'template' section in 'method' configuration with id: " + _sMethodID
                            + ", using default");
                } else {
                    _sTemplatePath = _configurationManager.getParam(eTemplate, "path");
                    if (_sTemplatePath == null) {

                        _logger.error(
                                "No 'path' parameter found in 'template' section within 'method' configuration with id: "
                                        + _sMethodID);
                        throw new OAException(SystemErrors.ERROR_CONFIG_READ);
                    }
                }
                _logger.info("Using JSP: " + _sTemplatePath);
            }
        } catch (OAException e) {
            throw e;
        } catch (Exception e) {
            _logger.fatal("Internal error during start", e);
            throw new OAException(SystemErrors.ERROR_INTERNAL);
        }
    }

    /**
     * Stops the method.
     * @see com.alfaariss.oa.api.IComponent#stop()
     */
    @Override
    public void stop() {
        _sTemplatePath = null;
        _sMethodID = null;
        _oaEngine = null;
        _oUserFactory = null;
        _bEnabled = false;
    }

    /**
     * @see com.alfaariss.oa.api.IManagebleItem#getID()
     */
    @Override
    public String getID() {
        return _sMethodID;
    }

    /**
     * Returns TRUE if module is enabled.
     * @see com.alfaariss.oa.api.IManagebleItem#isEnabled()
     */
    @Override
    public boolean isEnabled() {
        return _bEnabled;
    }

    /**
     * @see com.alfaariss.oa.api.IManagebleItem#getFriendlyName()
     */
    @Override
    public String getFriendlyName() {
        return _sFriendlyName;
    }

    /**
     * @see IAuthority#getAuthority()
     */
    @Override
    public String getAuthority() {
        return AUTHORITY_NAME + _sMethodID;
    }

    /**'
     * TODO add user id mapping support (MHO)
     * @see IWebAuthenticationMethod#authenticate(HttpServletRequest, 
     *  HttpServletResponse, ISession)
     */
    @Override
    public UserEvent authenticate(HttpServletRequest oRequest, HttpServletResponse oResponse, ISession oSession)
            throws OAException {
        UserEvent oUserEvent = UserEvent.AUTHN_METHOD_FAILED;
        String sUserid = null;
        try {
            //DD If a user is available in the session (e.g. from SSO Session) it is leading and the user form is omitted 
            IUser oUser = oSession.getUser();
            if (oUser == null) //No user identified yet
            {
                //Check forced user
                sUserid = oSession.getForcedUserID();
                if (sUserid != null) {
                    oUser = _oUserFactory.getUser(sUserid);
                    if (oUser == null) {
                        throw new UserException(UserEvent.AUTHN_METHOD_NOT_SUPPORTED);
                    }
                    //DD If a forced user is available in the session the user form is omitted
                } else //get user id from request
                {
                    sUserid = oRequest.getParameter(TEMPLATE_ID_PARAM);
                    if (sUserid == null || sUserid.trim().length() == 0) {
                        //No user submitted yet
                        throw new DetailedUserException(UserEvent.AUTHN_METHOD_IN_PROGRESS, new Vector<Enum>());
                    }

                    //Validate submitted user
                    oUser = _oUserFactory.getUser(sUserid);
                    if (oUser == null) {
                        //DD Retries == -1 means unlimited retries  
                        if (_iMaxRetries == -1) {
                            throw new DetailedUserException(UserEvent.AUTHN_METHOD_IN_PROGRESS,
                                    Warnings.NO_SUCH_USER_FOUND);
                        }

                        ISessionAttributes oAttributes = oSession.getAttributes();
                        //Update retries
                        Integer intRetries = (Integer) oAttributes.get(IdentifyingAuthenticationMethod.class,
                                IWebAuthenticationMethod.RETRIES_ATTRIBUTE_NAME);
                        if (intRetries != null) {
                            if (intRetries.intValue() < _iMaxRetries)
                                intRetries++;
                        } else
                            intRetries = new Integer(0);

                        //Validate retries                    
                        if (intRetries.intValue() >= _iMaxRetries) {
                            throw new UserException(UserEvent.USER_UNKNOWN);
                        }
                        Vector<Enum> warnings = new Vector<Enum>();
                        warnings.add(Warnings.NO_SUCH_USER_FOUND);
                        if (intRetries == _iMaxRetries - 1)
                            warnings.add(Warnings.ONE_RETRY_LEFT);

                        //Update attributes
                        oAttributes.put(IdentifyingAuthenticationMethod.class,
                                IWebAuthenticationMethod.RETRIES_ATTRIBUTE_NAME, intRetries);

                        throw new DetailedUserException(UserEvent.AUTHN_METHOD_IN_PROGRESS, warnings);
                    }
                }
                if (!oUser.isEnabled()) {
                    throw new UserException(UserEvent.USER_DISABLED);
                }
            }
            if (!oUser.isAuthenticationRegistered(_sMethodID)) {
                throw new UserException(UserEvent.AUTHN_METHOD_NOT_REGISTERED);
            }

            //Everything okay
            oSession.setUser(oUser);

            _eventLogger.info(new UserEventLogItem(oSession, oRequest.getRemoteAddr(),
                    UserEvent.AUTHN_METHOD_SUCCESSFUL, this, null));

            oUserEvent = UserEvent.AUTHN_METHOD_SUCCESSFUL;
        } catch (DetailedUserException e) {
            //Non blocking error occurred - >show page                   
            _eventLogger.info(new UserEventLogItem(oSession, oRequest.getRemoteAddr(), e.getEvent(), this,
                    e.getDetails().toString()));
            forwardUser(oRequest, oResponse, oSession, e.getDetails());
            oUserEvent = e.getEvent();
        } catch (UserException e) {
            //Blocking error occurred
            _eventLogger.info(new UserEventLogItem(oSession, oRequest.getRemoteAddr(), e.getEvent(), this, null));
            oUserEvent = e.getEvent();
        } catch (OAException e) //Internal error
        {
            _eventLogger.info(
                    new UserEventLogItem(oSession, oRequest.getRemoteAddr(), UserEvent.INTERNAL_ERROR, this, null));
            //already logged to system log. 
            throw e;
        } catch (Exception e) //unknown error
        {
            if (oSession != null)
                _eventLogger.info(new UserEventLogItem(oSession, oRequest.getRemoteAddr(), UserEvent.INTERNAL_ERROR,
                        this, null));
            else
                _eventLogger.info(new UserEventLogItem(null, null, null, UserEvent.INTERNAL_ERROR, null,
                        oRequest.getRemoteAddr(), null, this, null));

            _logger.fatal("Fatal error during authentication", e);
            throw new OAException(SystemErrors.ERROR_INTERNAL);
        }

        return oUserEvent;
    }

    /**
     * @see IServiceAuthenticationMethod#authenticate(java.lang.String, byte[])
     */
    @Override
    public UserEvent authenticate(String sUserID, byte[] baCredentials) throws OAException {
        IUser oUser = _oUserFactory.getUser(sUserID);
        if (oUser == null) {
            _eventLogger.info(new UserEventLogItem(null, null, SessionState.USER_UNKNOWN, UserEvent.USER_UNKNOWN,
                    sUserID, null, null, null, null));

            return UserEvent.USER_UNKNOWN;
        }

        if (!oUser.isEnabled()) {
            _eventLogger.info(new UserEventLogItem(null, null, SessionState.USER_BLOCKED, UserEvent.USER_DISABLED,
                    sUserID, null, null, null, null));

            return UserEvent.USER_DISABLED;
        }

        if (!oUser.isAuthenticationRegistered(_sMethodID)) {
            _eventLogger.info(new UserEventLogItem(null, null, SessionState.AUTHN_FAILED,
                    UserEvent.AUTHN_METHOD_NOT_REGISTERED, sUserID, null, null, null, null));

            return UserEvent.AUTHN_METHOD_FAILED;
        }

        _eventLogger.info(new UserEventLogItem(null, null, SessionState.AUTHN_OK, UserEvent.AUTHN_METHOD_SUCCESSFUL,
                sUserID, null, null, null, null));

        return UserEvent.AUTHN_METHOD_SUCCESSFUL;
    }

    private void forwardUser(HttpServletRequest oRequest, HttpServletResponse oResponse, ISession oSession,
            List<Enum> warnings) throws OAException {
        try {
            oRequest.setAttribute(ISession.ID_NAME, oSession.getId());
            oRequest.setAttribute(ISession.LOCALE_NAME, oSession.getLocale());

            if (warnings != null) {
                oRequest.setAttribute(DetailedUserException.DETAILS_NAME, warnings);
            }

            oRequest.setAttribute(IWebAuthenticationMethod.AUTHN_METHOD_ATTRIBUTE_NAME, _sFriendlyName);
            oRequest.setAttribute(Server.SERVER_ATTRIBUTE_NAME, _oaEngine.getServer());

            RequestDispatcher oDispatcher = oRequest.getRequestDispatcher(_sTemplatePath);
            if (oDispatcher == null) {
                _logger.warn("There is no request dispatcher supported with name: " + _sTemplatePath);
                throw new OAException(SystemErrors.ERROR_INTERNAL);
            }

            _logger.debug("Forward user to: " + _sTemplatePath);

            oSession.persist();

            oDispatcher.forward(oRequest, oResponse);
        } catch (OAException e) {
            throw e;
        } catch (Exception e) {
            if (oSession != null)
                _eventLogger.info(new UserEventLogItem(oSession, oRequest.getRemoteAddr(), UserEvent.INTERNAL_ERROR,
                        this, null));
            else
                _eventLogger.info(new UserEventLogItem(null, null, null, UserEvent.INTERNAL_ERROR, null,
                        oRequest.getRemoteAddr(), null, this, null));

            _logger.fatal("Internal error during forward", e);
            throw new OAException(SystemErrors.ERROR_INTERNAL);
        }
    }

}