Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resource level authorization in RESTful service

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.

like image 643
Barath Avatar asked Jul 09 '11 12:07

Barath


People also ask

How does authorization work in REST webservices?

A REST request can have a special header called Authorization Header, this header can contain the credentials (username and password) in some form. Once a request with Authorization Header is received, the server can validate the credentials and can let you access the private resources.

What is resource type in REST API?

The fundamental concept in any RESTful API is the resource. A resource is an object with a type, associated data, relationships to other resources, and a set of methods that operate on it.


2 Answers

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

like image 93
Phil Parker Avatar answered Oct 14 '22 01:10

Phil Parker


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() { /* ... */ }

}
like image 32
Jonas Avatar answered Oct 14 '22 00:10

Jonas