Modeling Authorization
Published on Oct 14, 2018
Most applications need to take care of authorization. Authorization is the answer to the question of whether a request is permitted or not. We will look at different models of authorization using a meta-model in this article. I am going to use Casbin for concrete examples. You can experiment with example model definitions using Casbin Model Editor.
PERM Meta-Model
An instance of PERM (Policy, Effect, Request, Matchers) describes how these four kinds of entities interact with each other to build something that can used for authorization. First let's describe each of these entities and then look at an example model built using them.
- Request
- Information about the access request. A simple request would be a
tuple with the subject, action and the resource.
A concrete request model can have resources such as
physical hardware components like CPU caches or logical entities
built out of persisted data like customers in a CRM system.
r = {sub, action, resource}
- Policy
- A model of what can constitute a rule in the system, e.g., an
administrator should be allowed to read user info.
p = {sub, action, resource}
- Matchers
- A model of how requests and policies are matched.
The simplest example would be using equality for matching
requests and policies if the above models for those are used.
m = r.sub == p.sub && r.action == p.action && r.resource == p.resource
Given a request, a value is produced for every policy using this matcher expression. So, we have ap.eft
value for every policy in our policy set. We haven't defined instances of policies yet. We have only defined how those instances would look like, i.e. the policy model. - Effect
- A model for combining/reducing policies that match a given request
to a final result. Value of evaluating the matcher expression is
available in
eft
field in every policy.e = some(p.eft == allow)
The diagram below illustrates how a request is authorized using a model based on PERM.
Model Definitions
Here is the complete model definition for ACL-based authorization:
[request_definition] r = sub, obj, act [policy_definition] p = sub, obj, act [policy_effect] e = some(where (p.eft == allow)) [matchers] m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
For such a model, the policies that define authorization rules will look like
p, alice, data1, read p, bob, data2, write
If we wish to allow everything to the admin
user, all we need to change is
the definition of the matcher:
[matchers] m = r.sub == admin || (r.sub == p.sub && r.obj == p.obj && r.act == p.act)
To enable simple attribute based access control, we need access to the actual data in the resource object. For example if we only want to allow requests which are initiated by the owner of the resource, the matcher expression would change to:
m = r.obj.owner == r.sub && (r.sub == p.sub && r.obj == p.obj && r.act == p.act)
The PERM meta-model is flexible enough to allow us to switch to complex authorization models even if we start with a simple model in the beginning. An extension of the PERM model would be to allow materialized views of the resource based on policies. This requires that the final result is a resource rather than a boolean value. This might seem like a good idea in the beginning but it seems to be mixing two different ideas:
- Allowing access to a resource
- Building an instance of a logical resource based on constraints or the context.
For example, let's say a hypothetical SaaS company needs to manage credits for
multiple applications that register themselves on their platform (Ola credits,
Uber credits). There can be a field in the User resource, say credits
, which
has a list of credits (logically) for all these applications. Now, we must
ensure that credits for one application are not visible to any other
application. All applications have access to all other fields but this field
needs to be filtered. In my opinion, this field should have never been designed
such that it ends up with data for all applications while building the User
object/map/representation in memory. Share your thoughts about this in the
comments below.
Conclusion
PERM is a flexible meta-model for building authorization models.