Re: Modeling permissions with Hydra

Hi Ryan,

Am 29.10.2015 um 16:32 schrieb Ryan Shaw:
> We have an API for managing scholarly notes. The API is organized as
> follows: a scholarly project has a collection of notes associated with
> it. Projects may have multiple users, each of which may have different
> role-based permissions to do things with the project's notes. The
> names and permissions of these roles are project-specific. Users may
> belong to multiple projects and have different roles in each.
> 
> One of the main reasons we chose to use Hydra is to help clients
> understand what they are permitted to do with the various resources
> they have access to. So, our entry point to the API should show an
> authenticated user links to the note collections of all the projects
> with which the user is affiliated, and the client should be able to
> determine, e.g., which of these collections can be written to, and
> which can only be read.
> 
> If I understand correctly, there are several approaches we could take.
> (The thread on "Specifying operations for instances" [1] was critical
> for helping me understand this, by the way---the current version of
> the spec does not make these alternatives very clear.) For those
> readers that, like me, were unclear on the differences among these
> approaches, I've gone into pedantic detail descibing them below, but
> we might summarize them as follows:
> 
> 1. The first choice to be made is whether we want to specify supported
> operations by describing resource classes, by describing links, or by
> describing individual resources.

Summarizing this as:

Option a) overload the semantics of collections or links by subclassing
Link or Collection with "editable Link" or "editable collection"
constructs and let the clients choose the next transition based on that
semantics

Option b) Use the presence or absence of hypermedia controls (Links
supporting GET, PUT, POST, DELETE) to reflect the application state,
here: if the current state of the application disallows to update an
item, then there is no such control.

The latter follows the "Hypertext as the engine of application state"
(HATEOAS) constraint in the ReST architectural style. The constraints
reflect the conditions of the internet. One thing you achieve by this is
not to need server-side session state as application state, because that
doesn't scale well and makes it difficult to handle host failures.

The former requires the client to derive its application state not from
Hypertext controls, but from semantics "buried" in your vocabulary. The
knowledge about the possible options must be custom-coded into each
client that wants to use your service.

So, if you want to write a ReST API, then describe the possible
operations as hypertext controls on individual resources - use
hydra:operation.

If you feel that hypertext controls "pollute" your data, Ruben has
written an article which might let you reconsider:
http://ruben.verborgh.org/blog/2015/10/06/turtles-all-the-way-down/

A note on caching: If your authentication is based on the Authorization
field, then special conditions apply. See
https://tools.ietf.org/html/rfc7234#section-3.2

If you are not using the Authorization field, you must make sure you
have no expiration-based caching. One possibility might be to let the
client revalidate (Cache-Control: must-revalidate) so the server can
decide if the client should use a different representation or if it can
respond with 304 and an empty body so the client uses what it already
has. If you don't do this, you have to disable caching.

Since your service allows clients to change resources, it is probably
necessary to think about this anyway.

Making the ApiDocumentation dynamic only moves the caching problem
elsewhere - the client can't use a cached ApiDocumentation without
revalidating it - and it makes debugging the application way more
complicated.

In my view, the ApiDocumentation is the place where a service can
describe all its capabilities, regardless of resource or application
state. In that regard it seems counter-productive to hide edit
capabilities for non-admins in ApiDocumentation, since an implementer
browsing the ApiDocumentation will never know that the service also
supports editing. But that is something under discussion. Some people do
have a dynamic ApiDocumentation. The spec doesn't say what to do if
operations are dynamic and what the effect is if a class has
supportedOperations in ApiDocumentation and hydra:operation triples in
the response.

> 
> 3. A third decision to be made is the extent to which we expose or
> model the workings of the permissions system: ought we make clients
> aware that there are such things as user roles, for example by
> defining links based on roles, or should we simply say "these are the
> supported operations of this link" and hide the fact that those
> operations are being determined by the role of the user?


Hide the fact :)

Best regards,
Dietrich

Received on Friday, 30 October 2015 09:00:42 UTC