Rapid Application Development toolkit for building Administrative Web Applications

A Role-Based Access Control (RBAC) system for PHP

By Tony Marston

13th May 2004
Amended 1st May 2014

As of 10th April 2006 the software discussed in this article can be downloaded from www.radicore.org

Introduction
What is 'access control'?
What is 'role based'?
- Level based
- User based
- Group based
- Responsibility based
What is a 'menu system'?
My current design
Conclusion
Other types of Access Control
References
Amendment History

Introduction

An 'access control' system is just another name for a 'security system' or a 'permissions' system, and in my long career I have been involved in the design and development of several of these systems:

This article will document the features of some of the early systems I worked on and explain the features of my current design.

What is 'access control'?

In a single-user application which is typically found on a desktop computer there is no need for any access control - the user has access to every function within the application. However, in a multi-user application which is deployed over numerous devices which are linked together in a network it is more than likely that not all functionality will be available to all users. In this situation a method is required whereby functions within the application can only be accessed by persons to whom permission has been granted. This will typically require the maintenance of the following details:

Each of these lists is normally maintained as a table within a database.

What is 'role based'?

There is more than one way to give different permissions to different users, but each method has its own set of advantages and disadvantages. Here are some that I have encountered:

Level based

This is a simple system as it only requires two database tables - USERS and TASKS - without any relationship between them, as shown in Figure 1:

Figure 1 - a level-based permission system

rbac-01 (1K)

In this system each TASK is given a security level number in the range 1 to 99, with 1 being the lowest level and 99 the highest. Each USER is then given a security level number and is allowed to access only those TASKs which have a security level which is the same or lower. Thus a USER with a security level of 5 can access a TASK which has a security level in the range 1-5.

The problem with this system is that it is totally cumulative - by raising the level number you can add more tasks, and you can only remove tasks by reducing the level number. Groups of tasks that share the same level number are either included or excluded as a group, there is no possibility to mix'n'match. For example, take a simple setup with two users, 'Ua' and 'Ub', and two tasks, 'Ta' and 'Tb'. Now try to give user 'Ua' access to task 'Ta' but not task 'Tb', and user 'Ub' access to task 'Tb' but not task 'Ta'. You will find that it cannot be done:

User based

In this system permissions are defined for individual users. This involves a many-to-many relationship between USERS and TASKS with PERMISSIONS being the link or intersection table, as shown in Figure 2.

Figure 2 - a user-based permission system

rbac-02 (1K)

I have seen several different implementations of this design:

My personal preference is for a system to be comprised of small and simple tasks. This may increase the number of tasks, but each one is simple, easer to design, easier to specify, easier to develop and easier to use.

This disadvantage of this design is that where several users share the same permissions any change to those permissions needs to be repeated for each user.

Group based

In this design the users are split into groups and permissions are assigned to the group, not the individual user, as shown in Figure 3.

Figure 3 - a group-based permission system

rbac-03 (2K)

This design has the following advantages:

In this design the USER-GROUP table is sometimes known as SECURITY-CLASS or ROLE.

Responsibility based

In this design it is possible for a user to belong to more than one group at the same time. This involves two many-to-many relationships, as shown in Figure 4.

Figure 4 - a responsibility-based permission system (simple)

rbac-04 (2K)

The USER-GROUP table is sometimes referred to as AREA-OF-RESPONSIBILITY because an individual user may have responsibilities in more than one area.

This design has the following disadvantages:

A more complex version of this design is shown in Figure 5.

Figure 5 - a responsibility-based permission system (complex)

rbac-05 (4K)

In this design there are now five many-to-many relationships which enables a far wider range of customisation. In the implementation I saw the tasks were complex (a single task could operate in Create, Read, Update and Delete mode) which meant that each of the link/intersection tables was a CRUD matrix and could either turn a set of options ON (as an "include" list) or OFF (as an "exclude" list). These tables were read in a strict sequence and the task permissions on one table could be updated by the task permissions on another table. It was therefore possible for a record with a permission checked ON to be superseded by a record from another table with that permission checked OFF.

Even though in theory the above design appeared to be much more flexible, in practice this created a problem with usability. As permissions can exist on five tables, and the permission granted on one table can be taken away by the contents of another table it becomes a more difficult process to track down which user has access to which task.

What is a 'menu system'?

Within an application that may contain dozens or even hundreds of functions a method is required whereby the user can quickly activate the function that will allow him to perform the desired task. In some of the first systems I worked on in the 1970s this 'list' was actually nothing more than a written list, and each part of the system had to be activated manually from the command line. A later innovation was to have this list presented on the computer screen with a mechanism so that simply selecting an item would cause it to be activated. With large systems it was cumbersome to have this list presented in a single unit, so it was split into smaller units or pages. These pages were arranged in a hierarchical structure, and links on one page could activate other pages at a lower level. This was the birth of the menu system.

In the first systems I worked on the menu pages were always hard-coded in a fixed and rigid structure. This method had the following disadvantages:

In the mid-1980s I was asked to design a menu system which did not include these disadvantages, so I came up with the following:

As you can see a security system and a menu system share a lot of common data, so it makes sense (to me at least) to combine them into a single system.

My current design

My current design has evolved over 20 years and has been written in three different languages. It has been used as the basis for many different systems for many different clients and has proved to be effective and robust. As it is driven by the contents of the database then changes can be made easily and quickly. Due to the modular design any changes in functionality can be made easily either by changing an existing module or by adding in a new module.

I originally chose to implement group based security around the USER<==ROLE==>ROLE TASK<==TASK tables as this gave sufficient flexibility with a simple set of options:

In 2014 I decided to upgrade this to implement responsibility based security around the USER==>USER ROLE<==ROLE==>ROLE TASK<==TASK tables as this provides the ability to link a User to more than one Role with only a slight increase in complexity:

Figure 6 - my current design

rbac-06 (5K)

Here is an explanation of the other tables in my database:

Conclusion

Some people may say that having to maintain such a complex database is overkill for such a 'simple' requirement, but in my long experience the customer is always dreaming up 'little additions' to his requirements that cannot be satisfied with a primitive design. How easy would it be for you to change your current system to incorporate the following 'little requirements':

I have also found over the years that by having such a database I can easily extend it to incorporate new requirements or features. For example, because of the TASK table I am able to include extra pieces of information which can be used by the task at run-time and which can be changed without going near any source code, such as the initial sort order for LIST screens.

All the maintenance screens for the PHP+MySQL version of my Menu and Security system are documented in User Guide to the Menu and Security (RBAC) System.

Other types of Access Control

The system described in this document grants or denies permission to use particular tasks within an application, and if a user is granted access to a particular task then he has automatic access to all the data which can be handled by that task. For example, permission to use the "Update Customer Details" task means that the user can update the details of any customer.

Some users may require a level of permissions which goes beyond the individual task and is applied at the data level, such as the following:

References


Amendment History

01 May 2014 Amended My Current Design to allow each User to belong to more than one Role.
09 Mar 2008 Added Other types of Access Control.

counter