ChatGPT解决这个技术问题 Extra ChatGPT

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.

These concepts are still also very vague to me. They seem to do the same thing as well. The one is just a roles with a value?

E
Emran Hussain

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.


What I'm confused about is how Roles factor into claims - aren't in claims-based systems roles basically a grouping of claims so that you can mass-assign stuff? eg you can say Bob is in role Marketing and everyone in Marketing has claims CanCreateCustomer, CanViewAdCampaigns
Wow, I've been trying to figure out how this whole claims thing works but I NEVER understood all the vague abstract explanations and examples. Your post was the first that opened my mind and got the message across. Thank you so much for explaining it so concise.
This is a very thoughtful explanation, but I think you recognized that it is incomplete with your comment "The difference is in concept, rather than technology." There actually is a difference in technology, which this answer doesn't address. In short, I disagree that it depends on how you define Role as the two technologies satisfy very different requirements. I hesitate to offer correction as the answer itself is very helpful in demonstrating traps associated with applying authorization roles (or claims) which are too broad. Unfortunately that wasn't the question asked.
Suppose I want it like this: 1) A "permission" is a right to do one simple action, like "Create a customer". Permission's name begins with "can" - CanCreateCustomer. Permissions' names are hardcoded in the app's source code. 2) A user can be assigned a set of permissions - but not directly. The user receives permissions only through the roles. 3) A role is a set of permissions, nothing more. Some of end users (admins) can dynamically create new custom roles with arbitrary set od permissions (chosen from fixed list). The question is: CAN I DO IT LIKE THIS with the Claims-based model?
Microsoft documentation says: A claim is name value pair that represents what the subject is, not what the subject can do.
R
Ricardo

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.


This is a great explanation that should be upvoted to the top, thank you for adding the example and diagram.
Great answer. One recommendation would be to remove references to other answers. Each answer should stand alone, and although i read the other answers, not everyone will.
Thank you Brent. Great idea. I swept through the answer and tried to improve it by removing unnecessary references to other answers and by explaining the basis of the night club metaphor so it doesn't require reading the other answer. If you have any further suggestions for improvement I will be happy to promptly apply them. Thanks again.
this is awesome and explained in great normal language - thank you
Hello @SPopenko I appreciate the kind words. 1) Identity providers like OAuth are for "authentication" (i.e. prove who you are), whereas this thread is about "authorization" (i.e. what you are allowed to do). Once authentication is proven, then authorization is applied. 2) These kinds of permissions are against data not software artifacts. This thread is about authorization of capabilities like buttons, access to pages, tabs, etc. Data that is created by users is another matter and is outside the scope of this thread. I recommend asking a new question for that. 3) Sorry I don't have a PoC
P
Pushpendra

I don't fully agree with Emran's answer

[Authorize(Roles="Sale")]

Is naive

The question is how

  [Authorize(Roles="CustomerCreator")]

is different from

 [ClaimAuthorize(Permission="CanCreateCustomer")]

If both are equally good, why we need claim ?

I think because

Claims concept is more generic compared to Role

In context of the example above we can say "CustomerCreator" is a claim of type "role" provided by "Asp.NETroleProvider"

Additional examples of claims.

"AAA" is claim of type "MYExamSite.Score" provided by "MYExamSite.com" "Gold" is claim of type "MYGYM.Membershiptype" provided by "MYGYMApp"


I think this answer has value as it addresses the fundamental difference between a claim and its equivalent role, rather than describing a scenario that can be effectively implemented using either a claims or role-based authorization model. +1
This is how roles are done in MSSQL. it has DBDataReader and DBDataWriter not MyAppDB and HisAppDB.
How do roles mean appointment? In RBAC Roles are assigned with permissions.
Thank you for your feedback. I have updated my answer and I hope, this time, I have amended previously stated ambiguous and confusing parts.
h
hemp

The accepted answer appears to position Roles as a blunt object and Claims as a flexible tool, but otherwise makes them seem nearly identical. Unfortunately, this positioning does a disservice to the concept of claims and may fundamentally reflect a slight misunderstanding of their purpose.

Roles exist and make sense only within an implicit scope. Generally that is an application or organizational scope (i.e. Role=Administrator). Claims, on the other hand, can be 'made' by anyone. For example, Google authentication may produce claims including a user's "email", thus attaching that email to an identity. Google makes the claim, the application chooses whether to understand and accept that claim. The application itself might subsequently attach a claim called "authenticationmethod" (as ASP.NET MVC Core Identity does) with a value of "Google". Each claim includes a scope so that it's possible to identify whether a claim has meaning externally, locally, or both (or more fine grained as needed.)

The key points are that all claims are explicitly attached to an identity and include an explicit scope. Those claims may of course be used for authorization - and ASP.NET MVC provides support for that via the Authorize attribute, but that is not the only or necessarily even primary purpose for Claims. It certainly doesn't distinguish it from Roles, which can be used in exactly the same ways for locally scoped authorization.

So one can choose to use Roles, or Claims, or both for the purpose of authorization and likely find no inherent advantage or disadvantage to either, so long as those Roles and Claims are locally scoped. But if, for instance, authorization depends upon external identity claims, then Roles will be inadequate. You would have to accept the external claim and translate it into a locally scoped role. There isn't necessarily anything wrong with that, but it introduces a layer of indirection and discards context.


Good answer... I think I understand you..., but it would be clearer if you could provide some concrete example (possibly in ASP MVC context)... the answer is too abstract I am having a hard time wrapping my head around it.
The second paragraph does include a concrete example related to ASP.NET MVC Core Identity and Google authentication. It sounds like a more detailed walk-thru of Core's new model would help - for that I recommend this article: andrewlock.net/introduction-to-authentication-with-asp-net-core
Best answer IMHO
B
Benjamin Nguyen

The fundamental between RBAC and CBAC is that:

RBAC: a user must be assigned to a role to be authorized to perform an action.

CBAC : user must have a claim with the correct value, as expected by the application, to be authorized. Claims-based access control is elegant to write and easier to maintain.

Beside that claims are issued to the application by an issuing authorize services (Security Service Token STS) that is trusted by your application (Relying Party)


B
Bouke

It is important to first analyse what the Authentication is required for before deciding on which method is best. From Claims-Based Authorization:

A claim is not what the subject can do. For example, you may have a driver's license, issued by a local driving license authority. Your driver's license has your date of birth on it. In this case the claim name would be DateOfBirth, the claim value would be your date of birth, for example 8th June 1970 and the issuer would be the driving license authority. Claims based authorization, at its simplest, checks the value of a claim and allows access to a resource based upon that value. For example if you want access to a night club the authorization process might be: The door security officer would evaluate the value of your date of birth claim and whether they trust the issuer (the driving license authority) before granting you access.

From this example we can see that accessing a nigh club with a Claims-Based Authorization is quit different from the type of Authorization that will be required by the staff who work in the night club, in this case the staff of the night club will require a Role based Authorization which is not required for the night club visitors as the night club visitors all have a common purpose at the night club hence in this situation a Claims-Based Authorization is suitable for the night club visitors.

From Role based Authorization:

When an identity is created it may belong to one or more roles. For example, Tracy may belong to the Administrator and User roles whilst Scott may only belong to the User role. How these roles are created and managed depends on the backing store of the authorization process. Roles are exposed to the developer through the IsInRole method on the ClaimsPrincipal class.


D
David Brossard

More broadly, you should consider attribute-based access control (ABAC). RBAC and ABAC are both concepts defined by NIST, the National Institute of Standards and Technology. CBAC, on the other hand, is a model pushed by Microsoft which is very similar to ABAC.

Read more here:

Role-based access control NIST page

Attribute-based access control NIST page


While the recommendation to use Attribute-based access control is great. Links to common/best practices of implementing these in the MVC/WebAPI stacks would be nice. Thanks
V
Venkat Naidu

Role is just one type of Claim. Like that, there can be many other claim types, for example user name is one of the claim type


T
Teoman shipahi

If you want a real life example;

You have a school system, and teachers can login and see their students. Those teachers are under "Teacher" role. But we don't want all teachers to see all students, so we need to differentiate same level of people with their claims.

Mary - Math Teacher (claims: math) -> can only see math students John - Physics Teacher (claims: physics) -> can only see physics students Adam - Physics and Chemistry Teacher (claims: physics, chemistry) -> can see physics and chemistry students.

While all those three teachers are under Teacher role, they can only see students with their corresponding claims.

And there is a principal who's name is Mike:

Mike - Principal (role: Admin, claims: n/a) -> can see and manage all students since he is under admin role, regardless he does not has any claim.

If we need to differentiate admin level people, we can assign related claims to each of them.


p
pixelda

It is also possible to manages roles in a claims manner.

Instead of creating authorisation roles that reflect a business role, create roles that reflect action roles, e.g. CreateCustomer, EditCustomer, DeleteCustomer. Annotate methods as required.

It is not a simple matter to map individuals to a set of action roles, especially as the role list gets larger. Therefore, you'll need to manage the business roles at a lower level of granularity (e.g. Sales, Marketing) and map the business Role to the action roles required. I.e., add a user to a business role and it maps them to the required (action) roles in the existing authorisation table.

You can even override the business role and add a person to an action role directly.

Because you build on top of what already works, you don't undo the existing Authorisation process. You need only a few more tables to implement this approach


A
Ahmed Bahtity

I think this question could be answered from the database prospective. if you noticed how the tables involved in this implantation you will find the following

AspNetUsers : each user has one row with all the attributes required by all users like email, address phone, password..... AspNetRoles ; defines different roles as per application requirements like GM , CTO, HRM,ADMIN, EMP. what each roles defines is as per application needs. AspNetUserRoles: each row links AspNetUsers and AspNetRoles and effectively links between one user and many roles. AspNetUserClaims: each row has key to AspNetUsers and one type and value. so effectively add one attribute for each user that could be added/removed at run time.

The usage of this tables could be tweaked at one moment of user/application life time to match specific needs.

Consider the early stage of "Purchasing Manager" (PM), we could have three approachs

Application populates AspNetUserRoles with one row to grants 'PM' right to buy. To issue purchasing order with any amount, user only need "PM" role. Application populates AspNetUserRoles with one row to grants 'PM' right to buy, and populates the AspNetUserClaims a claim of TYPE 'Purchasing Amount' type and "<1000" value to set the amount limit. To issue purchasing order, user need to has 'PM'and the order amount be less than claim value of claim TYPE 'Purchasing Amount'. Application populate AspNetUserClaims with claim of TYPE 'Purchasing Amount' type and "<1000" value. Any user can issue purchasing order, given the the amount to be less than claim value of claim TYPE 'Purchasing Amount' for this user.

As it could be noticed, role based is coarse grained of rigid rights that would simplify the life of the application user from the system management point of view. however it will limits the user abilities from the business requirements point of view. At the other hand claim based is very fine rights that need to be assigned to each user. claim based will push the business too the limit, however will make the system management very complex.


A
Alex Olivier

Another option to consider is ABAC.

Attribute-Based-Access-Control takes a different approach by granting access to users based on each one’s attributes, the resources they’re requesting, and the environment they’re making the request from.

The main benefit of ABAC is that you have granular control over each user’s privileges. For example, using ABAC, you can give users of a human resources application the right to export personnel reports for only the regions they are responsible for. Because the model is designed to scale up to any number of attributes and permissions, it’s generally easier to build more dynamic permissions in ABAC.

Good article here summarising the differences https://cerbos.dev/blog/the-hidden-costs-of-user-authorization