Resource references in REST APIs
When we are developing a multi-user REST API, one thing to think about is how we design endpoints so the consumer can access or fetch only her resources. In this post, I will show what I consider the best way to deal with it.
Let's say we are developing a REST API for a TODO list application where a user is able to fetch her tasks. A first approach could be to have an endpoint that returns tasks for a given user, i.e:
GET /users/{userId}/tasks
This solution is not really bad, but there is a couple of caveats.
First, API consumer must know user ID to call this endpoint. In the case we are using some kind of token mechanism (like JWT or similar) that identifies the user in each request, this solution would be reduntant: we are telling server who we are in two places. This happens in the case our application allows a user to fetch only her tasks
Then, design the API like this can cause security issues; if we don't validate that 'userId' path param matches really with the caller's ID, we could be showing tasks of a user to another one.
To avoid this concerns, we can simplify design our API endpoints with references to the caller. Using this technique, our endpoint looks like this:
GET /users/me/tasks
This way, we are telling the server who we are only via (for instance) a JWT token in Authorization header, with no need the consumer to send his ID in the path. Also, using 'me' reference in the endpoint disables any possibility to fetch another user's tasks. No security issues any more.
Of course, using 'me' is not an standard or something. You can use what you want: 'me', 'current', 'requester', etc...
This approach can be applied to other resources of the system as well, not only to reference the "caller" user. For example, if we want to fetch only finished tasks, we could design an endpoint like this:
GET /users/me/tasks/finished
With 'finished' "keyword", we are referencing precisely finished tasks. In some cases, this technique makes the endpoint more readable that using, for instance, a filter query param ('/tasks?state=finished'). Of course, it depends on the context and the use case.
Some people may think this is not a RESTful design but, in my opinion, it is. There is no REST rule specifying that resources must be accessed or referenced only by its identifier whatsoever.