What is a REST-conform approach to handle user based resource access?

751 views Asked by At

I'm building an API, that will be used by different logged-in (and not logged-in) users of different roles/types (e.g. reader, editor, admin etc.).

Is something like /users/{user_id}/path/to/data a correct RESTful way to define the are the user has access to? Or maybe just /{user_id}/path/to/data? Or should it be a body/query param like /path/to/data?user_id={user_id} or /path/to/data?user_token={user_token}? Or is the header the correct place for that information?

How should the user be provided to the API server REST-conform way?


Note: It's not about subresources of the user resource, e.g. addresses (if we define this as a subresource of user). Since this case is clear /users/{user_id}/addresses/{address_id}. The question is in general about the whole data the user may access.

2

There are 2 answers

0
Mark Hughes On

I would argue that the user ID has no place in the URL for non-user related things - what you describe would best be represented as simply /path/to/data/ - and the user_token or similar should be carried in a header (e.g. a JSON Web Token in the auth header), not in the URL and not in the query parameters.

The system should then respond with an authorization error HTTP response if the user does not have access to the specified resource.

The structure you describe would only be appropriate when the resources are subresources of the user and, as you have noted, this is not the case for the resources you are asking about.

1
Peter Brittain On

Although I completely agree with previous reply from Mark, it jumps straight to the answer without explaining why it's right. It also doesn't address some of the comments which question the need for a URI scheme at all, so I thought I'd try to add some flesh to the bones here.

I think there are 2 fundamental issues behind this question and so I'll take them in turn.

URI naming principles

Although not strictly required for strict REST conformity, it is widely recognized that meaningful names enhance a RESTful API and so there's a lot of debate out there, but nothing that fully codifies the decisions you have to make.

Generally, I find that the principle of least astonishment (POLA) helps create the best designs. In the case of RESTful APIs that means it's worth trying to find a natural match for the URI to the data you are representing. If you're looking for a sound bite, this typically means using nouns rather than verbs. This is well explored here.

You then have the issue of what the natural representation for your data actually is. Is the natural scope a high-level URI with lots of data contained in the associated document, many URIs with very little data in them or indeed some hybrid of the two where you can find ever more detailed information from a constructed URI, similar to something like XPath?

This one usually comes down to the requirements of your application. Some applications need to have fine-grained access so that many clients can update subsections of the same URI tree simultaneously; others may need a single URI containing a complex document to avoid performance issues with hundreds of requests. Generally I try to start with the least complicated implementation - e.g. a single document - until I find that more complex one is needed.

If that still hasn't solved your naming dilemma, you're into the thorny subject of inter-related objects, which has strong parallels to good OO, or relational database design. Again applying the POLA, I believe that you should only use /some/path/to/data if the data you want to retreive only makes sense in the context of the higher elements of the path.

Taking your example through the above criteria: clearly your users can have profile information including addresses. This address probably only makes sense inside the user context - it is their address. On its own it is largely meaningless (unless you're maintaining a database of addresses for some reason).

Now let's take the example further and assume you're creating something like StackOverflow and each user has the ability to post questions and answers. Does it make sense for a user to have a list of questions asked? Yes it does, but... Does it make sense to restrict all users of your system to finding those questions by looking for the user first? What happens when you want to access the questions in their own right - e.g. display the newest 50 questions, find any unanswered questions, etc? Clearly there are use cases which mean it makes sense for the questions to be extracted to a separate URI from the users and store some sort of relationship correlator (e.g. a list of IDs for the questions raised by this user) instead.

Applying the same principles to your question, I hope you agree that limiting your data to URLs that stem from your user are wrong.

Authentication of your users

Any strict RESTful needs to be stateless and so should avoid session based authentication. There's plenty of options out there - many of which have already been explored in some detail on this site, so I don't think there's much more I can or should add on this subject. You should check out the use of SSL and the various HTTP authentication schemes suggested.