Search code examples
restsecurityauthorizationrestful-authenticationrestful-architecture

REST API access control extract subject from access token vs. from path parameter


The general idea in securing REST API in OAUTH is by using Authorization Bearer <access token> header, typically a JWT, which has information about the subject, ie. sub: u1 with u1 is the userId in the database.

With such access token, client app can access the different resources. Let's say an user has many cars, has many boats, etc...So, in RESTful manner, /users returns all users, /users/:u1 returns data of user u1, /users/:u1/cars/:c1 returns data of the car c1 of user u1, /users/:u1/boats/:b1 returns data of the boat b1 of user u1, etc.

My question is about u1. Shouldn't u1 be extracted from the JWT access token instead because we know we can trust the JWT? In theory an app can use a JWT issued for user u1, but requesting access to /users/:u2 which should be forbidden.

One can make /users/:u1 unavailable, and force client app to call /users instead and extract the sub from the JWT. However, calling /users to return data of u1 breaks the RESTful pattern and its benefits (ie. http caching).

What's the right approach?

This probably an authorization framework on REST api question. JWT can only address authentication only.


Solution

  • IMO your REST API should be independent of your authorization framework.

    While it makes sense in your case that user u1 cannot access cars or boats from user u2, this may not hold for all users.

    You can easily imagine an administrator user or some other role that does have access to cars and boats of any (or a particular subset of) users.

    So, I would say that

    GET /users/:u1/cars/
    

    should responds with HTTP 200 OK and return all cars for user u1 if the user has permission to retrieve the cars for user u1. Otherwise it should respond with HTTP 403 Forbidden.

    So, in other words, use the information from the JWT token to authorize the actions. Do not change your API design to implicitly infer the user context from it.