Skip to main content
drupalreleases

Use direct release data with your AI assistant.

Learn more

External Roles

Security covered Maintenance fixes only

Part of the External ecosystem · 21 projects

This module allows you to grant permissions to users based on roles defined externally, integrating with Drupal's access control system. It is intended for developers who need to manage user access through external systems or custom business logic.

The External Roles module integrates seamlessly with Drupal's core Access Policy API to extend role-based access control. This module allows you to assign permissions to users based on external roles, making it an ideal solution for projects that require integration with external systems or configurations.

Important Note

This module is intended for developers. It provides flexible interfaces for customization and extension through code, allowing you to define external roles and easily manage them within your business logic.

How to use?

Minimal setup

Installation

Start by installing the module via Composer and enable the module.

External roles definition

Add the following definition to the settings.php file. The array structure for this configuration is defined as follows.

$settings['external_roles'] = [
  '{role}' => [
    'name' => '...',
    'permissions' => [
      '...',
      '...',
      '...',
    ],
  ],
  '{role}' => ...,
  '{role}' => ...,
];

Assign external roles in business logic

Use the ExternalRolesUser wrapper to assign external roles to users in your business logic. The easiest way to do this is probably through hook_user_presave(). For example:

function my_module_user_presave(UserInterface $user): void {
  $wrapped_user = new ExternalRolesUser($user);
  $wrapped_user->addExternalRole('alpha');
  $wrapped_user->addExternalRole('beta');
}

Rebuild cache

The cache requires a rebuild whenever the definition of the external roles is changed.

Advanced setup

External roles repository

The first point of extension is the external roles repository. It implements the simple ExternalRolesRepositoryInterface and can be easily replaced by a more advanced repository. Let's discuss an example where the external roles are defined in a file.

namespace Drupal\my_module;

use Drupal\Component\Serialization\Yaml;
use Drupal\Core\Extension\ModuleExtensionList;

class ExternalRolesRepository implements ExternalRolesRepositoryInterface {

  protected const ROLES_FILE_NAME = 'my_module.roles.yml';
  
  protected array $definition;

  public function __construct(protected ModuleExtensionList $extensions) {}

  public function getPermissionsByRole(string $role): array {
    return $this->loadDefinition()[$role]['permissions'] ?? [];
  }

  protected function loadDefinition(): array {
    if (!isset($this->definition)) {
      $file_contents = file_get_contents($this->extensions
        ->getPath('my_module') . '/'. static::ROLES_FILE_NAME) ?: '';
      $this->definition = Yaml::decode($file_contents) ?? [];
    }
    return $this->definition;
  }
  
}

The external roles file my_module.roles.yml could look like this.

alpha:
  name: 'Alpha'
  permissions: [
    'access foo',
  ]
beta:
  name: 'Beta'
  permissions: [
    'access foo',
    'access bar',
  ]

Then, overwrite the external roles repository in your custom module service definition.

external_roles.repository:
  class: Drupal\my_module\ExternalRolesRepository
  arguments: [ '@extension.list.module']

OpenID Connect

If you are using OpenID Connect, the user info hook is a good point for assigning external roles.

function my_module_openid_connect_userinfo_save(UserInterface $account, array $context) {
  // Get roles from the identity provider.
  $roles = ...;
  $wrapped_user = new ExternalRolesUser($account);
  foreach ($roles as $role) {
    // Optionally add some validation here.
    if (!my_module_validate_role($role)) {
      continue;
    }
    $wrapped_user->addExternalRole($role);
  }
}

Further developer notes

  • The Access Policy API heavily relies on caching to calculate the permissions efficiently. The relevant cache context is user.external_roles, which is defined in ExternalRolesCacheContext. For security reasons, a cache rebuild is required when the definition of external roles changes.
  • The ExternalRolesUser wrapper can easily manage the external roles.
  • The external roles are saved in a user base field. The database table is user__external_roles.
  • Please also consult the documentation for the Access Policy API.
Drupal 10–11

Ask your assistant about External Roles

Check compatibility with your Drupal and PHP version, maintenance and security coverage, from current release data. How it works

Depends on

Dependencies of the latest stable release

  • user Drupal core

Required by

Tracked projects that depend on this one

No tracked projects depend on this one yet.

Activity

Tracked releases
3
Tracked since
Aug 2024
Latest release
1 year ago
Releases (12 mo)
0 ▼ from 1
Maintenance
Dormant

Release Timeline

Releases

Version Type Core PHP Release date
1.0.1 Stable 10–11 Dec 19, 2024
1.0.0 Stable 10–11 Aug 30, 2024
1.0.x-dev Dev 10–11 Aug 20, 2024