Role-based access control (RBAC) vs. Claims-based access control (CBAC) in ASP.NET MVC

What are the main benefits of using CBAC vs. RBAC? When is it better to use CBAC and when is it better to use RBAC?

I'm trying to understand the general concepts of the CBAC model but the general idea is still not clear for me.


Solution 1:

I will try to explain the Role/Claim/Permission-based Access Control concept in layman's terms. The code snippet I will present here, are pseudocode, may or may not compile.

What are Roles?

Roles can be thought of as Job Titles. Like "Sales Manager", "Marketing Manager", "Admin" etc.

What are the claims?

Claims can be broader than a Role. You can think about Claim as a TAG. For example, you can tag a person as "Friendly", "Talkative", "European", "Photographer", "Adult-who-is-18-years-old" etc. Technically, a role can be thought of as a claim too.

Role-Based Access Control

Very simple. Instead of using words, let's show some examples. Say, you allow visiting some pages on your website by checking Roles. Like this:

    [Authorize(Roles="Sales Manager")]
    public ActionResult CreateCustomer()
    {
        return View();
    }

    [Authorize(Roles="Marketing Manager")]
    public ActionResult EditLandingPage()
    {
        return View();
    }

Claims Based Access Control

In layman's terms, in Claims Based Access control, you check for claims instead of a role when determining access to a page.

(This is a pseudo code. ClaimsAuthorize is not a built-in class in MVC, rather, you may find some NuGet packages for that or you can write your own)

    [ClaimsAuthorize(Claims="Senior-Employee, Award-Winner-Employee, Experienced-On-Sales")]
    public ActionResult CreateCustomer()
    {
        return View();
    }


    [ClaimsAuthorize(Claims="Trust-worthy-Employee, President")]
    public ActionResult DeleteCustomer()
    {
        return View();
    }

    [ClaimsAuthorize(Claims="Adult-over-18years")]
    public ActionResult ViewImagesOfViolence()
    {
        return View();
    }

Notice that, instead of checking for roles, we are allowing to visit a page based on WHO the user is claiming to be.

RBAC vs CBAC

Ok, now, if you ask what is the benefit of Role-based access control or Claim based access control, then, think about this page "ViewImagesOfViolence". Is not it more intuitive to check for a claim "Adult-over-18years" when determining if you should allow the user to visit that page? In a word, using Claims, you can create more segments within your users comparing roles. In an abstract sense, all roles can be claims too, but claims cannot be thought of as roles.

Permission-based access control

Instead of checking for Roles or Claims when allowing permissions to view a page, you should rather think about Permission-based access control. Let me show you some pain points.

When you are using Role-based authentication, if you have an action for creating customers and you want that the people who are in the 'Sale' role should be able to do that, then you write code like this:

[Authorize(Roles="Sale")]
public ActionResult CreateCustomer()
{
    return View();
}

Later, you realized that, sometimes, people from the 'Marketing' role should be able to create Customers. Then, you update your Action method like that

[Authorize(Roles = "Sale", "Marketing")]
public ActionResult CreateCustomer()
{
    return View();
}

Now, you realized that some of the marketing people must not be able to create Customers, but it is not possible to assign a different role for those people who are in Marketing. So, you are forced to allow all marketing people to create Customers.

you spotted another problem, anytime you decide that Marketing people should be allowed to create customers, you have to update all of your MVC Action methods Authorize attribute, compile your application, test, and deploy. Some days later, you decided, not marketing but some other role should be allowed to do the task, so you search in your codebase and delete all 'Marketing' from Authorize attribute and add your new role name in Authorize attribute... Not a healthy solution. At that point, you would realize a need for Permission-Based Access Control.

Permission-Based access control is a way of assigning various permissions to various users or various roles or various claims and checking if a user has permission to execute an action from the code in run time. If you assign permission to a role or a claim, then, you would check what are the roles or claims for that logged-in user. And then, you will check what permissions are available for those roles or claims.

You can define some set of permissions like this :

"CanCreateCustomer", "CanDeleteCustomer", "CanEditCustomer".. etc..

Now, you can decorate your Action Method like this:

[Authorize(Permission="CanCreateCustomer")]
public ActionResult CreateCustomer()
{
    return View();
}

Please note, [Authorize(Permission="CanCreateCustomer")] may not be built into the MVC class library, I am just showing as an example in an abstract sense. There can be a NuGet package that will have Permission property in Authorize class.

Now, you can see that, CreateCustomer action method will always need permission 'CanCreateCustomer' and it will never change or hardly change.

Who will get the permissions?

You can assign a set of permissions directly to a user. But do not do that. It will be tremendously difficult to manage that. Rather,

You can assign a set of permissions to a Role Or you can assign a set of permissions to a Claim (Recommended).

As I mentioned, roles can be thought of as claims too. So, you can treat the roles as claims. Then, you can create a table of Claims in your database. Then, create another table for holding the relations where each claim can contain multiple permissions.

This security model offers you clean code practice. Moreover, when you write your Action Method, you don't have to think about who can use this method, rather you can always be assured that whoever is using this method will have proper permission given by the Admin. Then, Admin can decide who will be able to do what. Not you as a developer. That's how your business logic is separated from Security logic.

Whenever someone signs in, your application will check whatever permissions are available for that user and that permission set will be available as additional properties of the currently logged-in user, so you don't have to check permission set all the time from the database. The bottom line is, you get more control of your security logic in your application if you apply permission-based access control.

If your application is a very little application where there would be only 2 roles: Customer and Admin and there is no chance that Customers will be able to do anything else other than what they are meant to do in your application, then perhaps, simple Role-based access control will serve the purpose, but as your application grows, you will start to feel the need of permission based access control at some point.

Solution 2:

I have implemented security models many times now and have had to wrap my head around these concepts as well. Having done it many times, here is my understanding of these concepts.

What Are Roles

Role = The union of Users and Permissions.

On one hand, a Role is a collection of Permissions. I like to call it a Permission Profile. When defining a Role you basically add a bunch of Permissions into that Role so in that sense a Role is a Permission Profile.

On the other hand, a Role is also a collection of Users. If I add Bob and Alice to the Role "Managers" then "Managers" now contains a collection of two Users sort of like a Group.

The truth is that a Role is BOTH a collection of Users and a collection of Permissions put together. Visually this can be viewed as a Venn diagram.

What is a Group

Group = Collection of Users

A "Group" is strictly a collection of Users. The difference between a Group and a Role is that a Role also has a collection of Permissions but a Group only has a collection of Users.

What is a Permission

Permission = What a subject can do

What is a Permission Set

Permission Set = A Collection of Permissions

In a robust RBAC system, Permissions can also be grouped like Users. Whereas Groups are a collection of Users only, a Permission Set is a collection of Permissions only. This allows an administrator to add whole collections of Permissions to Roles at one time.

How Users, Groups, Roles, and Permissions Come Together

In a robust RBAC system, Users can be added to a Role individually to create the collection of Users in the Role or Groups can be added to a Role to add a collection of Users to the Role at one time. Either way, the Role gets its collection of Users from being individually added or by adding Groups to the Role or by adding a mix of Users and Groups to the Role. Permissions can be thought of in the same way.

Permissions can be added to Roles individually to create the collection of Permissions inside the Role or Permission Sets can be added to a Role. Finally, a mix of Permissions and Permission Sets can be added to a Role. Either way, the Role gets its collection of Permissions from being individually added or by adding Permission Sets to a Role.

The whole purpose of Roles is to marry Users to Permissions. Therefore, a Role is the UNION of Users and Permissions.

What Are Claims

Claim = What a Subject "is"

Claims are NOT Permissions. As pointed out in previous answers, a Claim is what a subject "is" not what a subject "can do".

Claims do not replace Roles or Permissions, they are additional pieces of information that one can use to make an Authorization decision.

When to Use Claims

I have found Claims to be useful when an Authorization decision needs to be made when the User cannot be added to a Role or the decision is not based on the association of User to Permission. The example of a Facebook User causes this. A Facebook User may not be someone who is added to a "Role" ... they are just some Visitor authenticated through Facebook. Though it doesn't fit neatly into RBAC it is a piece of information to make a authorization decision on.

@CodingSoft used the night club metaphor in a previous answer, which I'd like to extend. In that answer, the Driver's License was used as an example that contained a set of Claims where the Date of Birth represents one of the Claims and the value of the DateOfBirth Claim is used to test against the authorization rule. The government that issued the Driver's License is the authority that gives the Claim authenticity. Therefore, in a night club scenario, the bouncer at the door looks at the the person's Driver's License, ensures that it was issued by a trusted authority by examining whether or not it is a fake ID (i.e. must be valid government issued ID), then looks at the Date of Birth (one of the many claims on a Driver's License), then uses that value to determine if the person is old enough to enter the club. If so, the person passes the authorization rule by virtue of having a valid Claim, not by being in some Role.

Now, with that base in mind I'd like to now extend that further. Suppose that the building where the night club is contains offices, rooms, a kitchen, other floors, elevators, a basement, etc. where only employees of the club can enter. Furthermore, certain employees might have access to certain places that other employees may not. For example, a Manager may have access to an office floor above that other employees cannot access. In this case there are two Roles. Manager and Employee.

While visitors' access to the public night club area is authorized by a single claim as explained above, employees need access by Role to other non-public restricted rooms. For them, a Driver's License is not enough. What they need is an Employee Badge that they scan to enter doors. Somewhere there is an RBAC system that grants badges in the Manager Role access to the top floor, and badges in the Employee Role access to other rooms.

If for whatever reason certain rooms need to be added/removed by Role, this can be done using RBAC, but it is not a good fit for a Claim.

Permissions in Software

Coding Roles into the application is a bad idea. This hard codes the purpose of the Role into the application. What the application should have is just Permissions that act like Feature Flags. Where Feature Flags are made accessible by configuration, Permissions are made accessible by the User Security Context that is derived by the DISTINCT collection of Permissions gathered from all Roles the User has been placed in. This is what I call the "Effective Permissions." The application should only present a menu of possible Permissions to features / actions. The RBAC system should do the job of marrying those Permissions to Users through Roles. This way, there is no hard coding of Roles and the only time a Permission changes is when it is removed or a new one is added. Once a Permission is added to the software it should never be changed. It should only be removed when necessary (i.e. when a feature is discontinued in a new version) and only new ones can be added.

One final note.

Grant vs Deny

A robust RBAC system and even a CBAC system should distinguish between Grants and Denials.

Adding a Permission to a Role should come with either a GRANT or a DENY. When Permissions are checked, all GRANTed Permissions should be added to the Users list of Effective Permissions. Then after all that is done, a list of DENIED Permissions should cause the system to remove those Permissions from the list of Effective Permissions.

This allows administrators to "tweak" the final Permissions of a subject. It is best if Permissions can also be added to Users directly. This way, you can add a User to a Manager Role and they get access to everything, but perhaps you want to DENY access to the Lady's Restroom because the User is a male. So you add the male User to the Manager Role, and add a Permission to the User object with DENY so it takes away only that Lady's room access.

Actually, this would be a good candidate for a Claim. If the User has a Claim "gender=male", then being in the Manager Role gives access to all rooms but the Lady's restroom also requires the Claim gender=female and the Men's restroom requires Claim gender=male. In this way one would not have to configure a DENY permission to male Users since the Claim enforcement takes care of that for everyone with a single authorization rule. However, it could be done either way.

The point is that with DENIAL of Permissions it makes the management of the Roles easier because exceptions can be implemented.

Below is a diagram I made a long time ago that shows the RBAC model. I don't have a graphic for the Claims but you can imagine they are just attributes attached to the Users wherever they are. Also, the diagram doesn't show Groups (I need to update it at some point).

I hope this helps.

This is a Diagram of the RBAC Described Above

Update on April 7, 2019 Based on feedback from @Brent (thank you) ... removed unnecessary references to previous answers and explained the original basis of the "night club" metaphor provided by @CodingSoft in order to make this answer understandable without having to read other answers.