An access control system maps authenticated users to the actions they are required to perform. In this way, you can separate users into groups within your application and empower only certain individuals to perform certain actions. Adding files, downloading raw data, executing SQL statements, sending transactional email, changing system settings – each of these operations can be locked down such that the application permits only a subset of users to execute them. At the same time, unprivileged users can still authenticate and use your application, but sensitive operations are protected from abuse.
There are multiple forms of access control, and each is suited for a different environment and type of use.
With role-based access control (RBAC), users are each assigned one or more roles within a system. Sensitive operations are then restricted based on whether or not a user is in a certain role.
RBAC separates the concepts of Users, Roles and Permissions. Roles are defined in a system, then Permissions defined separately. Then the security administrator decides what role should be permitted to do what action, by assigning that role to the permission. Finally users are assigned to roles. The system does the rest.
As a trivial example, triggering a system update might require users to be in the
ADMINISTRATOR roles. Users might be granted other roles within the system, but the update operation will always check for the presence of at least one of these required roles.
Role-based systems can be very powerful, can scale to manage users and permissions for large applications, and are relative easy to administer. In addition to ready-built tools like PHP-RBAC, the Symfony project published a Security module that supports role-based access control with minimal configuration. The point of both projects is to empower strong security for PHP developers without requiring engineering teams to reinvent the wheel.
A slightly different system uses custom attributes of users, objects, and even the environment to manage access control. Users can (and likely will) still possess one or more roles within the system, but these roles are augmented by other user properties and the nature of the systems with which they interact to determine relative levels of access.
As a trivial example, a user in the
EDITOR will be allowed to edit a publication of a news website, only if the status of the publication is
draft. Once the publication is pushed to production (and its status toggles from
published), the user will be blocked from making changes.
Attribute-based control is far more granular than role-based control, and allows for finer control over the operations in your system. Open source projects like php-abac help to abstract away the detailed implementation while still leveraging the smooth configuration elements provided by libraries like Symfony.
The final access control system we’ll discuss is one that factors in risk. Risk of the operation being performed. Risk of the way the user authenticated. Risk in general. It’s based on an attribute-based system above, but rather than merely taking attributes into account, rates certain attributes based on the riskiness inherent to them.
Consider the operation being executed: is the user attempting to view their profile, or is the user attempting to drop a database table. One operation is riskier than the other – we’d want to ensure additional checks are performed before carrying on a
drop table operation. Since this is a risky operation, we might only want to allow it if the user is browsing from a certain IP address (i.e. the company’s office) or only if they authenticated via LDAP to the system (vs leveraging OpenID via a social media account).
Each of these additional rules combine with specific attributes of the user, the environment, and the operation being performed (or object being acted upon) to determine whether or not we proceed. While not written in PHP, the Golang project ladon presents an efficient means of enumerating these rules, very similar to the way AWS’ Identity and Access Management system works.
One of the other, more interesting ways systems can prevent abuse and invalid access is through a set of rules. These rules can gauge which users are allowed to perform an action (similar to a role-based or attribute-based system). But they can also integrate other logic in evaluating whether or not to permit access.
Is this an application that should only ever be accessed from a trusted corporate network? Filter based on the requester’s IP address regardless of their identity.
Is this an application that should only be used during work hours? Block access to users on evenings and weekends regardless of their identity.