Avoid Role-Based Access Control pitfalls

Bala Dutt
6 min readDec 27, 2019

--

Vijayan Srinivasan and Bala Dutt

What is Role-Based Access Control (RBAC) about? It is not about roles. It is about protecting access. Access to what? Resources. Yes, that is the central domain entity when we discuss access control. Roles is one mechanism and tomorrow there would be others. In fact, there are already other approaches like Attribute-Based Access Control, which might be the topic of a future write-up. So, let us forget the access control mechanisms and focus on resources.

Resource centric view

Resource is the object being protected. Below is the picture of some resources.

Resource examples

A resource could be a table, record in a database, folder, email message, a message in a queue, piece of code, API, GraphQL entity or even a UI widget. A resource may manifest in many ways. Also what it means to access would depend on the actual resource. We need an abstraction for access control and for that purpose we need to know that it is a resource with a unique id to identify it. Also, we need to know possible actions on the resources. So, access is basically the ability to perform a specific action on a resource.

So, we have a resource to be protected and possible multiple actions that can be performed on it.

This is not alien to most of us. Remember the web was built on the notion of resources and possible actions on them.

By typing URL in a browser address bar, we type the address or locator of a resource (Uniform Resource Locator) and what we get is a representation of the resource. We may do a read or Get, but not only those but other operations like update, delete, create, etc.

As a developer of products, applications one is only concerned with identifying and marking resources.

Authorization

The problem of access control is also called Authorization. With this resource-centric view, the problem of authorization is broken down into the framing, “A subject S wants to perform an action A on resource R, should it be allowed?” The place where this question is asked and the result enforced is the Enforcement point. This point is capable of intercepting the access and block it if decision is to deny. Enforcement is specific to the resource. For Java code, enforcement will typically be a Java code, for API it could even be a proxy. To complete the picture, the question is answered by an AuthZ system, shown here as the AuthZ server.

NIST RBAC model — year 2000

Now let us come to roles. Roles allow access to a set of resources to perform specific actions. These may be defined at runtime. Users are assigned roles and as an effect of that, they get access to perform actions on resources. So, roles are merely a vehicle to give access to users (subjects). Below diagram shows this. Roles provide permissions that allow operations (actions) on objects (resources).

What we have achieved with this is separation of concerns of,

  • Identifying with marking of resources and actions
  • Intercepting & Enforcement of access
  • Decision of Authorization
  • User Management

Do not use roles in your code

So, one key lesson is that do not use roles in your code. We are misled by easy APIs in standard libraries. For e.g.

J2EE

HttpServletRequest

Boolean isUserInRole(java.lang.String role)
java.security.Principal getUserPrincipal()

Spring Method Security

@Secured(“ROLE_VIEWER”)

public String getUsername() { …}

.NET

System.Web.Mvc.AuthorizeAttribute

Roles — Gets or sets the user roles that are authorized to access the controller or action method.

Users — Gets or sets the users that are authorized to access the controller or action method.

These APIs hint that we could write code using users or roles in our logic. There are two compelling reasons to not do that,

  • Introducing a new role will need changes to code. It gets very complex and slow as we define more and more roles.
  • At some point, if the ability to define roles is passed to end-users of your application, your code could never know about them beforehand.

Also, note that organizations change. More people are added. Newer roles may have to be defined to limit access to a subset of the same set of resources. Also, one learns with time, role definitions need changes and this is necessary for healthy RBAC. There is usually a governance needed for role assignment (who gets what role) and role definition (what can this role do). And these would identify whether a role should be broadened, narrowed or aligned. There is no magic way to get to the “right” set of roles. There may not even be a “right” fixed set.

Other Best practices

Here are some other best practices that will make your RBAC implementation robust.

  • Principle of least privilege (PoLP), also known as the principle of minimal privilege or the principle of least authority, requires that every entity must be able to access only the resources that are necessary for its legitimate purpose. The principle means giving a user account or process only those privileges which are essential to perform its intended function. Prevent privilege crepe with regular audits and giving just in time privileges.
  • Separation of duty (SoD; also known as Segregation of Duty) is another principle to prevent fraud and errors. The same person should not be given all the permissions, for e.g. initiator should not be authorizer (static SoD) of payment or at least for the same payment the person should not be both initiator and authorizer (dynamic SoD).
    Another way to describe this and also generalize this is the two-man rule. The simplest way to explain is to say that it’s a “Buddy System” for grownups. What does this mean? It’s a procedure in which two people operate together as a single unit so that they are able to monitor and help each other to ensure the work is finished safely or the skill is transferred effectively from one person to another. If you remember from the movie “Crimson Tide” where the Captain of a submarine wants to launch an attack while his deputy wants to wait for confirmation. This kind of mechanism is used for a high level of security for especially critical material or operations (such as nuclear weapons, submarines, laboratories, aircraft, etc.).
  • Permissions are transient. Do not persist them or cache them.
  • The principle of defense-in-depth is that layered security mechanisms increase the security of the system as a whole. So, protect resources at multiple levels — API, method, data, etc..
  • Protect closer to the resource. Do not rely on perimeter-based security. Do not depend on safe networks and have zero trust security model. That means an API call from a server in your datacenter or the internet is to be treated with the same distrust. This moves away from giving more access to some networks to access give only based on users, applications and devices. Read more at Google’s BeyondCorp.
  • Do not enumerate permissions but only assert. This is especially beneficial when we have multiple approaches to access control. This would be the subject of a future article.
  • Keep audit logs and audit. Manage the drift of the system or discover attacks by continuously auditing the system.

Conclusion

The summary is that RBAC is a very simple and yet powerful mechanism for protecting resources. It has stood test of time. Somethings that we can do for a “better” implementation of RBAC are,

Do not use Roles in code

Take a resource-centric view

Separate concerns

Follow best practices

Have a great time using RBAC! Please feel free to leave comments. We will be back with another article soon in the domain of authorization.

--

--