org.alfresco.web.app.servlet.AuthenticationHelper.java Source code

Java tutorial

Introduction

Here is the source code for org.alfresco.web.app.servlet.AuthenticationHelper.java

Source

/*
 * #%L
 * Alfresco Repository WAR Community
 * %%
 * Copyright (C) 2005 - 2016 Alfresco Software Limited
 * %%
 * This file is part of the Alfresco software. 
 * If the software was purchased under a paid Alfresco license, the terms of 
 * the paid license agreement will prevail.  Otherwise, the software is 
 * provided under the following open source license terms:
 * 
 * Alfresco 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 3 of the License, or
 * (at your option) any later version.
 * 
 * Alfresco 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
 * #L%
 */
package org.alfresco.web.app.servlet;

import java.io.IOException;
import java.io.UnsupportedEncodingException;

import javax.faces.context.FacesContext;
import javax.servlet.ServletContext;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.SessionUser;
import org.alfresco.repo.management.subsystems.ActivateableBean;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.external.RemoteUserMapper;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.webdav.auth.AuthenticationDriver;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.web.app.Application;
import org.alfresco.web.app.portlet.AlfrescoFacesPortlet;
import org.alfresco.web.bean.LoginBean;
import org.alfresco.web.bean.repository.User;
import org.alfresco.web.bean.users.UserPreferencesBean;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.surf.util.Base64;
import org.springframework.extensions.surf.util.I18NUtil;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

/**
 * Helper to authenticate the current user using available Ticket information.
 * <p>
 * User information is looked up in the Session. If found the ticket is retrieved and validated.
 * If the ticket is invalid then a redirect is performed to the login page.
 * <p>
 * If no User info is found then a search will be made for a previous username stored in a Cookie
 * value. If the username if found then a redirect to the Login page will occur. If no username
 * is found then Guest access login will be attempted by the system. Guest access can be forced
 * with the appropriate method call.  
 * 
 * @author Kevin Roast
 */
public final class AuthenticationHelper {
    /** session variables */
    public static final String AUTHENTICATION_USER = AuthenticationDriver.AUTHENTICATION_USER;
    public static final String SESSION_USERNAME = "_alfLastUser";
    public static final String SESSION_INVALIDATED = "_alfSessionInvalid";

    /** JSF bean IDs */
    public static final String LOGIN_BEAN = "LoginBean";

    /** public service bean IDs **/
    private static final String AUTHENTICATION_SERVICE = "AuthenticationService";
    private static final String AUTHENTICATION_COMPONENT = "AuthenticationComponent";
    private static final String REMOTE_USER_MAPPER = "RemoteUserMapper";
    private static final String UNPROTECTED_AUTH_SERVICE = "authenticationService";
    private static final String PERSON_SERVICE = "personService";
    private static final String AUTHORITY_SERVICE = "AuthorityService";

    /** cookie names */
    private static final String COOKIE_ALFUSER = "alfUser0";

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

    /**
     * Does all the stuff you need to do after successfully authenticating/validating a user ticket to set up the request
     * thread. A useful utility method for an authentication filter.
     * 
     * @param sc
     *           the servlet context
     * @param req
     *           the request
     * @param res
     *           the response
     */
    public static void setupThread(ServletContext sc, HttpServletRequest req, HttpServletResponse res,
            boolean useInterfaceLanguage) {
        if (logger.isDebugEnabled())
            logger.debug("Setting up the request thread.");
        // setup faces context
        FacesContext fc = Application.inPortalServer() ? AlfrescoFacesPortlet.getFacesContext(req)
                : FacesHelper.getFacesContext(req, res, sc);

        // Set the current locale and language (overriding the one already decoded from the Accept-Language header
        if (WebApplicationContextUtils.getRequiredWebApplicationContext(sc)
                .containsBean(Application.BEAN_CONFIG_SERVICE)) {
            I18NUtil.setLocale(Application.getLanguage(req.getSession(),
                    Application.getClientConfig(fc).isLanguageSelect() && useInterfaceLanguage));
        } else {
            Application.getLanguage(req.getSession(), false);
        }
        if (logger.isDebugEnabled())
            logger.debug("The general locale is : " + I18NUtil.getLocale());

        // Programatically retrieve the UserPreferencesBean from JSF
        UserPreferencesBean userPreferencesBean = (UserPreferencesBean) FacesHelper.getManagedBean(fc,
                "UserPreferencesBean");
        if (logger.isDebugEnabled())
            logger.debug("The UserPreferencesBean is : " + userPreferencesBean);
        if (userPreferencesBean != null) {
            String contentFilterLanguageStr = userPreferencesBean.getContentFilterLanguage();
            if (contentFilterLanguageStr != null) {
                // Set the locale for the method interceptor for MLText properties
                I18NUtil.setContentLocale(I18NUtil.parseLocale(contentFilterLanguageStr));
            } else {
                // Nothing has been selected, so remove the content filter
                I18NUtil.setContentLocale(null);
            }
            if (logger.isDebugEnabled())
                logger.debug("The content locale is : " + I18NUtil.getContentLocale());
        }
    }

    /**
     * Helper to authenticate the current user using session based Ticket information.
     * <p>
     * User information is looked up in the Session. If found the ticket is retrieved and validated.
     * If no User info is found or the ticket is invalid then a redirect is performed to the login page. 
     * 
     * @param forceGuest       True to force a Guest login attempt
     * 
     * @return AuthenticationStatus result.
     */
    public static AuthenticationStatus authenticate(ServletContext sc, HttpServletRequest req,
            HttpServletResponse res, boolean forceGuest) throws IOException {
        return authenticate(sc, req, res, forceGuest, true);
    }

    /**
     * Helper to authenticate the current user using session based Ticket information.
     * <p>
     * User information is looked up in the Session. If found the ticket is retrieved and validated.
     * If no User info is found or the ticket is invalid then a redirect is performed to the login page. 
     * 
     * @param forceGuest       True to force a Guest login attempt
     * @param allowGuest       True to allow the Guest user if no user object represent
     * 
     * @return AuthenticationStatus result.
     */
    public static AuthenticationStatus authenticate(ServletContext sc, HttpServletRequest req,
            HttpServletResponse res, boolean forceGuest, boolean allowGuest) throws IOException {
        if (logger.isDebugEnabled())
            logger.debug("Authenticating the current user using session based Ticket information.");
        // retrieve the User object
        User user = getUser(sc, req, res);

        HttpSession session = req.getSession();

        // get the login bean if we're not in the portal
        LoginBean loginBean = null;
        if (Application.inPortalServer() == false) {
            if (logger.isDebugEnabled())
                logger.debug("We're not in the portal, getting the login bean.");
            loginBean = (LoginBean) session.getAttribute(LOGIN_BEAN);
        }

        // setup the authentication context
        WebApplicationContext wc = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
        AuthenticationService auth = (AuthenticationService) wc.getBean(AUTHENTICATION_SERVICE);

        if (logger.isDebugEnabled())
            logger.debug("Force guest is: " + forceGuest);
        if (user == null || forceGuest) {
            if (logger.isDebugEnabled())
                logger.debug("The user is null.");
            // Check for the session invalidated flag - this is set by the Logout action in the LoginBean
            // it signals a forced Logout and means we should not immediately attempt a relogin as Guest.
            // The attribute is removed from the session by the login.jsp page after the Cookie containing
            // the last stored username string is cleared.
            if (session.getAttribute(AuthenticationHelper.SESSION_INVALIDATED) == null) {
                if (logger.isDebugEnabled())
                    logger.debug("The session is not invalidated.");
                Cookie authCookie = getAuthCookie(req);
                if (allowGuest == true && (authCookie == null || forceGuest)) {
                    if (logger.isDebugEnabled())
                        logger.debug("No previous authentication or forced Guest - attempt Guest access.");
                    try {
                        auth.authenticateAsGuest();

                        // if we get here then Guest access was allowed and successful
                        setUser(sc, req, AuthenticationUtil.getGuestUserName(), auth.getCurrentTicket(), false);

                        // Set up the thread context
                        setupThread(sc, req, res, true);

                        // remove the session invalidated flag
                        session.removeAttribute(AuthenticationHelper.SESSION_INVALIDATED);

                        if (logger.isDebugEnabled())
                            logger.debug("Successfully authenticated as guest.");
                        // it is the responsibilty of the caller to handle the Guest return status
                        return AuthenticationStatus.Guest;
                    } catch (AuthenticationException guestError) {
                        if (logger.isDebugEnabled())
                            logger.debug(
                                    "An AuthenticationException occurred, expected if Guest access not allowed - continue to login page as usual",
                                    guestError);
                    } catch (AccessDeniedException accessError) {
                        // Guest is unable to access either properties on Person
                        AuthenticationService unprotAuthService = (AuthenticationService) wc
                                .getBean(UNPROTECTED_AUTH_SERVICE);
                        unprotAuthService.invalidateTicket(unprotAuthService.getCurrentTicket());
                        unprotAuthService.clearCurrentSecurityContext();
                        logger.warn("Unable to login as Guest: ", accessError);
                    } catch (Throwable e) {
                        // Some other kind of serious failure to report
                        AuthenticationService unprotAuthService = (AuthenticationService) wc
                                .getBean(UNPROTECTED_AUTH_SERVICE);
                        unprotAuthService.invalidateTicket(unprotAuthService.getCurrentTicket());
                        unprotAuthService.clearCurrentSecurityContext();
                        throw new AlfrescoRuntimeException("Failed to authenticate as Guest user.", e);
                    }
                }
            }
            if (logger.isDebugEnabled())
                logger.debug("Session invalidated - return to login screen.");
            return AuthenticationStatus.Failure;
        } else {
            if (logger.isDebugEnabled())
                logger.debug("The user is: " + user.getUserName());
            // set last authentication username cookie value
            String loginName;
            if (loginBean != null && (loginName = loginBean.getUsernameInternal()) != null) {
                if (logger.isDebugEnabled())
                    logger.debug("Set last authentication username cookie value");
                setUsernameCookie(req, res, loginName);
            }

            // Set up the thread context
            setupThread(sc, req, res, true);

            return AuthenticationStatus.Success;
        }
    }

    /**
     * Helper to authenticate the current user using the supplied Ticket value.
     * 
     * @return true if authentication successful, false otherwise.
     */
    public static AuthenticationStatus authenticate(ServletContext context, HttpServletRequest httpRequest,
            HttpServletResponse httpResponse, String ticket) throws IOException {
        if (logger.isDebugEnabled())
            logger.debug("Authenticate the current user using the supplied Ticket value.");
        // setup the authentication context
        WebApplicationContext wc = WebApplicationContextUtils.getRequiredWebApplicationContext(context);
        AuthenticationService auth = (AuthenticationService) wc.getBean(AUTHENTICATION_SERVICE);
        HttpSession session = httpRequest.getSession();
        try {
            // If we already have a cached user, make sure it is for the right ticket
            SessionUser user = (SessionUser) session.getAttribute(AuthenticationHelper.AUTHENTICATION_USER);
            if (user != null && !user.getTicket().equals(ticket)) {
                if (logger.isDebugEnabled())
                    logger.debug("Found a previously-cached user with the wrong identity.");
                session.removeAttribute(AUTHENTICATION_USER);
                if (!Application.inPortalServer()) {
                    if (logger.isDebugEnabled())
                        logger.debug("The server is not running in a portal, invalidating session.");
                    session.invalidate();
                    session = httpRequest.getSession();
                }
                user = null;
            }

            // Validate the ticket and associate it with the session
            auth.validate(ticket);

            if (user == null) {
                if (logger.isDebugEnabled())
                    logger.debug("Ticket is valid; caching a new user in the session.");
                setUser(context, httpRequest, auth.getCurrentUserName(), ticket, false);
            } else if (logger.isDebugEnabled())
                logger.debug("Ticket is valid; retaining cached user in session.");
        } catch (AuthenticationException authErr) {
            if (logger.isDebugEnabled())
                logger.debug("An AuthenticationException occured: ", authErr);
            session.removeAttribute(AUTHENTICATION_USER);
            if (!Application.inPortalServer()) {
                if (logger.isDebugEnabled())
                    logger.debug("The server is not running in a portal, invalidating session.");
                session.invalidate();
            }
            return AuthenticationStatus.Failure;
        } catch (Throwable e) {
            if (logger.isDebugEnabled())
                logger.debug("Authentication failed due to unexpected error", e);
            // Some other kind of serious failure
            AuthenticationService unprotAuthService = (AuthenticationService) wc.getBean(UNPROTECTED_AUTH_SERVICE);
            unprotAuthService.invalidateTicket(unprotAuthService.getCurrentTicket());
            unprotAuthService.clearCurrentSecurityContext();
            return AuthenticationStatus.Failure;
        }

        // As we are authenticating via a ticket, establish the session locale using request headers rather than web client preferences
        setupThread(context, httpRequest, httpResponse, false);

        return AuthenticationStatus.Success;
    }

    /**
     * Creates an object for an authenticated user and stores it in the session.
     * 
     * @param context
     *            the servlet context
     * @param req
     *            the request
     * @param currentUsername
     *            the current user name
     * @param ticket
     *            a validated ticket
     * @param externalAuth
     *            was this user authenticated externally?
     * @return the user object
     */
    public static User setUser(ServletContext context, HttpServletRequest req, String currentUsername,
            String ticket, boolean externalAuth) {
        if (logger.isDebugEnabled())
            logger.debug("Creating an object for " + currentUsername + " and storing it in the session");
        WebApplicationContext wc = WebApplicationContextUtils.getRequiredWebApplicationContext(context);

        User user = createUser(wc, currentUsername, ticket);
        // store the User object in the Session - the authentication servlet will then proceed
        HttpSession session = req.getSession(true);
        session.setAttribute(AuthenticationHelper.AUTHENTICATION_USER, user);
        setExternalAuth(session, externalAuth);
        return user;
    }

    /**
     * Sets or clears the external authentication flag on the session
     * 
     * @param session
     *            the session
     * @param externalAuth
     *            was the user authenticated externally?
     */
    private static void setExternalAuth(HttpSession session, boolean externalAuth) {
        if (logger.isDebugEnabled())
            logger.debug("Settings the external authentication flag on the session to " + externalAuth);
        if (externalAuth) {
            session.setAttribute(LoginBean.LOGIN_EXTERNAL_AUTH, Boolean.TRUE);
        } else {
            session.removeAttribute(LoginBean.LOGIN_EXTERNAL_AUTH);
        }
    }

    /**
     * Creates an object for an authentication user.
     * 
     * @param wc
     *           the web application context
     * @param currentUsername
     *           the current user name
     * @param ticket
     *           a validated ticket
     * @return the user object
     */
    private static User createUser(final WebApplicationContext wc, final String currentUsername,
            final String ticket) {
        if (logger.isDebugEnabled())
            logger.debug("Creating an object for " + currentUsername + " with ticket: " + ticket);
        final ServiceRegistry services = (ServiceRegistry) wc.getBean(ServiceRegistry.SERVICE_REGISTRY);
        return services.getTransactionService().getRetryingTransactionHelper()
                .doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<User>() {

                    public User execute() throws Throwable {
                        NodeService nodeService = services.getNodeService();
                        PersonService personService = (PersonService) wc.getBean(PERSON_SERVICE);
                        NodeRef personRef = personService.getPerson(currentUsername);
                        User user = new User(currentUsername, ticket, personRef);
                        NodeRef homeRef = (NodeRef) nodeService.getProperty(personRef,
                                ContentModel.PROP_HOMEFOLDER);

                        if (homeRef == null || !nodeService.exists(homeRef)) {
                            throw new AuthenticationException("Home folder is missing for user " + currentUsername);
                        }

                        user.setHomeSpaceId(homeRef.getId());
                        return user;
                    }
                });
    }

    /**
     * For no previous authentication or forced Guest - attempt Guest access
     * 
     * @param ctx
     *           WebApplicationContext
     * @param auth
     *           AuthenticationService
     */
    public static User portalGuestAuthenticate(WebApplicationContext ctx, AuthenticationService auth) {
        if (logger.isDebugEnabled())
            logger.debug("Authenticating the current user as Guest in a portal.");
        try {
            auth.authenticateAsGuest();

            return createUser(ctx, AuthenticationUtil.getGuestUserName(), auth.getCurrentTicket());
        } catch (AuthenticationException guestError) {
            if (logger.isDebugEnabled())
                logger.debug(
                        "An AuthenticationException occurred, expected if Guest access not allowed - continue to login page as usual",
                        guestError);
        } catch (AccessDeniedException accessError) {
            // Guest is unable to access either properties on Person
            AuthenticationService unprotAuthService = (AuthenticationService) ctx.getBean(UNPROTECTED_AUTH_SERVICE);
            unprotAuthService.invalidateTicket(unprotAuthService.getCurrentTicket());
            unprotAuthService.clearCurrentSecurityContext();
            logger.warn("Unable to login as Guest: " + accessError.getMessage());
        } catch (Throwable e) {
            if (logger.isDebugEnabled())
                logger.debug("Unexpected error authenticating as Guest in a portal.", e);
            // Some other kind of serious failure to report
            AuthenticationService unprotAuthService = (AuthenticationService) ctx.getBean(UNPROTECTED_AUTH_SERVICE);
            unprotAuthService.invalidateTicket(unprotAuthService.getCurrentTicket());
            unprotAuthService.clearCurrentSecurityContext();
            throw new AlfrescoRuntimeException("Failed to authenticate as Guest user.", e);
        }
        return null;
    }

    /**
     * Uses the remote user mapper, if one is configured, to extract a user ID from the request
     * 
     * @param sc
     *           the servlet context
     * @param httpRequest
     *           The HTTP request
     * @return the user ID if a user has been externally authenticated or <code>null</code> otherwise.
     */
    public static String getRemoteUser(final ServletContext sc, final HttpServletRequest httpRequest) {
        String userId = null;

        // If the remote user mapper is configured, we may be able to map in an externally authenticated user
        RemoteUserMapper remoteUserMapper = getRemoteUserMapper(sc);
        if (remoteUserMapper != null) {
            userId = remoteUserMapper.getRemoteUser(httpRequest);
        }
        if (logger.isDebugEnabled()) {
            if (userId == null) {
                logger.debug("No external user ID in request.");
            } else {
                logger.debug("Extracted external user ID from request: " + userId);
            }
        }

        return userId;
    }

    /**
     * Gets the remote user mapper if one is configured and active (i.e. external authentication is in use).
     * @param sc
     *           the servlet context
     * @return the remote user mapper if one is configured and active; otherwise <code>null</code>
     */
    public static RemoteUserMapper getRemoteUserMapper(final ServletContext sc) {
        final WebApplicationContext wc = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
        RemoteUserMapper remoteUserMapper = (RemoteUserMapper) wc.getBean(REMOTE_USER_MAPPER);
        if (remoteUserMapper != null && !(remoteUserMapper instanceof ActivateableBean)
                || ((ActivateableBean) remoteUserMapper).isActive()) {
            if (logger.isDebugEnabled()) {
                logger.debug("Remote user mapper configured and active.");
            }
            return remoteUserMapper;
        }
        if (logger.isDebugEnabled()) {
            logger.debug("No active remote user mapper.");
        }
        return null;
    }

    /**
      * Attempts to retrieve the User object stored in the current session.
      * 
      * @param sc
      *            the servlet context
      * @param httpRequest
      *            The HTTP request
      * @param httpResponse
      *            The HTTP response
      * @return The User object representing the current user or null if it could not be found
      */
    public static User getUser(final ServletContext sc, final HttpServletRequest httpRequest,
            HttpServletResponse httpResponse) {
        // If the remote user mapper is configured, we may be able to map in an externally authenticated user
        String userId = getRemoteUser(sc, httpRequest);

        final WebApplicationContext wc = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
        HttpSession session = httpRequest.getSession();
        User user = null;

        // examine the appropriate session to try and find the User object
        SessionUser sessionUser = Application.getCurrentUser(session);

        // Make sure the ticket is valid, the person exists, and the cached user is of the right type (WebDAV users have
        // been known to leak in but shouldn't now)
        if (sessionUser != null) {
            if (logger.isDebugEnabled())
                logger.debug("SessionUser is: " + sessionUser.getUserName());
            AuthenticationService auth = (AuthenticationService) wc.getBean(AUTHENTICATION_SERVICE);
            try {
                auth.validate(sessionUser.getTicket());
                if (sessionUser instanceof User) {
                    user = (User) sessionUser;
                    setExternalAuth(session, userId != null);
                } else {
                    user = setUser(sc, httpRequest, sessionUser.getUserName(), sessionUser.getTicket(),
                            userId != null);
                }
            } catch (AuthenticationException authErr) {
                if (logger.isDebugEnabled())
                    logger.debug("An authentication error occured while setting the session user", authErr);
                session.removeAttribute(AUTHENTICATION_USER);
                if (!Application.inPortalServer()) {
                    if (logger.isDebugEnabled())
                        logger.debug("Invalidating the session.");
                    session.invalidate();
                }
            }
        }

        // If the remote user mapper is configured, we may be able to map in an externally authenticated user
        if (userId != null) {
            AuthorityService authorityService = (AuthorityService) wc.getBean(AUTHORITY_SERVICE);
            // We have a previously-cached user with the wrong identity - replace them
            if (user != null && !authorityService.isGuestAuthority(user.getUserName())
                    && !user.getUserName().equals(userId)) {
                if (logger.isDebugEnabled())
                    logger.debug("We have a previously-cached user with the wrong identity - replace them");
                session.removeAttribute(AUTHENTICATION_USER);
                if (!Application.inPortalServer()) {
                    if (logger.isDebugEnabled())
                        logger.debug("Invalidating session.");
                    session.invalidate();
                }
                user = null;
            }

            if (user == null) {
                if (logger.isDebugEnabled())
                    logger.debug("There are no previously-cached users.");
                // If we have been authenticated by other means, just propagate through the user identity
                AuthenticationComponent authenticationComponent = (AuthenticationComponent) wc
                        .getBean(AUTHENTICATION_COMPONENT);
                try {
                    if (logger.isDebugEnabled())
                        logger.debug(
                                "We have been authenticated by other means, authenticating the user: " + userId);
                    authenticationComponent.setCurrentUser(userId);
                    AuthenticationService authenticationService = (AuthenticationService) wc
                            .getBean(AUTHENTICATION_SERVICE);
                    user = setUser(sc, httpRequest, userId, authenticationService.getCurrentTicket(), true);
                } catch (AuthenticationException authErr) {
                    if (logger.isDebugEnabled())
                        logger.debug("An authentication error occured while setting the session user", authErr);
                    // Allow for an invalid external user ID to be indicated
                    session.removeAttribute(AUTHENTICATION_USER);
                    if (!Application.inPortalServer()) {
                        if (logger.isDebugEnabled())
                            logger.debug("Invalidating the session.");
                        session.invalidate();
                    }
                }
            }
        }
        return user;
    }

    /**
     * Setup the Alfresco auth cookie value.
     * 
     * @param httpRequest
     * @param httpResponse
     * @param username
     */
    public static void setUsernameCookie(HttpServletRequest httpRequest, HttpServletResponse httpResponse,
            String username) {
        if (logger.isDebugEnabled())
            logger.debug("Setting up the Alfresco auth cookie for " + username);
        Cookie authCookie = getAuthCookie(httpRequest);
        // Let's Base 64 encode the username so it is a legal cookie value
        String encodedUsername;
        try {
            encodedUsername = Base64.encodeBytes(username.getBytes("UTF-8"));
            if (logger.isDebugEnabled())
                logger.debug("Base 64 encode the username: " + encodedUsername);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        if (authCookie == null) {
            if (logger.isDebugEnabled())
                logger.debug("No Alfresco auth cookie wa found, creating new one.");
            authCookie = new Cookie(COOKIE_ALFUSER, encodedUsername);
        } else {
            if (logger.isDebugEnabled())
                logger.debug("Updating the previous Alfresco auth cookie value.");
            authCookie.setValue(encodedUsername);
        }
        authCookie.setPath(httpRequest.getContextPath());
        // TODO: make this configurable - currently 7 days (value in seconds)
        authCookie.setMaxAge(60 * 60 * 24 * 7);
        httpResponse.addCookie(authCookie);
    }

    /**
     * Helper to return the Alfresco auth cookie. The cookie saves the last used username value.
     * 
     * @param httpRequest
     * 
     * @return Cookie if found or null if not present
     */
    public static Cookie getAuthCookie(HttpServletRequest httpRequest) {
        if (logger.isDebugEnabled())
            logger.debug("Searching for Alfresco auth cookie.");
        Cookie authCookie = null;
        Cookie[] cookies = httpRequest.getCookies();
        if (cookies != null) {
            if (logger.isDebugEnabled())
                logger.debug("Cookies present.");
            for (int i = 0; i < cookies.length; i++) {
                if (COOKIE_ALFUSER.equals(cookies[i].getName())) {
                    // found cookie
                    if (logger.isDebugEnabled())
                        logger.debug("Found Alfresco auth cookie: " + cookies[i].toString());
                    authCookie = cookies[i];
                    break;
                }
            }
        }
        return authCookie;
    }

    /**
     * Gets the decoded auth cookie value.
     * 
     * @param authCookie
     *           the auth cookie
     * @return the auth cookie value
     */
    public static String getAuthCookieValue(Cookie authCookie) {
        String authCookieValue = authCookie.getValue();
        if (logger.isDebugEnabled())
            logger.debug("Decoding auth cookie: " + authCookieValue);
        if (authCookieValue == null) {
            return null;
        }
        try {
            String decodedAuthCoockieValue = new String(Base64.decode(authCookieValue), "UTF-8");
            if (logger.isDebugEnabled())
                logger.debug("The auth cookie is: " + decodedAuthCoockieValue);
            return decodedAuthCoockieValue;
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }
}