Understanding Policy-Based Access Control
Published August 16th, 2024
In version 11 introduced a change to how Directus handles access control through the introduction of policies.
Previously, permissions were attached directly to roles, and a user could receive those permissions by assigning their role. Now, permissions are attached to reusable policies that can be added to users or roles, as well as other subtle but impactful changes.
Introducing Policies
Each policy can contain one or more permissions, which in turn is made up of a collection, an action, and either allow all or create custom rules. While the creation of permissions remains unchanged, we have also updated the UI so only relevant collections are shown.
As before, custom permissions can include a filter to only allow access to certain items or fields.
Assigning Policies & Roles
Policies can be added directly to roles, meaning you can continue to use the permission as you have done prior to Directus 11 by creating a single policy per role.
However, roles can have multiple policies attached to them, and policies can be attached to multiple roles. This flexibility means that you can create smaller and more modular sets of permissions and reuse them at any time.
You can also add policies directly to users, which can be useful for users in your project who have edge cases, or already have an assigned role.
Multiple Roles
While you can still only assign a single role to a user, roles can now contain other roles. All policies applied to any of the roles will be used when determining access control.
A new $CURRENT_ROLES
dynamic variable is now available throughout Directus and will return an array of all roles at all depths. $CURRENT_ROLE
will contain only the directly-added role as before.
Additive Permissions
By default, a user has no access to any collection. All permissions in all policies are additive and are combined to determine what a user has access to. There are no “negative” permissions that remove access.
Composing Access Control
Having this new level of flexibility in policies helps in two ways - to remove repetitive permission configuration for similar roles, and to create sets of permissions that have a clear purpose when applied together.
An Example
In this store, there is a staff
, shift manager
, and store manager
role. There are inventory
, shifts
, and sales
collections.
A see inventory
policy could contain a single permission allowing read access to the inventory
collection, and be assigned to the staff
role.
An accept inventory
policy could allow full access to all actions in the inventory
collection, and be added to both the shift manager
, and store manager
roles.
A see shifts
policy could be added to the staff role that could allow read
access to shifts
and only allowing read
access to the name field of staff
, while shift managers
could get a more permissive policy allowing for the creation and editing of shifts.
Staff should be able to create
sales
, but only the store manager
should be able to read
, edit
, or delete
sales. Once again, two policies with the varying permission levels.
Finally, the shift manager
role could contain the staff
role, so they get all staff-level policies.
API Changes
These changes also introduce API changes - the ones you might expect are the introduction of a Policies API, and changes to the fields in the Roles and Users APIs. And, of course, permissions are no longer attached to a role
but instead to a policy
.
If there is ever conflicting permissions around which fields or items are available based on a filter, the field will be returned with a value of null
. This means that null
must now be treated as both a value and as an indication of lacking access.
Migrating from Role-Based Access Control
When upgrading to Directus 11, our automatic migrations will handle this upgrade for you by turning each role’s permissions into a single policy and attach the policy to the role on your behalf.
You are then free to take advantage of the new policy-based access control as you are ready to - taking common permissions across roles into their own policies is a fantastic first step.
The way we have implemented the migration is intended to make this a smooth transition, allowing you to take advantage of policies at your own pace. But we hope that you find this addition a powerful change.