AnsweredAssumed Answered

JOSSO and Container Managed Security with Alfresco

Question asked by stk137 on Aug 23, 2007
Latest reply on Jan 25, 2008 by tpasturel
So I have made some progress getting Alfresco working with JOSSO, but I have a couple of issues/questions.  The code below is my authentication filter.  I didn't find any examples of using JOSSO or Container Managed Security, so I based this off NovellIChainsHTTPRequestAuthenticationFilter.  Since JOSSO works with CMS, I wrote generically for CMS instead of JOSSO specifically.   This means you have to secure the webapp in the web.xml and rely on that rather than checking the JOSSO cookie, etc directly yourself.  I secured /faces/*.

Which brings up my first question.  What should I secure?  And what should the auth filter be set up for.  I have on rare occasion gotten

net.sf.acegisecurity.AuthenticationCredentialsNotFoundException: A valid SecureContext was not provided in the RequestContext

If I just click return to application everything is fine.  How could the auth filter not get called?

Should /alfresco/n/* and /alfresco/d/d/*  be given filter mappings for whatever auth filter /faces/* is using?
I noticed I needed sitemesh mappings for /alfresco/n/* and wonder why there wasn't auth filter mappings for that.
What else could be causing this error?

My other issue is that when a user starts a totally new Alfresco session he gets sents to his user home (after logging into JOSSO) rather than the dashboard as his settings are configured to. 

This doesn't happen when he logs out  of JOSSO and back in.  But for now, I am not properly logging out of Alfresco, just JOSSO.  I just replaced the Alfresco logout link with one that has href="/alfresco/josso_logout/".


Here's my CmsAuthenticationFilter as it is now.


import java.io.IOException;
import java.util.List;
import java.util.Locale;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.transaction.UserTransaction;
import org.alfresco.config.ConfigService;
import org.alfresco.i18n.I18NUtil;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.repo.security.authentication.AuthenticationException;
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.PersonService;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.LoginBean;
import org.alfresco.web.bean.repository.User;
import org.alfresco.web.config.LanguagesConfigElement;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.alfresco.web.app.servlet.*;

public class CmsAuthenticationFilter extends AbstractAuthenticationFilter implements Filter {

    private static final String LOCALE = "locale";
    public static final String MESSAGE_BUNDLE = "alfresco.messages.webclient";
    private static Log LOG = LogFactory.getLog(CmsAuthenticationFilter.class);
    private ServletContext context;
    private String loginPage;
    private AuthenticationComponent authComponent;
    private AuthenticationService authService;
    private TransactionService transactionService;
    private PersonService personService;
    private NodeService nodeService;
    private List<String> m_languages;

    public CmsAuthenticationFilter() {
        super();
    }

    public void destroy() {
    }

    public void doFilter(ServletRequest sreq, ServletResponse sresp, FilterChain chain) throws IOException,
            ServletException {

        LOG.debug("doFilter - CmsAuthenticationFilter");
        HttpServletRequest req = (HttpServletRequest) sreq;
        HttpServletResponse resp = (HttpServletResponse) sresp;
        HttpSession httpSess = req.getSession(true);

        String userName;

        if (req.getUserPrincipal() == null)
            return;
        userName = req.getUserPrincipal().getName();
        if (userName == null)
            return;
        LOG.debug("auth userName = " + userName);

        User user = (User) httpSess.getAttribute(AuthenticationHelper.AUTHENTICATION_USER);

        if (user != null) {
            try {
                if (LOG.isDebugEnabled())
                    LOG.debug("User " + user.getUserName() + " validate ticket");
                if (user.getUserName().equals(userName)) {
                    authComponent.setCurrentUser(user.getUserName());
                    I18NUtil.setLocale(Application.getLanguage(httpSess));
                    chain.doFilter(sreq, sresp);
                    return;
                } else {
                    setAuthenticatedUser(req, httpSess, userName);
                }

            } catch (AuthenticationException ex) {
                if (LOG.isErrorEnabled())
                    LOG.error("Failed to validate user " + user.getUserName(), ex);
            }

        }

        setAuthenticatedUser(req, httpSess, userName);
        if (req.getRequestURI().endsWith(getLoginPage()) == true) {
            if (LOG.isDebugEnabled())
                LOG.debug("Login page requested, chaining …");
            resp.sendRedirect(req.getContextPath() + "/faces/jsp/browse/browse.jsp");
            return;
        } else {
            chain.doFilter(sreq, sresp);
            return;
        }
    }

    private void setAuthenticatedUser(HttpServletRequest req, HttpSession httpSess, String userName) {
        authComponent.setCurrentUser(userName);
        UserTransaction tx = transactionService.getUserTransaction();
        NodeRef homeSpaceRef = null;
        User user;
        try {
            tx.begin();
            user = new User(userName, authService.getCurrentTicket(), personService.getPerson(userName));
            homeSpaceRef = (NodeRef) nodeService.getProperty(personService.getPerson(userName),
                    ContentModel.PROP_HOMEFOLDER);
            user.setHomeSpaceId(homeSpaceRef.getId());
            tx.commit();
        } catch (Throwable ex) {
            LOG.error(ex);
            try {
                tx.rollback();
            } catch (Exception ex2) {
                LOG.error("Failed to rollback transaction", ex2);
            }
            if (ex instanceof RuntimeException) {
                throw (RuntimeException) ex;
            } else {
                throw new RuntimeException("Failed to set authenticated user", ex);
            }
        }
        httpSess.setAttribute(AuthenticationHelper.AUTHENTICATION_USER, user);
        httpSess.setAttribute(LoginBean.LOGIN_EXTERNAL_AUTH, Boolean.TRUE);
        Locale userLocale = parseAcceptLanguageHeader(req, m_languages);
        if (userLocale != null) {
            httpSess.setAttribute(LOCALE, userLocale);
            httpSess.removeAttribute(MESSAGE_BUNDLE);
        }

        I18NUtil.setLocale(Application.getLanguage(httpSess));
    }

    public void init(FilterConfig config) throws ServletException {
        this.context = config.getServletContext();
        WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(context);
        ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
        transactionService = serviceRegistry.getTransactionService();
        nodeService = serviceRegistry.getNodeService();
        authComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent");
        authService = (AuthenticationService) ctx.getBean("authenticationService");
        personService = (PersonService) ctx.getBean("personService");
        ConfigService configServiceService = (ConfigService) ctx.getBean("webClientConfigService");
        LanguagesConfigElement configElement = (LanguagesConfigElement) configServiceService.getConfig("Languages")
                .getConfigElement(LanguagesConfigElement.CONFIG_ELEMENT_ID);
        m_languages = configElement.getLanguages();

    }

    private String getLoginPage() {
        if (loginPage == null) {
            loginPage = Application.getLoginPage(context);
        }
        return loginPage;
    }

}

Outcomes