Posts Tagged ‘interceptor’

User authorization in RESTful Spring

I’m having a lot of fun with the new RESTful features in Spring 3.0. I’m sure you could tell by the number of RESTful Spring posts lately.

Last night I wrote a user authorization interceptor that makes sure there is a user associated with each resource request that requires it. I’m structuring most of my new web apps in such a way that user authorization is required for almost all actions.  I had to make a choice of how to enforce user authorization in the app.  The two choices were between a Servlet filter and a HandlerInterceptor.

A Servlet Filter is part of the Java EE Servlet package.  Most of my Java web projects use Servlet Filters in some way so I wasn’t immediately opposed to using one to make sure there is a logged in user associated with a request.  Because I wanted possible errors to be properly rendered in my different view types using Spring I decided to use a HandlerInterceptor.

A HandlerInterceptor is a Spring interface that is pretty much analogous to a Servlet Filter in terms of structure, though it’s a little more focused in purposed.  The HandlerInterceptor is mostly concerned with text-based content, where Filters can be applied to any content type.  Filters are also more appropriate for setting headers and gzipping responses.  The Handler Interceptor is targeted for application logic.

This interceptor only checks to see that there is a user object associated with an resource request before passing it on to the handler (a controller).  In practice this may include more detailed authorization checks but for the example just checking for a user is fine.

@Component
public class UserAuthorizationInterceptor extends HandlerInterceptorAdapter {

  private static final String UNAUTHORIZED_MSG = "You are not logged in.  You must log in or supply an API token.";

  @Override
  public boolean preHandle(HttpServletRequest request,
                        HttpServletResponse response,
                        Object handler) throws Exception {

    String uri = request.getRequestURI();
    User user = (User) request.getSession().getAttribute("user");

    if (user != null || uri.indexOf("login") != -1) {
      return true;
    } else {
      response.sendError(HttpServletResponse.SC_FORBIDDEN, UNAUTHORIZED_MSG);
      return false;
    }
  }
}

Initially I wanted any error messages to be rendered by my Atom, RSS and JSON views. Any error message generated by the application should come back to the user in the requested data format. But this is a RESTful app. The REST philosophy already addresses the only error message that should come out of an authorization check with HTTP status codes. The only error message that should come out of this interceptor is an “unauthorized” message. HTTP supplies the 401 status code to indicate a user is unauthorized.

The implication of using the 401 code is that the user should use HTTP authentication, either basic or digest. That’s not appropriate for an application using OpenID and API tokens for user authentication. Instead the 403 status code is more appropriate. This means the client is forbidden from accessing the requested resource. The server understood the request but the client is not allowed to access the resource, which is exactly the case when there is no logged in user associated with the request.

Because HTTP already provides plenty of status codes for things that can go wrong we should rely on those codes when building RESTful applications. There is no reason to supply an application-generated error message when the protocol supplies everything we need to deal with the problem. The REST philosophy actually makes it much easier to write web apps because we’re using HTTP as it is intended to be used which takes a lot of responsibility off of our application code.