I'm creating an API where based on the permissions that authenticated user different properties of objects can be changed.
Whats the common way to approach this problem?
Should i have endpoints like
/admin/users and /users with different API definition and capabilities?
It sounds rather inflexible design, what about situation where user can have permission like can_modify_foo_prop and can_modify_bar_prop?
I was thinking a better solution would be instead to just provide one endpoint /users and based on authenticated user roles some fields would be read-only/hidden instead? That seems more flexible but could be more annoying to document/implement.
Remember, URI means Uniform Resource Identifier. Which means a given user (concept) should be always identified by the same URI, hence I would suggest your second proposal, to have a single hierarchy/list of users:
/users/1
/users/2
...
It is acceptable to define (in the appropriate Media-Type) the returning document to hold properties based on the current user's permissions.
Now, regarding whether that is easy to use or not is subjective. I would argue that returning pure data is always somewhat inconvenient, because the client has to parse and understand the data. This is why HTML and HTML Forms were created, so the client does not need to know how to present the data, and also doesn't need to know what's editable and what is not. Then again, I don't know your exact use-case.
Related
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.
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.
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...
I have resource endpoints that I would like to respond differently to the user that tries to access the endpoint.
Scenario
Let us say that I have a resource endpoint /users, and the following UserTypes:
GirlUser
BoyUser
Admin
When a GirlUser executes a GET on /users I want to only allow for other GirlUsers to be accessible. I would expect BoyUsers to have a similar result, and Admins to receive all users.
My Question
Is it more RESTful to:
Handle this with different GrantTypes or Scopes through OAuth, using the one /users endpoint.
Have different endpoints, such as: users/girls, users/boys, and users/all.
Have different APIs for the different types of users.
I'm totally off-base with possible answers and it's something that I don't expect.
Would anything change if I have other endpoints that I would want to only be operational for a certain UserType?
(For example, ones that process payments.)
Thank you.
Your endpoints should be independent of the sex of the user. What's the problem in having a common User endpoint. (You are doing it right already!!)
Though it depends on the kind of information that you want to return, the kind of resources in hand. Are you returning JSON/XML? You have a Girl and a Boy class that you work with in the backend. If a girl user hits the endpoint you serialize objects and return data to the user - that sounds okay to me.
If your UML design does not differentiate between girls/boys then you should have the same endpoint.
In order to understand the problem properly,
i) What kind of data are you returning?
ii) How have you designed the UML?
iii) Are you returning some data from a DB? Is it expensive to run all girls/all boys query on it everytime the endpoint is hit?
As for scopes, in OAuth one scope generally corresponds to one endpoint. Like in Google, G+ is a scope, google drive is a scope. We don't see G+ girls, G+ boys scopes, do we now?
In java terms, the closest match to the API design is a Factory pattern (that's how I explain it to myself, might not be technically correct) - depending on the type of user you call a specific method that returns data. The endpoint should be generic and extensible - having separate API's is indeed a bad design as it leaves little to expansion.
To access an instance of a User in a restful web-service the url is structured as shown in the curl request below:
curl -v -X GET -s "$BASE_URL/User/${customer_id}.json"
If I wanted to specify all User entities or page through a range of User entities, such as the first 50 Users in my database, how would I structure my request so that it is compliant with REST ???
You should start by trying to de-emphasize the meaning of the characters in a URI. While nice, pretty and readable URIs are a good thing, they have nothing to do with REST -- in fact it's a good exercise to judge the design of a RESTful interface by changing all the URIs to meaningless strings, and add the prettiness afterwards. A client should never have any knowledge of the server's URI structure, for the simple reason that the server won't be able to change it afterwards.
Next, if a list of customers is a meaningful concept to you, you should by all means turn it into a resource of its own right. In its representation, you might want to include some information about each individual customer, along with a link to each individual customer resource.
Paging? Good idea -- turn each page into its own resource, and link them together. Take a look at the way Google presents search results for a hint.
Often that's all you need because it's not necessary for the client to be able to specify the page size. But if it is, you essentially have two options: You can have a resource that encapsulates a form that allows you to specify the parameters that, when submitted, will directly or indirectly via a redirect take you to the appropriate URI. Or you can include a poor man's form, a URI template.
In any case, and to re-iterate my first point: Don't view a RESTful interface as an API that manifests itself as a set of URI construction rules. Instead, think of resources, representations, and hypermedia.