I finally managed to design my own system with the required functionality using the existing asp.net identity 2.0 tables + a few of my own.
I'm gonna call every AREA-CONTROLLER-ACTION trio as resources in my system. WebAPI included. Area itself is a resource. Controller itself is a resource. Action itself is a resource. Any combination of them, is also a resource. I'll auto generate everything from the system itself using reflection.
Also, I'm going to use the same AspNetRoles
table to store my User Groups. Users belong to one or more groups (Super Admin, Admin, Agent, Client etc.).
Using the existing Role based model as a user group based model with claims, I could get it working.Super admins are on god mode. They can create lower level users/groups/assign permissions etc.
Users can have special permissions. For example, Everyone in Agent group is denied access to updating a hotel, but a special agent who might also be the owner of a hotel can be given specific access to updating only their hotel.
Since the entire access control system runs on MVC area-controller-action sets. No one initially has no access (including super admins) and we gradually define which parts the groups/users has access to. And we give super admins and admins exclusive access through a claim. Access to everywhere is denied by default.
Once I Auto generated the AREA-CONTROLLER-ACTION sets, I let the user select which group has access to which item.
When the user logs in, I get all the resources the current user has access to and store them as claims. Based on that, using a claims auth manager, when a user request access to some resource, I can check their claims and decide if they should be given access to.
foreach(var claim in permissionClaims) {
var parts = claim.Value.Split(new [] {
'|'
}, StringSplitOptions.None);
if (parts.Length == 3) {
//var httpMethod = parts[0];
var action = parts[1];
var api = parts[2];
//Current.Log.Warn("Checking Access : " + req + " [action: " + action + "]");
// is this request for a API action?
if (api.Contains("API")) {
// if so, req must be for a API action
if (req.Contains("Api") && action.Contains(req)) {
Log.Trace("User has access to API : " + req + " [action: " + action + "]");
return true;
}
} else {
// this is for a MVC action
if (action.Contains(req)) {
Log.Trace("User has access to MVC : " + req + " [action: " + action + "]");
return true;
}
}
}
}
I have explained the approach in detail here - ASP.NET MVC Fine Grained Identity & Access Control.