1

We currently have REST API, where you have a set of different resources, like:

GET /cats
GET /cats/{catId}
GET /dogs

Clients decide whether they can perform an action based on resource permissions. To query those the client calls:

GET /cats/{catId}/permissions

And gets back a list like "deleteCat", "sellCat", "initiateCatMating" etc., so its more complicated than read, write etc, i.e. calling OPTIONS is not working.

Now when the client gets let's say 100 cats, it has to call the permission endpoint 100 times. Resources are related, so the number of permission calls virtually explodes, to the amount of slowing the UI down when working with big lists.

I was thinking whether it would be a good/acceptable practice to include the permissions in all resources, like:

cat: {
name:string
permissions:[string]
}

This way the client will always know what it can do with the resource. Unfortunatelly I could not find any guidance on this, so this approach is either wrong or people just implement it as they like and don't care to ask questions. All I found were some ABAC references, which totally make sense, but solve I think only how the server can handle access easier. I want the client to know if it may call POST/cats/{catId}/matingPartner/{cat2Id} by knowing it has e.g. "initiateCatMating" permission for both cats, and if it doesn't than the "Choose mating partner" button should not appear in the UI.

Any opinions and links are appreciated.

  • what about GET /cats/permissions? – Martin Ba Nov 22 '19 at 9:32
  • 1
    That would work, but the client will have to match results of this EP to /cats. This EP will have to support the same pagination, filtering and sorting rules as /cats. All doable, but is that a common way? A REST "recommended" way? I feel kind of confused by the fact that I cannot find much info on the subject. – Maxim Zabolotskikh Nov 22 '19 at 9:41
  • It was just a suggestion that came to mind. I constantly feel confused by not finding much guideline for many non-trivial REST scenarios, so my help here is limited. :-) – Martin Ba Nov 22 '19 at 10:16
  • What do the presented permissions depend on? Is that only the (authenticated) client calling the API or also the specific cat? – Bart van Ingen Schenau Nov 22 '19 at 12:11
  • Also the specific cat. The client may have a certain permission on cat1, but not on cat2. – Maxim Zabolotskikh Nov 22 '19 at 12:20
4

I was thinking whether it would be a good/acceptable practice to include the permissions in all resources

This way the client will always know what it can do with the resource.

You are really close. In REST, the answer is hypermedia affordances.

Think about the web. How do you, as a client, know what you can do? You look for links and forms in the HTML representation of the resource (well, more precisely, a general purpose client renders a bunch of links and forms for you). If, for whatever reason, you aren't able to proceed along a particular workflow, the links and forms related to that workflow are removed from the representation.

(Note: this is purely "communicate possibilities to the client"; the server still needs to defend itself against inappropriate use).

For example, consider Wikipedia: you navigate to https://en.wikipedia.org/wiki/Hypermedia and at the top of the page is an "edit" link. That tells you how to navigate from the "read" resource to another that supports editing. The editing resource includes a big hypermedia form at the bottom, describing to the general purpose browser how to submit a request with your edits.

Atom Syndication and Atom Publishing achieve a similar result by defining link relations - an RDF triple that describes a relationship between the thing here and something over there. You signal to clients that an affordance is available by including a link to it in the representation.

cat: {
    name:string
    permissions:[string]
}

You may want to look into the JSON hypermedia standards that are under development, rather than trying to roll your own. SIREN, Hydra, and so on. Kevin Sookocheff discussed choosing among the alternatives, although you may want to look for something more recent than 2014.

  • Is "editing" really a resource? I would've thought that "editing" is an action you can do to a resource. – user253751 Nov 22 '19 at 14:05
  • 1
    @user253751 everything that can be named is a valid candidate for a resource. You just shouldn't confuse an edit form for a certain resource with the resource itself. The edit-form will usually have a submit-link that points towards the actual resource. As an update evolves around unsafe HTTP operation any (intermediary) cache will automatically invalidate any stored representation for the targeted resource so that a consecutive request will retrieve the new data instead of the old, outdated one. So, yes. A resource describing how to alter an other resource is a valid resource on its own. – Roman Vottner Nov 22 '19 at 14:42
  • "Any information that can be named can be a resource" -- ics.uci.edu/~fielding/pubs/dissertation/… – VoiceOfUnreason Nov 22 '19 at 15:44
2

Web Linking should be used when you return a cat resource to let people know what they can do with the cat. For example, if you want to tell people that they can update the description of the cat, when they do GET /cat/1 should return a link with relation type "edit". How the link is returned by the API depends on the content type, I think for JSON, JSON schema (draft standard) has definition for web linking. Here is an example in atom+xml from :

<link rel="edit" href="http://example.org/media/edit/the_beach.atom" />

When the client sees this link, they know they can edit the resource using the target URI. The semantic of "edit" is defined in Atom Protocol that the client sends a PUT request to the target URL.

The trick is to find a standard link relation type that match the use case. There is a list of standard types here. If you can't find one, then you can define your own proprietary type to suit your use case.

0

A seperate "permissions" resource isn't really a thing in REST, which is probably why you didn't see much about it.

If you want to know what HTTP verbs a resource accepts you can do an OPTIONS request and look at the "Allow" header.

For example a resource like "weather.com/current_weather" would not accept PUT or DELETE from a client, only GET. If you need to know that upfront you can get that information via and OPTIONS request which would not involve the server to do things like calculate the current weather.

But ultimately REST is a "beg for forgiveness" kinda thing rather than an "ask for permission" kinda thing

What I mean by that is it is better to just make the request and deal with any failures rather than try and work out on the client first if the request will work or not.

If the server won't let DELETE a resource or PUT a resource into a particular state it will tell you, hopefully with an explanation of why. It doesn't make much sense to query a different end point, where the server presumably has to do the same amount of work to figure out if the client has the permission as it would if it just handled the original request.

And passing permissions to the client in a previous request on a different resource couples resources unnecessarily and also risks the permission getting out of sync with the server.

So just make the request and then gracefully handle any failures

0

If the client needs the information to display everything correctly then GET /cats should provide it in the cat resource, as you thought.

If you want to achieve level 3 maturity you can express these permissions with links:

GET /cats HTTP/1.1

HTTP/1.1 200 OK
[various headers]

<cats>
  <cat id = "1234" name = "fluffy">
     <link rel = "/linkrels/cat/sellCat" 
           uri = "/cats/1234/sell"/>
  </cat>
  ...
</cats>

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.