4

I have succesfully created a REST web service with Jersey and secured it via java security annotations. It looks something like this

GET    /users/     // gives me all users
GET    /users/{id} // gives the user identified by {id}
POST   /users/     // creates user
PUT    /users/{id} // updates user identified by {id}
DELETE /users/{id} // delete user

I also have setup a realm with two roles: user and admin

I secured all methods so that only admins can access them.

Now i want to give free the PUT /users/{id} and GET /users/{id} methods, so that users can access their own and only their own resources.

Example:

// user anna is logged in and uses the following methods
    GET    /users/anna // returns 200 OK
    GET    /users/pete // returns 401 UNAUTHORIZED

Since i could not find a way to configure this through annotations, I am thinking of passing the HTTP request to the corresponding method to check if the user is allowed to access the resource.

It would look something like this for the GET /users/{id} method:

@GET
@Path("/users/{id}")
@RolesAllowed({"admin","user"})
@Produces(MediaType.APPLICATION_JSON)
public Response getUser(
    @PathParam("id") String id,
    @Context HttpServletRequest req
) {
    HttpSession session = request.getSession(false);

    if (session != null && session.getValue("userID").equals(id))
        return getObject(User.class, id);

    return Response.status(Status.UNAUTHORIZED).build();
}

I don't like this aproach because i think i would have to add the userID manualy to the session.

  • Do you know a more elegant way to solve this?

  • If not how do you add the userid to the session while using form authentication?

EDIT

Thank you Will and Pavel :) Here is my final solution:

@Context
private SecurityContext security;

// ...
@GET
@Path("/users/{id}")
@RolesAllowed({"admin","user"})
@Produces(MediaType.APPLICATION_JSON)
public Response getUser(@PathParam("id") String id){
    if (security.isUserInRole("user"))
        if (security.getUserPrincipal().getName().equals(id))
            return getObject(User.class, id);
        else
            return Response.status(Status.UNAUTHORIZED).build();
    else
        return getObject(User.class, id);
}
Zounadire
  • 1,496
  • 2
  • 18
  • 38

2 Answers2

3

In the HttpServletRequest, you can call getRemoteUser() or getUserPrincipal() to get the identity of the logged in user. You would then continue like you are doing in specifically allowing or denying them access to the particular resource.

Blessed Geek is referring more specifically to the aspect of REST regarding stateless transactions and the use of HTTP authentication. While this is an important point in the larger scope of a REST architecture, it's less relevant to your specific question since you don't specify the type of authentication mechanism you're using against your Java EE app, especially since authentication is a container issue in Java EE, not an application issue.

If you're using basic authentication, then you are using HTTP headers to manage authentication and authorization. If you're using form based authentication, then the container is managing this for you via the servlet session, making the service stateful (since sessions are a stateful artifact).

But this has no bearing on your specific question.

Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
Will Hartung
  • 115,893
  • 19
  • 128
  • 203
  • 1
    or you can inject SecurityContext, see http://jersey.java.net/nonav/apidocs/1.11/jersey/javax/ws/rs/core/SecurityContext.html – Pavel Bucek Feb 23 '12 at 11:19
  • Thank you Will for your insight helped a lot. @Pavel thank you too I'm now using the SecurityContext looks awesome now :D – Zounadire Feb 26 '12 at 20:04
0

One of the most important aspects of deploying REST is understanding the role of http headers and cookies.

For REST to be practical, you need to deploy an authentication framework.

Read

GWT and Google Docs API.

GWT-Platform login + session management

Read up on Google Federated Login, OAuth and OpenID.

Some of my explanations may be outdated, if they were posted before OAuth 2.0.

Community
  • 1
  • 1
Blessed Geek
  • 21,058
  • 23
  • 106
  • 176
  • Hi Geek :) thank you for your answer. Maybe in my case that's a bit of an overkill since the REST service is only used by an AJAX Web-Fronted which is only accessible after you haved logged in. By reading your Answers I did not quite get why I need an authenticaion framework. Maybe you could give me some more insight by going into my case a little more and make one or two examples to convince me :). Regarding the headers and cookie point I could also need some clarification. – Zounadire Feb 23 '12 at 03:29
  • http://stackoverflow.com/questions/9425884/different-browser-means-a-different-client-from-the-same-machine/9426183#9426183 – Blessed Geek Mar 05 '12 at 01:20