5

Say I have the endpoints:

/users

and

/users/<id>

If I wanted to DELETE a user authenticated with a JWT token that contains the user object, should this DELETE handled go under /users or /users/<id>?

It makes sense to have under the /users/<id> endpoint as you're deleting that specific item.

But also makes sense to have it under /users as then you don't have redundant data and you don't have to enter the <id> every time you want to perform a function on your user when you already have the JWT authentication.

This idea falls to many-to-many objects too, say I wanted to access /users/<id>/games/<id>/move stripping '/users/<id>' makes it seem like there's not 'user' resource but it makes it less clunky and again less data redundancy.

Which is more 'accepted' or 'right'? Thanks :)

tomhepz
  • 331
  • 1
  • 6
  • 3
    For refering the user authenticated `/me`. Looks to me less complicated. It's a very common alias and more intuitive than the cannonical uri (/users//). The action would be `DELETE /me HTTP/1.1`. – Laiv Dec 08 '17 at 16:52

2 Answers2

5

If the purpose of this end point is to perform an operation on the "current user" as defined by the user in the JWT token, then you absolutely don't want the User Id in the URL.

You don't want someone to maliciously change the URL to perform an action on a user other than their own, and implicitly using the JWT token for the user to operate on is a great way to ensure nobody is trying to screw with your system to do something they shouldn't be able to do.

Laiv brings up a good point in his comment on the question:

For refering the user authenticated /me. Looks to me less complicated. It's a very common alias and more intuitive than the cannonical uri (/users/id/). The action would be DELETE /me HTTP/1.1

Name your end point so clients of your service know they are performing an operation on their own user:

HTTP/1.1 DELETE /users/me

This tells clients "hey, I'm doing something to myself" and keeps them from accidentally doing something they shouldn't by munging the Id in the URL.

Greg Burghardt
  • 34,276
  • 8
  • 63
  • 114
  • 2
    This answer is absolutely wrong. You want to identify the resource to be deleted. that identifier *is* the URI of the resource. Successfully DELETE-ing the /user/me resource means no-one else will be able to GET the /user/me resource. You should use ACLs to determine which /user/:id objects are able to be deleted by the authenticated user (which for an ordinary user, is probably just themselves). – Nicholas Shanks Dec 18 '17 at 15:11
  • 1
    "You don't want someone to maliciously change the URL to perform an action on a user other than their own," this is a problem of authorization, and should not make any effect on your API design. – adnanmuttaleb Jan 26 '20 at 15:52
4

I think you are muddling the concept of the id of the user that is authenticated and the id of the user that you want to delete. I could be wrong but it's a little unclear when a user would delete him/herself and what that would mean. I would think the user being deleted and the user that is authenticated would typically be different.

For the second part of the question, I don't think it makes sense to make the games a subresource of the user. Games are a resource where each one has it's own ID. What user (or users) own the game or have access to it is an attribute of that game resource. You can use the authenticated user and their role to determine whether they have access to a given game. You would do something like this: /users/<id>/games to provide a list of URLs for the games that user is associated with.

JimmyJames
  • 24,682
  • 2
  • 50
  • 92
  • My point is to DELETE a user you must already be authenticated as being that user, in my case you will have a JWT. In this JWT there is encoded the PK in the database to the user object you wish to delete. So if I send an authorisation header with JWT I don't need to repeat it in the URL again? I hope that cleared my intentions. – tomhepz Dec 08 '17 at 17:18
  • So your design is that a user can delete his/her own resource and no one else can? – JimmyJames Dec 08 '17 at 17:32
  • Yes. Only a user can delete his/her own profile. – tomhepz Dec 08 '17 at 17:33
  • So an administrator can't do that? What happens when a user delete's his/her profile? Are you going to invalidate their authentication/authorization? – JimmyJames Dec 08 '17 at 17:35
  • I don't have a concept of an administrator account as I don't see a purpose for one in my circumstances and the JWT will be inherently invalid once the user is deleted as the the JWT checks against the user object in all circumstances. (it's now deleted) – tomhepz Dec 08 '17 at 17:38
  • And then what, redirect them to some unauthorized page? The only other option I see is to throw back an unauthorized error. Even if you don't see the need for an admin now, I think it's a bad idea to paint yourself into a corner. The more assumptions you build into the model, the harder it will be to modify it later. Authorization should be used to determine what you are allowed to do not what actions are being taken. – JimmyJames Dec 08 '17 at 17:43
  • I would say the `/me` thing seems OK in addition to explicit resources. It's clear that it's contextual. – JimmyJames Dec 08 '17 at 17:48