Role Based Access Control

Role Based Access Control on parts of objects

As mentionned, Attribute based access control may be the good solution. And XACML could be used in an application with complex policies.

Here is a very understandable documentation about ABAC in Spring Security

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

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.

Role Based Access Control (RBAC) cares about permission or roles?

You are correct - checking for roles in applications instead of permissions is not Role-Based Access Control. Spring security and many other prominent access control mechanisms propagate this security anti-pattern. For correct RBAC usage - perform permission checks in your policy enforcement logic.

Scope/Role/Group Based Access Control

Two most popular one:

  • Role Based Access Control - you are assigning roles to the users or groups in the your application configuration (inside Azure Portal). Then in code you can use those roles authorize users to certain parts of your application. You can do something line that: if (User.IsInRole("SuperAdmin")) {...}
  • Group based access control using the groupMembershipClaims - it's similar but you are checking if user belongs to specific group

Designing a role based access control with support for relations

You shouldn't implement a DB model for access control. Your DB model should have the objects you care about (students, teachers, classes...). The rest should be expressed as policies in an externalized authorization model. This is called Attribute-Based Access Control abac. It's also known as policy-based access control (PBAC). Different names, same thing.

In ABAC, you have attributes on the one hand (the fields of your tables in your DB model e.g. username, role, course year...) and policies on the other. For instance:

  • Teachers can edit the grade of a student in a class they teach
  • Students can view their own grades
  • A student can view the course material of a class they belong to

All these are examples of (business) authorization policies.

In ABAC, you then have the notion of a Policy Decision Point (PDP) which evaluates authorization policies and a Policy Enforcement Point (PEP) which intercepts business requests and sends off authorization requests to the PDP. For instance:

  • Can Alice the student view grade #123?
  • Can Bob the teacher view the profile of student Alice?

The PDP replies with a decision, either Permit or Deny, which the PEP must then enforce. You mention that you have an MVC model for your application. Your PEP would likely be an interceptor or annotation in your controller layer.

ABAC Architecture

There are several ABAC languages and implementations out there:

  • open-source:

    • Open Policy Agent based on the Rego language
    • AuthZForce based on the XACML standard.
  • closed-source: Axiomatics Policy Server based on the XACML and ALFA standards.

Role-based access control with Google authentication

I don't think you can add more information to the ID Token that you get from Google. According to Google's OIDC discovery document, these are the claims that can be present in the ID token:

"claims_supported": [
"aud",
"email",
"email_verified",
"exp",
"family_name",
"given_name",
"iat",
"iss",
"locale",
"name",
"picture",
"sub"
]

Apparently, an organization administrator can limit which claims do end up in the ID token, so you might get a subset of these.

You should be able to get information about the user's group from one of the myriad APIs that Google exposes. Not sure if Cloud Identity is the one you're after, but there is an endpoint that returns information about groups: https://cloud.google.com/identity/docs/reference/rest/v1/groups.memberships/get If that's not the one, I think you could search the scopes page that you linked, and you should find the relevant scope there. The scope will be tied to a concrete API and this will be the API that you have to call to get the user's groups, roles, etc.



Related Topics



Leave a reply



Submit