Search code examples
gwtauthenticationrequestfactory

GWT RequestFactory authentication functions


I'm using GWT and RequestFactory on a new project that needs authentication.

Where would be the best place to add the login and logout functions ? in a UserRequestContext ?

Thanks in advance.


Solution

  • Use servlet filter.

    I split RequestFactory calls into two streams - one for unauthenticated calls and another one for authenticated ones. Here is piece of my web.xml.

    <servlet>
        <servlet-name>CustomRequestFactoryServlet</servlet-name>
        <servlet-class>my.server.CustomRequestFactoryServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>CustomRequestFactoryServlet</servlet-name>
        <url-pattern>/gwtRequest</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>CustomRequestFactoryServlet</servlet-name>
        <url-pattern>/gwtRequestAuth</url-pattern>
    </servlet-mapping>
    

    Then I created servlet filter which looks like this:

    public class GaeAuthFilter implements Filter
    {
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException
        {
            UserService userService = UserServiceFactory.getUserService();
            HttpServletRequest request = (HttpServletRequest) servletRequest;
            HttpServletResponse response = (HttpServletResponse) servletResponse;
    
            if (!userService.isUserLoggedIn())
            {
                String returnURI = "/";
    
                String requestURI = request.getRequestURI();
                String refererURI = request.getHeader("Referer");
                if (requestURI.equals("/gwtRequestAuth"))
                {
                    if (refererURI != null)
                        returnURI = refererURI;
                } else
                    returnURI = requestURI;
    
                response.setHeader("login", userService.createLoginURL(returnURI));
                response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
                return;
            }
    
            LoginService.login(request);
    
            filterChain.doFilter(request, response);
        }
    }
    

    As you can see I set login http-header with URL to auth webpage.

    In the client code I intercept it by implementing my own DefaultRequestTransport that looks ike this:

    public class GaeAuthRequestTransport extends DefaultRequestTransport
    {
        private final EventBus eventBus;
    
        public GaeAuthRequestTransport(EventBus eventBus)
        {
            this.eventBus = eventBus;
        }
    
        @Override
        protected RequestCallback createRequestCallback(final TransportReceiver receiver)
        {
            final RequestCallback superCallback = super.createRequestCallback(receiver);
    
            return new RequestCallback()
            {
                public void onResponseReceived(Request request, Response response)
                {
                    if (Response.SC_UNAUTHORIZED == response.getStatusCode())
                    {
                        String loginUrl = response.getHeader("login");
                        if (loginUrl != null)
                        {
                            receiver.onTransportFailure(new ServerFailure(
                                    "Unauthenticated user", null, null, false /* not fatal */));
                            eventBus.fireEvent(new GaeAuthenticationFailureEvent(loginUrl));
                            return;
                        }
                    }
                    superCallback.onResponseReceived(request, response);
                }
    
                public void onError(Request request, Throwable exception)
                {
                    superCallback.onError(request, exception);
                }
            };
        }
    }
    

    Fired event is handled in the client code that navigates browser to login URL.

    That's it.