12

Let /users/{id} be a resource url in RESTful service.

Basic authentication is enabled and only authenticated users are allowed to access the url.

Example Scenario:

User_1 & User_2 are authenticated users with userId 1 & 2. Since both are authenticated, both of them are having access to,

  • /users/1
  • /users/2

But the expectation is User_1 should have access to /users/1 and not to /users/2 or other userId.

Question: How to do resource level authorization in RESTful services?

Note: I am implementing RESTful using Jax-RS (with Apache CXF implementation), helpful if you could explain with Jax-RS.

-Barath

Edit:

As Donal mentioned, I am not looking for role based authorization rather resource level authorization.

To give an example, lets say /users/{id}/photos/{photoId} be another resource url. User_1 should be given access to the photos belong to him only. If photoId of 2 belonging to user_2, then we should give http_404 error code for user_1 when a request /users/1/photos/2 is requested.[Since User_1 is also authenticated user he can invoke /users/2/photos/2, so we must identify the user id based on authentication parameters than via resource url]

Only solution I can think of is, include the unique id which determines the authorization in each query like,

Instead of SELECT * FROM PHOTO_TBL WHERE PHOTO_ID=2;

use SELECT * FROM PHOTO_TBL, USER_TBL WHERE PHOTO_ID=2 AND USER_ID=1 AND USER_ID=PHOTO_ID;

with this resources are delivering data that belongs to specific user. [There should be a mechanism to prevent the modification of the unique id in client side which is used to decide on authorization(userId in this case), since all requests are STATELESS request]

Caveat: Each and every query should be intelligent enough to understand the security concerns and include extra join. This is a bad design to tie up security logic to every business function.

I am yet to look into Spring security and how it can be used in this use case.

Barath
  • 265
  • 1
  • 5
  • 12
  • Like you note in the tag, this is an authorization issue past authentication. This can be implemented either rolled into the application, or as an intermediary proxy comparing the user ID in the URL and in the authentication headers. – Szocske Jul 09 '11 at 12:46
  • @Szocske: This is where it's worth putting it in the app. But you can use Spring AOP (and Spring Security, naturally) to make it easier. The only slightly tricky bit is realizing that this really is not role-based access control, and so that SpringSec's RBAC support isn't relevant. (Alas, that's what the best tutorial material is on…) – Donal Fellows Jul 09 '11 at 22:32
  • OK, now I see the edit about picture IDs which need a join to the users table anyway. In this case however there's little need for the user id in the URL anyway :-) – Szocske Jul 10 '11 at 17:22
  • @Szocske: Yes, userId in url is not required. – Barath Jul 10 '11 at 21:57
  • @Barath Did you manage to solve this problem ? – Sagar Nov 06 '13 at 16:28
  • I looking for a similar solution as well. @Barath, were you able to solve this problem? and If yes could you elaborate on how? – Pradeep Jun 02 '15 at 08:06

2 Answers2

3

I would recommend not having the user id in the url (as if it's being 'limited' by a Basic Auth header then you may as well just have it 'specified' by the Basic auth header). This will reduce the risk of introducing a Direct Object Reference Vulnerability - https://www.owasp.org/index.php/Top_10_2010-A4-Insecure_Direct_Object_References)

In this case you could have one of the following urls:

/users/CURRENT
/me

As photos is a sub resource then you could just create the photos with a "sequence number" within the user. In a sql database this would mean having a "compound key" across both user and photo columns.

/users/CURRENT/photo/{user_photo_seq}
/me/photo/{user_photo_seq}

Your SQL would then look something like:

SELECT * FROM PHOTO_TBL WHERE USER_ID=<BasicAuthUsername> AND PHOTO_ID=<path param value>;

A good explanation of "Basic Auth Headers":

http://en.wikipedia.org/wiki/Basic_access_authentication

Phil Parker
  • 1,557
  • 12
  • 10
1

JAX-RS specifies sub-resource where instead of handling request in a method, processing is delegated to other object - sub-resource.

Using sub-resources it's enought to take care of the root resource and nested ones will be secured as well.

In the example you can see UserResource and all it's sub-resources available only to authorized user.

@Path("/user/{userId}")
public class UserResource {

  private final String userId;

  public UserResource(@PathParam("userId") String userId, @Context SecurityContext securityContext) {
    this.userId = userId;

    boolean authorized = /* authorization code */;

    if (!authorized) { throw new WebApplicationException(Status.UNAUTHORIZED); }
  }

  @Path("photo")
  public PhotoResource getPhotoResource() {
    return new PhotoResource(userId);
  }

}

public class PhotoResource {

  private final String userId;

  public PhotoResource(String userId) {
    this.userId = userId;
  }

  @GET
  public Response listAll() { /* ... */ }

  @GET
  @Path("{photoId}")
  public Response present() { /* ... */ }

}
Jonas
  • 2,910
  • 2
  • 26
  • 36