External Login fail implements CubaAuthProvider

Hi,
i try to use an implementation of CubaAuthProvider with cuba 6.7.2 version as git example ‘sso-login-by-token’ to have an external login and authenticate session in doFilter but it doesn’t work becouse every time it redirect on login page also if the request has correct params and a Principal is added to session.

I use this code (simple copy and paste from git project):

package com.company.demo.web.auth;

import com.haulmont.cuba.security.global.LoginException;
import com.haulmont.cuba.web.auth.CubaAuthProvider;
import org.apache.commons.lang.StringUtils;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.security.Principal;
import java.util.Locale;

public class SimpleTokenAuthProvider implements CubaAuthProvider {

    public static final String TOKEN_PRINCIPAL_SESSION_ATTR = "TOKEN_PRINCIPAL";

    @Override
    public void authenticate(String login, String password, Locale messagesLocale) throws LoginException {
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // do nothing
    }

    @Override
    public void destroy() {
        // do nothing
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // here we check request parameter and if it is a correct token, then login user as passed user name
        // http://localhost:8080/app?token=LOG_IN_ME_PLEASE&user=admin

        HttpServletRequest httpRequest = (HttpServletRequest) request;
        // ignore static requests
        if (StringUtils.startsWith(httpRequest.getRequestURI(), httpRequest.getContextPath() + "/VAADIN/")) {
            chain.doFilter(request, response);
            return;
        }

        HttpSession session = httpRequest.getSession();
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        if (request.getParameter("user") != null
                && "LOG_IN_ME_PLEASE".equals(request.getParameter("token"))) {

            SimpleTokenPrincipalImpl sessionPrincipal = new SimpleTokenPrincipalImpl(request.getParameter("user"));
            session.setAttribute(TOKEN_PRINCIPAL_SESSION_ATTR, sessionPrincipal);
            httpResponse.sendRedirect(httpRequest.getRequestURL().toString());
            return;
        }

        SimpleTokenPrincipalImpl principal = (SimpleTokenPrincipalImpl) session.getAttribute(TOKEN_PRINCIPAL_SESSION_ATTR);
        if (principal != null) {
            HttpServletRequest authenticatedRequest = new ServletRequestWrapper(httpRequest, principal);
            chain.doFilter(authenticatedRequest, response);
            return;
        }

        chain.doFilter(request, response);
    }

    public static class ServletRequestWrapper extends HttpServletRequestWrapper {
        private final SimpleTokenPrincipalImpl principal;

        public ServletRequestWrapper(HttpServletRequest request, SimpleTokenPrincipalImpl principal) {
            super(request);
            this.principal = principal;
        }

        @Override
        public Principal getUserPrincipal() {
            return principal;
        }
    }

    public static class SimpleTokenPrincipalImpl implements Principal {
        private final String userName;

        public SimpleTokenPrincipalImpl(String userName) {
            this.userName = userName;
        }

        @Override
        public String getName() {
            return userName;
        }
    } 
}

app.log file is empty as also catalina.out.
If i try to execute pure git cloned project ‘sso-login-by-token’ i got same problem.

What i’m doing wrong?

Hi,

By default, automatic login by SSO from filter can be performed only once per HTTP session on session start. If you want to login user automatically even if there is an active session then you can force invalidation of the session:

if (request.getParameter("user") != null
        && "LOG_IN_ME_PLEASE".equals(request.getParameter("token"))) {

    // CAUTION: we want to reset previous session completely, even if it is active
    session.invalidate();
    // obtain newly created session
    session = httpRequest.getSession();

    SimpleTokenPrincipalImpl sessionPrincipal = new SimpleTokenPrincipalImpl(request.getParameter("user"));
    session.setAttribute(TOKEN_PRINCIPAL_SESSION_ATTR, sessionPrincipal);
    httpResponse.sendRedirect(httpRequest.getRequestURL().toString());
    return;
}

Do not forget to use the following link: http://localhost:8080/app?token=LOG_IN_ME_PLEASE&user=admin

Also, I’ve updated the sample application on Github. Now it supports standard login from login form if a user is not logged in automatically.

See also the issue in 6.8 release: https://youtrack.cuba-platform.com/issue/PL-9867 CubaAuthProvider will be deprecated and we will provide neat and documented APIs for web login/sso implementation.

Hi Yuriy,
thanks for your answer.

Now modifying code as your example adding session.invalidate() and authentication call in authentication method of class, it works.

Only one last question, to force logout if arrive a call from external to this filter, i just need to catch that call with specific custom param and call session.invalidate(), it’s correct?

In this case middleware session will be active until expiration.

I’d recommend that you find and logout corresponding middleware session using LoginService.logout(), but it is not required.