Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Restful Web Services (jax rs) authentication pattern

I have started using JAX-RS to created a simple restful interface to my web application. Currently, it is only being used (read only) by one internal client which has access to all application data, and I am using http basic authentication for access. I would like to start using it as part of the view layer of my app, and certain operations will only be allowed if a user is logged in via the web app. I am struggling to find a pattern that allows me to use both forms of authentication in an elegant way, without repeating a lot of code. Here is roughly what I have come up with:

First a util class for loading an application session, which is stored in the database.

public class RestUtil {
    public static AppSession getAuthenticatedSession(HttpServletRequest request) {
        AppSession session;
        String remoteUser = request.getRemoteUser();
        if (remoteUser != null) {
            session = SessionRepository.loadSessionByRemoteUser(remoteUser);
        } else {
            session = SessionRepository.loadSessionById(request.getSession().getId());
        }
        return session;
    }
}

Here's our resource, with one method that is only accessible to an authenticated user, or our http basic auth client:

@Path("/protected/resource")
public class ProtectedResource {
    @GET
    @Produces(MediaType.TEXT_JSON)
    @Path("{userId}")
    public String getProtectedResourceJson(@Context HttpServletRequest request, @PathParam("userId") Integer userId) {
        // Return Charity List XML
        AppSession session = RestUtil.getAuthenticatedSession(request);

        if (session.canAccessUser(userId))  //get Json...
    }
}

Here's the most basic view of the AppSession, for the purpose of this question:

public class AppSession {
    User authenticatedUser;
    String remoteUser;

    public boolean canAccessUser(Integer userId) {
        if (remoteUser != null) {
            //this client has access to all users
            return true;
        } else if (authenticatedUser.getId().equals(userId)) {
            //this is local client, calling the service from a view
            //only has access to authenticatedUser
            return true;
        } else {
            return false;
        }
    }
}

Furthermore, for services that do not require any sort of authentication, how do I prevent unauthorized third parties from just pointing at the url, and grabbing the data at their leisure?

like image 311
Peter Anthony Avatar asked Jul 26 '11 18:07

Peter Anthony


1 Answers

You're getting to the point when it is worth looking into using aspect-oriented programming to split the security side of things from your business logic. If you're already using Spring to assemble the pieces of your app (which I recommend for complex servers) then it's just a matter of adding in Spring AOP to inject the security logic. Otherwise, use AspectJ directly. The actual logic to handle the multiple login modes will probably have to be custom, but at least you can keep it quarantined.

If using Spring, consider using Spring Security; that builds on top of Spring AOP and supplies you with much more of the solution.

like image 129
Donal Fellows Avatar answered Nov 02 '22 23:11

Donal Fellows