Our application uses multiple ways for authorizing access to a given resource. Although it's working, it's messy and... well, it doesn't seem right.
We have well defined roles where each role has access to a set of the resources and different roles can access the same resources.
Resources, as of now, are simply MVC actions mapped in a database table as module
, controller
and action
.
This seems to be OK, but every time I need to add a new controller/action I have to map this resource to the database table.
Besides role-based authorization, users can have more or less access to a subset of resources of another role. Eg.:
RoleA: resources a, b, c, d
RoleB: resources x, y, z
RoleC: resources 1, 2, 3
User1: has RoleA but needs to access resource y
User2: has RoleB and RoleC but does not have access to resource z
This is implemented as an user_resources
table with entries for additional resources that the user has access or is denied (indicated by a flag).
I could create different roles with tailored access, treating roles as group of permissions, but that would lead to a roles explosion.
If that's not enough, some actions can only be performed when the model is in a certain state (each model knows when something can be done). Eg.: an order can only be edited if the user has access to the edit resource (through steps #1 or #2) and the object Order
can be edited.
Anoter example: an user can access a Customer
if he has access to /customer/view
resource and he owns that Customer (he is the contact info for that customer).
A role, group of roles or individual users can see more or less information about a model, depending on it's state.
How can I simplify this authorization process without loosing flexibility in giving or restraining access to resources?
There is any pattern I'm missing here to unify all this authorization in a single place?
After a long time I finally found an answer that satisfies all my requirements: http://lostechies.com/derickbailey/2011/05/24/dont-do-role-based-authorization-checks-do-activity-based-checks/.
His solution is to consider everything as an activity, the permission to execute/call/whatever an activity is given to a role and users can have multiple roles.
What shines in this approach is that the permission check is done on the activity itself, not on the roles.