I am working on an API in a system that has very complex access control rules. Often times there are complex SQL queries required to determine if a user has read or write access to a particular resource. This causes a lot of complexity and redundancy in our client applications as they have to know all these rules in order to determine whether to present the user with CRUD options for each object.
My goal is to reduce much of the complexity on the client side and house all the complex logic in the API. This way new client applications written against our API can avoid re-implementing the complex access rule logic on their side when ensuring that the UI only presents valid options to the user.
I am not sure what the best way is to handle this. I'm considering two different options but I don't know if there is a better or more standard way to expose generic access information to callers of an API.
When a caller makes a GET request on a resource entity or collection of them, every returned entity will return an _allowed_actions
field attached, which is an array of actions the caller is allowed to perform on that entity. For example, requesting a Listing
object may result in the following response.
GET /listing/5
{
"id": 5,
"address": "123 Foo Street",
"city": "New York",
"state": "New York",
"price": 457000,
"status": "pending",
"_allowed_actions": ["READ", "UPDATE", "DELETE"]
}
Still unsure how to relate to clients whether they have the authority to create instances of a resource entity using this method, but perhaps the client will simply need to maintain enough understanding of the permission structure to determine this on its own. The access rules around creating instances are typically less complex than the READ/UPDATE/DELETE access rules so that doesn't seem too bad.
Create a meta-API, which clients can make requests to in order to determine what actions they can perform on each resource. For example, checking what the client can do with a listing:
GET /access-query/listing/5
{
"allowed_actions": ["READ", "UPDATE","DELETE"]
}
And checking what options are allowed for listings in general, including CREATE:
GET /access-query/listing
{
"allowed_actions": ["READ", "CREATE", "UPDATE", "DELETE"]
}
The benefit of this approach is that it allows callers to have a full understanding of what they can do on every resource in a generic way. This way clients wouldn't have to understand that the "create_listing" permission AND a non-probationary user status are required required in order to create listings. They can simply query for this information ahead of time.
The downside to this approach is that it increases the amount of requests. Rather than require clients to have an understanding of the permissions logic, they now have to query once to determine what they can do and a second time to do it.
I don't particularly care for either of these methods but they're all I can come up with at the moment. Is there a better way to go about this?
Application credential requirements The client must create a POST call and pass the user name, password, and authString in the Request headers using the /x-www-form-urlencoded content type. The AR System server then performs the normal authentication mechanisms to validate the credentials.
OAuth 2.0 is the best choice for identifying personal user accounts and granting proper permissions. In this method, the user logs into a system. That system will then request authentication, usually in the form of a token.
What you are looking for is fine-grained, externalized authorization:
There is a model called attribute-based access control (ABAC) that defines an approach to fine-grained externalized authorization. NIST, the National Institute of Standards and Technology, has produced a report on ABAC which you can read online.
OASIS, the organization for the advancement of structured information standards, has defined a standard called XACML (eXtensible Access Control Markup Language) to implement ABAC.
XACML brings you:
With a XACML-based approach, you get to maintain your business logic and your API separate from the authorization logic. This has several benefits:
I recommend you check out the following resources:
There are both vendor and open-source implementations of XACML:
HTH, David.
Not trying to resurrect an old question, but I came here searching for almost exactly the same thing and wanted to add a solution that I think is more RESTful.
I haven't actually implemented this but think it may help others who come here...
Your second option is very nearly what I think should be done, but instead of a get use the OPTIONS verb to your resource which will then return an "allow" header with a list of available verbs for that resource.
OPTIONS /listing/5
Assuming your resources are fine-grained enough for this to make sense, then you would know if you can make a POST/DELETE
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With