How do I secure REST resources so that only a single user of a role can access it?
Question
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);
}
No correct solution