6

For some routes on an API, like GET /news, one would asume the user only wants news that pertains to them, so the userId is implicitly taken from authentication info.

However, some of the routes on an API i'm designing modify the "users" resource - i.e. changing some account info. For example, the user might want to change their name on the account. I could do

POST /users/name

or

PUT /users/:userId/name

1) Is this dichotomy generally correct (correct meaning most REST APIs would be designed in this fashion)? The idea that PUT would use an explicit userId where POST would take it from authentication info

2) If yes to the above, which style makes more sense for "modifying-account-info" type routes? If no, what do you suggest?

  • Did you use /name just as an example for some information about a user that can be changed or does your app actually use a granularity that small? Usually I would assume that there is more than just one field of info per remote call. For example, a userInfo JSon consisting of name, email, and maybe a few other fields. Only when data becomes more complex (like a list of projects a user belongs to), they would get separate URLs like GET /user/:userId/projects and GET /user/:userId/project/:projectId – Robert Jack Will May 20 '15 at 16:23
2

I've seen good APIs designed both ways. On the one hand, providing the userId in authentication and the URL seems redundant.

On the other hand, it could be more consistent to have an explicit Id in the URL if there are also ways for one user to look at public data of another user or you are using the same or a similar API in clients that need to get data for many users. That way, you always provide a userId in the URL, no matter if it's redundant or not.

As an aside, I have also seen APIs where you could use the word "me" in the URL to refer to the authenticated user.

  • in our use case, users will never modify another user's data. so implicit could work, although I do find it less consistent. I'm going to do some soul searching and maybe meet with a few gurus and perhaps I'll come back enlightened – jtmarmon May 20 '15 at 17:41
1

There are basically two different questions in one. Let me simplify and rephrase them:

1. If you have userId once as authentication info and once as a part of a data object which one should win?

None of them should win. These are two different userIds one is user performing the action another is the data object user as a subject of the action. Think of admin renaming another user. in case of a normal user you should compare this two id-s and return some error status code if they differ.

2. How to design an API call to the resource location which modifies the location itself? Example: PUT to /users/{name} would potentially alter the name.

That's why you have userId. I assume userId do not change. So use this location to PUT to to update the user. As a convenience you can provide response redirect on the location /users/{name} to corresponding permanent location of the resource.

0

Your GET /news essentially hides with what resources are you working with behind authentication info (which is usually transferred to the server using sessionId). This isn't RESTful, as you should explicitly define what resources are you working with in the URL.

Correct version is:

GET /news?userId=:userId

Even in this case you use the authentication info to validate/authorize the request, but this is OK from the REST point of view.

The only exception to this rule is the POST when you're creating a new entity while the key is generated on the server - in this case you omit the ID because you don't know it yet. It has some disadvantages (non-idempotent), using PUT with client-generated key is better.

  • Filtering has to happen on the server side based on authentication info, otherwise a user sending requests outside of the UI would be able to access to more than they should. – Mike Partridge May 20 '15 at 16:01
  • I think in practice this is not always true. github's api is generally an example of a well designed REST API and they still filter by authentication puu.sh/hUgTW/94e85b26d2.png – jtmarmon May 20 '15 at 16:02
  • @MikePartridge - filtering can happen on the userId argument in the URL. But before that, you check the authentication info to find out whether logged in user can access the requested data (in this case whether he is requesting his own data). – qbd May 20 '15 at 16:07
  • @jtmarmon URI in REST is the identification of the resource. In this (and GitHub's) case, it can't identify one resource, because /news resource collection is different for each user. Just because GitHub does it like this doesn't mean it's correct (or rather RESTful). – qbd May 20 '15 at 16:12
  • 1
    @MikePartridge, ok I see how /news/:userId could be considered confusing, I changed the answer to /news?userId=:userId. – qbd May 21 '15 at 10:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.