Rest /me/items vs /users/1/items - rest

I'm building an API where a logged in user can see his or her information. The user is also able to change its information. Only the user should be able to see and change their own info. Is it better to use the following routes
/me
/me/items
or (with policies)
/users/1
/users/1/items

/users/1 is marginally better than /me, but in practice it probably doesn't matter at all.
At the high level, REST doesn't care about URI spellings at all. General-purpose components treat the URI as opaque; only the origin server has any business trying to extract semantic information from the identifier.
From a design perspective, /me is somewhat vulnerable to the fact that you are combining two different concerns; "who is this resource about?" "who is allowed access?". It happens that today "Bob" is the only person authorized to read the "Bob" resource, but there's no particular reason that those two ideas will always be coupled together.
From the perspective of REST, having the same resource identifier mean different things depending on other header information could make the caching of representations problematic, in that you force the caches to become a lot smarter about deciding when a representation can be re-used.
HTTP solves some of this problem via the Vary header, which allows the origin server to describe to general purpose components which parts of the HTTP request might change the correct representation to use.
But in practice, even that is irrelevant, because HTTP doesn't permit shared caches to store a response to a request with an Authorization header field.

Related

REST API Best Practice For Accessing Self/Own Objects

Say I'm creating a journaling application and I want users to be able to post entries to their journals.
I do not intend to ever allow a user (even a moderator) to post an entry in someone else's journal.
That said, are there any arguments for exposing the account or journal id in my endpoint path?
I would think that POST api/journals/postEntry would be sufficient as I can determine the user via access token or JWT token.
Can anyone think of arguments for providing the journalId in the path? EX: POST api/journals/{user journalId}/postEntry
Can anyone think of arguments for providing the journalId in the path? EX: POST api/journals/{user journalId}/postEntry
Short answer: it's a violation of the uniform interface constraint.
See Fielding, 2000.
What you are doing, in effect, is creating this little corner of the world where, instead of using the target-uri to identify a resource, you are instead using target-uri + token.
Which means that your thing doesn't use the semantics that the general purpose components in the world are expecting.
For example, when I copy the URI out of my user agent, and share it with someone else, that other person doesn't get the result I expect -- they end up looking at their view, not mine.
The fact that we can stick a URI in an email message and have it just work for the person reading the email is a really big piece in the adoption story.
Furthermore, the cache constraint in REST rather depends on being able to use the identifier as the primary cache key. So your bespoke identity mechanism has the potential to mess up caching.
IN PRACTICE: you are using HTTP, and HTTP has caching rules that prohibit sharing authenticated requests. So the caching issues mentioned above are purely theoretical.
Alternatives you might consider
You could arrange for /api/journals/postEntry to redirect to /api/journals/{userJournalId}/postEntry
You could use the Content-Location header to indicate that there is a more specific identifier for the current representation.
You can use the canonical link relation to help clients navigate to the preferred resource from the alternatives.

REST API design for resource modification: catch all POST vs multiple endpoints

I'm trying to figure out best or common practices for API design.
My concern is basically this:
PUT /users/:id
In my view this endpoint could by used for a wide array of functions.
I would use it to change the user name or profile, but what about ex, resetting a password?
From a "model" point of view, that could be flag, a property of the user, so it would "work" to send a modification.
But I would expect more something like
POST /users/:id/reset_password
But that means that almost for each modification I could create a different endpoint according to the meaning of the modification, i.e
POST /users/:id/enable
POST /users/:id/birthday
...
or even
GET /user/:id/birthday
compared to simply
GET /users/:id
So basically I don't understand when to stop using a single POST/GET and creating instead different endpoints.
It looks to me as a simple matter of choice, I just want to know if there is some standard way of doing this or some guideline. After reading and looking at example I'm still not really sure.
Disclaimer: In a lot of cases, people ask about REST when what they really want is an HTTP compliant RPC design with pretty URLs. In what follows, I'm answering about REST.
In my view this endpoint could by used for a wide array of functions. I would use it to change the user name or profile, but what about ex, resetting a password?
Sure, why not?
I don't understand when to stop using a single POST/GET and creating instead different endpoints.
A really good starting point is Jim Webber's talk Domain Driven Design for RESTful systems.
First key idea - your resources are not your domain model entities. Your REST API is really a facade in front of your domain model, which supports the illusion that you are just a website.
So your resources are analogous to documents that represent information. The URI identifies the document.
Second key idea - that URI is used by clients to cache representations of the resource, so that we don't need to send requests back to the server all the time. Instead, we have built into HTTP a bunch of standard ways for communicating caching meta data from the server to the client.
Critical to that is the rule for cache invalidation: a successful unsafe request invalidates previously cached representations of the same resource (ie, the same URI).
So the general rule is, if the client is going to do something that will modify a resource they have already cached, then we want the modification request to go to that same URI.
Your REST API is a facade to make your domain model look like a web site. So if we think about how we might build a web site to do the same thing, it can give us insights to how we arrange our resources.
So to borrow your example, we might have a web page representation of the user. If we were going to allow the client to modify that page, then we might think through a bunch of use cases (enable, change birthday, change name, reset password). For each of these supported cases, we would have a link to a task-specific form. Each of those forms would have fields allowing the client to describe the change, and a url in the form action to decide where the form gets submitted.
Since what the client is trying to achieve is to modify the profile page itself, we would have each of those forms submit back to the profile page URI, so that the client would know to invalidate the previously cached representations if the request were successful.
So your resource identifiers might look like:
/users/:id
/users/:id/forms/enable
/users/:id/forms/changeName
/users/:id/forms/changeBirthday
/users/:id/forms/resetPassword
Where each of the forms submits its information to /users/:id.
That does mean, in your implementation, you are probably going to end up with a lot of different requests routed to the same handler, and so you may need to disambiguate them there.

Is it legal to have REST resource such as /currentUser in terms of RESTful and stateless?

In terms of RESTful and stateless it's pretty legal to have resource like
/users/123
But, the question is: is it legal to have resource that omits user id and assumes that it's implicitly resolved on the server from the user session? For example:
/loggedUser
That resource would point to /users/123 when user with identifier 123 is authorized.
Picking a resource locator
Using /me, /users/me, /users/myself, /users/current or similar URIs to identify a resource that corresponds to the authenticated user is perfectly fine from a REST perspective. According to Roy Thomas Fielding's dissertation, any information that can be named can be a resource:
5.2.1.1 Resources and Resource Identifiers
The key abstraction of information in REST is a resource. Any information that can be named can be a resource: a document or image, a temporal service (e.g. "today's weather in Los Angeles"), a collection of other resources, a non-virtual object (e.g. a person), and so on. In other words, any concept that might be the target of an author's hypertext reference must fit within the definition of a resource. A resource is a conceptual mapping to a set of entities, not the entity that corresponds to the mapping at any particular point in time. [...]
When using the URIs mentioned above, you have an identifier for the authenticated user and it will always identify the concept of an authenticated user, regardless of which user is authenticated.
The stateless constraint
The stateless constraint is not related to how your resources are identified. The stateless constraint is about not storing any session state on server side. In this approach, each request from client to server must contain all the necessary information to be understood by the server.
See que following quote from Fielding's dissertation:
5.1.3 Stateless
[...] each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server. Session state is therefore kept entirely on the client. [...]
When targeting protected resources that require authentication, for example, every request must contain all necessary data to be properly authenticated/authorized.
A similar question has been answered here and here.
It is OK as long as you use only the data from request (HTTP Headers in your case). In other words, this may work only for users that pass authentication.
Yes.
It is very common for ReST services to make assumption about authorization context.
Though making such a decision will limit usability of that route for users other than the logged on user. For example an admin might need to use that service for a specific user.
A ReST endpoint may even use Claims that exist in the Authorization context. for example return different data for a user that has logged in using certain mechanism.
of all HTTP headers, there are some that are probably not good to be used to tailor the ReST response. for example I will not use the 'referer'.
Make sure you check for any caching strategy you may have before making such design decisions.
It is perfectly legal as long as you keep it stateless. That is, you infer the current user from a security context provided with the HTTP request, usually a token of some kind.
For example, you perform a GET /current-user with an Authentication header containing a JWT token. The server can get most of the user info of the current user from the JWT token and complete with data from the database and retrieve it back to the caller.
I'd also recommend not to use camel case in URIs. It can be a nightmare for devs and some servers are case insensitive.
Beware, if you are holding a server user session, as you imply in your question, your API is already stateful.
As #n00b says, REST isn't a formal standard - and that's probably a good thing.
The original definition comes from Roy Fielding's dissertation. - so if you're doing the things Roy recommends, your design is RESTful. There are a few other things people have added to that - for instance, the Richardson Maturity Model is pretty commonly accepted. There are a few public "standards" documents on the web, e.g. Microsoft's version. I don't think they address this question directly, though.
So, it's up to you - but for what it's worth...
I believe APIs should be consistent and predictable. If I am asking for information about a user, I don't really like that there are two ways of doing it - one by ID, and one using a magic identifier for the current user. I also don't like the idea of introducing the concept of state into the API - by saying "there's an conceptual entity in your API called current user", you are introducing the concept of statefulness, even if you use HTTP headers to manage that.
So, if your RESTful API is designed for use by client application, I think it's reasonable to ask that client to manage state, and carry around the ID for the current user. This also makes your GET requests consistently cacheable - you can theoretically cache /users/123, but you cannot cache /loggedUser.
I believe there is a logical difference with your authentication and authorization action (I've logged in, proven who I am, and therefore got access to specific resources on the system), versus "I am user 123".
The reason you might disagree with this is that it makes your API harder to discover by human beings - someone who is trying to figure out how to get information about the current user has to log in, and then remember their user ID.

Authorization and the query string in REST API design

We have a design where a user has access to products, but only in a certain category.
A superuser can list all products in all categories with a simple GET request, such as GET /products.
Simple filtering already exists via the query string, so the superuser can already restrict his search to category N by requesting GET /products?category=N.
Say that user X is authenticated, and user X has access to products with category of 3.
Should an API server:
mandate that the user pass the filter for the appropriate category -- ie require GET /products?filter=3, and GET /products would fail with 403 Forbidden? -- or
expect a simple GET /products and silently filter the results to those that the user is authorized to access?
expect a simple GET /products and silently filter the results to those that the user is authorized to access?
Changing the representation of a resource depending on which user is looking at it strikes me was a Bad Idea [tm].
Consider, for instance, the use case where a uri gets shared between two users. They each navigate to the "same" resource, but get back representations of two different entites.
Remember - here's what Fielding had to say about resources
The key abstraction of information in REST is a resource. Any information that can be named can be a resource: a document or image, a temporal service (e.g. "today's weather in Los Angeles"), a collection of other resources, a non-virtual object (e.g. a person), and so on. In other words, any concept that might be the target of an author's hypertext reference must fit within the definition of a resource. A resource is a conceptual mapping to a set of entities, not the entity that corresponds to the mapping at any particular point in time.
Now, there are conceptual mappings which depend on the perspective of the user (e.g. "today's weather in my city"). But I'm a lot more comfortable addressing those by delegating the work to another resource (Moved Temporarily to "today's weather in Camelot") than I am in treating the authorization credentials as a hidden part of the resource identifier.
If consumers of your api are arriving at this resource by following a link, then 403 Forbidden on the unfiltered spelling is fine. On the other hand, if consumers are supposed to be bookmarking this URI, then implementing it as a redirecting dispatcher may make more sense.
The redirecting approach is consistent with remarks made by Fielding in a conversation about content negotiation on the rest-discuss list in 2006
In general, I avoid content negotiation without redirects like the
plague because of its effect on caching.
E.g., if you follow a link to
http://www.day.com/
then the site will redirect according to the user's preference to one of
http://www.day.com/site/en/index.html
http://www.day.com/site/de/index.html
Both of the solutions are perfectly valid. You can always hide things when the user does not have the permission to see them. This means, that you can display a filtered representation of /products by the actual user, or you can hide the /products resource and give link only to the /products?filter=3 resource. I don't think there is a best practice here, since both solutions are easy to implement.
#VoiceOfUnreason:
Apparently you did not read Fielding's work carefully enough.
Changing the representation of a resource depending on which user is
looking at it strikes me was a Bad Idea [tm].
The representation depends on the whole request, not just on the GET /resource part. The Authorization header is part of the HTTP request as well. So changing the representation depending on the Authorization header is valid in REST. It is just the same as changing the representation depending on the Accept header. Or do you say that we should serve XML even if somebody requests for JSON? It is a huge mistake to think that a single resource can have only a single representation. Another mistake to return a broken link to the client and let them waste resources by sending pointless HTTP messages...
Consider, for instance, the use case where a uri gets shared between
two users. They each navigate to the "same" resource, but get back
representations of two different entites.
REST is for machine to machine communication and not for human to machine communication! The browser is not a REST client. Or did you mean that a facebook bot will share the link with a google crawler? Such a nonsense...

How to deal with per verb permission in Rest on a client?

Lets assume we have a resource on an URL like so: foo.com/api/bar
And lets say that a user might be allowed to GET that resource, but not allowed to POST to that resource.
I can easily solve that by specifying different permissions per verb.
But how should the client know on beforhand if it is allowed to perform the POST?
Lets say we have a "save" button on a page, that should not be enabled if the user lacks the rights to do a POST.
I know about HATEOAS/Hypermedia constraint, and that I can pass a list of links for different actions together with the resource.
But AFAIK, that doesn't carry information on what verbs to use, only URL's for different actions.
Are there other variations where the verb is included?
Are there other approaches if you don't want to clutter the resource with all sorts of metadata?
This has been asked a lot on the HAL discuss forums https://groups.google.com/forum/#!forum/hal-discuss
The fact that verbs aren't returned is a decision of the hypermedia format you're using, which i'm guessing is HAL (or maybe collection+json). Some formats DO include verb information.
HAL actually allows you to include custom fields on your link objects if you wish, but i would discourage this because any standard client won't know how to interpret this.
But also i've found the verb to be worthless in the end.
First off in human 2 machine the user is going to read documentation. HAL has all of it's links dereference (via CURIE's as they are currently naemd) to human readable documentation that should describe the effects of requesting that link with different parameters, verbs, headers, etc.
Next off is that for your Application to be truly RESTful you should respond to all verbs...you might just not respond that the verb was OK. For an HTTP based app returning a 405 is VERY appropriate. Returning a 404 is not! A 500 would be worse!. Your 405 should include what methods are available for the requested resource.
Next in the case of machine 2 machine (and a bit of h2m) your application when accessed via HTTP (i try to avoid http in my answers as RESTful applications aren't necessarily HTTP..although i'd say 101% of them are) should use the OPTIONS method (http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html) against the resource URL in order to get a description of what's possible.
Here's where i see a lot of people getting tripped up, what should the response of OPTIONS be? well what people forget is content type negotiation! The requester should say what format for option information they expect. Accept: some-machine-language/xml or application/language+json. Some RFC or standards define these content types and your API can identify what formats it supports. I would suggest you include support for text/html so that you can return human readable documentation as well about what verbs are supported. This covers the h2m scenario nicely.
The same content type negotiation can be useful when returning info about a method not being supported. The server can send a content-type that the client can understand that describes semantically what methods are allowed.
The final thing i like to point out is that methods imply client intent. i want to PUT this resource or DELETE that resource. The server should accept requests and return responses indicated what state transitions occurred because of that request. Thus it's a little silly to have the API identify possible intents of the client with every request. The client knows what it wants to do, it should try, and if it can't then it should deal with that.
HTTP Verbs are pure transport protocol verbs. Those might not be the right verbs to do application functions, precisely because of the issues you mentioned in the question. So let us see if we can approach this differently without using http verbs. Doing http verbs to do appliction actions might limit us tommorrow as we might have need to move from http to another protocol.
LEt us take an example to illustrate. Let us say we are talking about Update Delete application using HATEOAS. So in this case, if the there are two products, represented by the URL www.abc.com/product/001 and www.abc.com/product/002. In a true HATEOAS situation, If the response of the two products product/001 and product/002 has to be looked at show the client screens.
So if the response to product/001 has a response product/001/delete,product/001/change and product/002 has the response product/002/Change then the client will show delete for only product/001 and change for the other two products.
So in response to your question. By appropriately identifying actions with product now it is possible to do role based actions.
I hope i have answered your question.