REST API Design – How to Handle Fine-Grained Field-Based ACL Permissions in a RESTful Service?

api-designrest

I've been trying to design a RESTful API and have had most of my questions answered, but there is one aspect of permissions that I'm struggling with.

Different roles may have different permissions and different representations of a resource. For example, an Admin or the user himself may see more fields in his own User representation vs another less-privileged user. This is achieved simply by changing the representation on the backend, ie: deciding whether or not to include those fields.

Additionally, some actions may be taken on a resource by some users and not by others. This is achieved by deciding whether or not to include those action items as links, eg: edit and delete links. A user who does not have edit permissions will not have an edit link.

That covers nearly all of my permission use cases, but there is one that I've not quite figured out. There are some scenarios whereby for a given representation of an object, all fields are visible for two or more roles, but only a subset of those roles my edit certain fields.

An example:

{
    "person": {
        "id": 1,
        "name": "Bob",
        "age": 25,
        "occupation": "software developer",
        "phone": "555-555-5555",
        "description": "Could use some sunlight.."
    }
}

Given 3 users: an Admin, a regular User, and Bob himself (also a regular User), I need to be able to convey to the front end that:

Admins may edit all fields, Bob himself may edit all fields, but a regular User, while they can view all fields, can only edit the description field. I certainly don't want the client to have to make the determination (or even, for that matter, to have any notion of the roles involved) but I do need a way for the backend to convey to the client which fields are editable.

I can't simply use a combination of representation (the fields returned for viewing) and links (whether or not an edit link is availble) in this scenario since it's more finely grained.

Has anyone solved this elegantly without adding the logic directly to the client?

Best Answer

How about adding specific permissions as 'links' in your resource representation. Basically, letting the client know what attributes are available to the updated (by regular users). Both Admin and Self are non-regular users which are allowed to edit everything. Based on your example that regular users can edit only the 'description' field, here are my thoughts:

{
    "person": {
        "id": 1,
        "name": "Bob",
        "age": 25,
        "occupation": "software developer",
        "phone": "555-555-5555",
        "description": "Could use some sunlight.."
        "_links": {
           "href": "/person/1",
           "method": "PUT",
           "attributes": ["description"]
        }
    }
}
Related Topic