Drupal Roles and Permissions — Granular RBAC System | OpsBlu Docs

Drupal Roles and Permissions — Granular RBAC System

Drupal's role-based access control with granular permissions, custom roles, and per-module permission assignments for secure content workflows.

Overview

Drupal's role-based access control (RBAC) system provides granular permission management through roles. This guide covers creating custom roles, assigning permissions, and implementing best practices for user access control.


Understanding Drupal's Permission System

How Permissions Work

Permission Hierarchy:

User → Assigned Roles → Inherited Permissions

Key Principles:

  • Permissions are additive (users get all permissions from all their roles)
  • Permissions are module-specific (each module defines its own permissions)
  • Deny never overrides allow (if any role grants permission, user has it)
  • User 1 (UID 1) bypasses all permission checks

Permission Types

1. Content Permissions:

  • View published/unpublished content
  • Create content types
  • Edit own/any content
  • Delete own/any content
  • Revert revisions

2. Administration Permissions:

  • Administer site configuration
  • Administer users
  • Administer permissions
  • Administer modules
  • Administer themes

3. Module-Specific Permissions:

  • Administer blocks
  • Administer views
  • Administer taxonomy
  • Administer commerce products
  • Administer webforms

Managing Roles

Accessing Role Management

Navigate to: Admin → People → Roles (/admin/people/roles)

Required permission: Administer permissions

Default Roles

1. Anonymous User

  • Non-authenticated visitors
  • Default permissions: View published content
  • Cannot be deleted

2. Authenticated User

  • Any logged-in user
  • Base permissions for all authenticated users
  • Cannot be deleted

3. Administrator

  • Full site access
  • Created during installation
  • Can be deleted (but not recommended)

Creating Custom Roles

Via UI:

  1. Navigate to /admin/people/roles
  2. Click Add role
  3. Enter role name (e.g., "Content Editor")
  4. Optionally set role weight (affects display order)
  5. Click Save

Via Drush:

# Create role
drush role:create content_editor "Content Editor"

# Create role with specific machine name
drush role:create marketing_manager "Marketing Manager"

# List all roles
drush role:list

Programmatically:

<?php

use Drupal\user\Entity\Role;

// Create role
$role = Role::create([
  'id' => 'content_editor',
  'label' => 'Content Editor',
  'weight' => 3,
]);
$role->save();

Role Naming Best Practices

Good Names:

  • Content Editor
  • Site Manager
  • Marketing Manager
  • Support Staff
  • Product Manager

Avoid:

  • ✗ Editor (too vague)
  • ✗ User (confusing)
  • ✗ Admin2 (unclear purpose)

Assigning Permissions

Permission Configuration

Navigate to: Admin → People → Permissions (/admin/people/permissions)

Interface Overview:

  • Rows: Individual permissions
  • Columns: Roles
  • Checkboxes: Grant permission to role

Common Permission Patterns

Content Creator Role

Minimal permissions for creating content:

Content:
☑ Article: Create new content
☑ Article: Edit own content
☑ Article: Delete own content
☑ View published content
☑ View own unpublished content

Media:
☑ Create media

Toolbar:
☑ Use the toolbar

Content Editor Role

Full content management without admin access:

Content:
☑ Article: Create new content
☑ Article: Edit any content
☑ Article: Delete any content
☑ Article: Revert revisions
☑ Page: Create new content
☑ Page: Edit any content
☑ View published content
☑ View unpublished content

Media:
☑ Create media
☑ Edit media
☑ Delete media

Taxonomy:
☑ Create terms in [vocabulary]
☑ Edit terms in [vocabulary]

System:
☑ Use the administration pages and help
☑ View the administration theme

Site Manager Role

Administrative permissions without development access:

All Content Editor permissions, plus:

Blocks:
☑ Administer blocks

Menus:
☑ Administer menus and menu items

Users:
☑ Administer users (with caution)
☑ Assign roles (with caution)

Views:
☑ Administer views

Webforms:
☑ Administer webforms

System:
☑ Administer site configuration (with caution)

Developer Role

Technical permissions:

All Site Manager permissions, plus:

Modules:
☑ Administer modules

Themes:
☑ Administer themes

Configuration:
☑ Synchronize configuration
☑ Export configuration
☑ Import configuration

Views:
☑ Administer views
☑ Use PHP in views (security risk - use carefully)

Development:
☑ Access developer information
☑ Access Devel information

Files:
☑ Administer file settings

Managing Permissions via Code

Export Permissions Configuration

# Export all configuration
drush config:export -y

# Check user role configuration
cat config/sync/user.role.content_editor.yml

Example: user.role.content_editor.yml

langcode: en
status: true
dependencies: {  }
id: content_editor
label: 'Content Editor'
weight: 3
is_admin: false
permissions:
  - 'access content'
  - 'create article content'
  - 'edit own article content'
  - 'delete own article content'
  - 'create page content'
  - 'edit any page content'
  - 'access toolbar'
  - 'access user profiles'

Assign Permissions Programmatically

<?php

use Drupal\user\Entity\Role;

// Load role
$role = Role::load('content_editor');

// Grant permissions
$role->grantPermission('create article content');
$role->grantPermission('edit own article content');
$role->save();

// Revoke permissions
$role->revokePermission('delete any article content');
$role->save();

// Check if role has permission
if ($role->hasPermission('edit own article content')) {
  // Role has permission
}

// Get all permissions for role
$permissions = $role->getPermissions();

Bulk Permission Assignment

<?php

use Drupal\user\Entity\Role;

$role = Role::load('content_editor');

$permissions = [
  'access content',
  'create article content',
  'edit own article content',
  'delete own article content',
  'access toolbar',
  'use text format basic_html',
];

foreach ($permissions as $permission) {
  $role->grantPermission($permission);
}

$role->save();

Assigning Roles to Users

Via User Interface

Method 1: Edit individual user

  1. Navigate to /admin/people
  2. Click Edit next to user
  3. Check desired roles under Roles section
  4. Click Save

Method 2: Bulk operations

  1. Navigate to /admin/people
  2. Select multiple users (checkboxes)
  3. Choose action: Add the [role] role to selected users
  4. Click Apply to selected items

Via Drush

# Add role to user
drush user:role:add "content_editor" johndoe

# Remove role from user
drush user:role:remove "content_editor" johndoe

# Add role to multiple users
drush user:role:add "editor" johndoe,janedoe,bobsmith

Programmatically

<?php

use Drupal\user\Entity\User;

// Load user
$user = User::load(123);

// Add role
$user->addRole('content_editor');
$user->save();

// Remove role
$user->removeRole('content_editor');
$user->save();

// Check if user has role
if ($user->hasRole('content_editor')) {
  // User has content editor role
}

// Get all user roles
$roles = $user->getRoles();

// Get roles excluding 'authenticated'
$roles = $user->getRoles(TRUE);

Content Access Control

Content Type Permissions

Each content type has its own permissions:

[Content Type]: Create new content
[Content Type]: Edit own content
[Content Type]: Edit any content
[Content Type]: Delete own content
[Content Type]: Delete any content
[Content Type]: Delete revisions
[Content Type]: Revert revisions
[Content Type]: View revisions

Node Access Modules

For more granular control:

Content Access Module:

composer require drupal/content_access
drush en content_access -y

Features:

  • Per-content type permissions
  • Per-node permissions
  • Role-based node access

Permissions per content type: Navigate to: /admin/structure/types/manage/[type]/access

Group Module:

composer require drupal/group
drush en group -y

Features:

  • Organizational groups
  • Group content ownership
  • Group-specific roles

Field-Level Permissions

Field Permissions Module

composer require drupal/field_permissions
drush en field_permissions -y

Configure per field: Navigate to: /admin/structure/types/manage/[type]/fields/[field]/storage

Permission types:

  • Public (everyone can view/edit)
  • Private (only author and administrators)
  • Custom (define specific roles)

Example use cases:

  • Internal notes field (admin only)
  • Draft comments (author only)
  • Sensitive data (specific roles)

Taxonomy Permissions

Per-Vocabulary Permissions

[Vocabulary]: Create terms
[Vocabulary]: Edit terms
[Vocabulary]: Delete terms

Taxonomy Access Control

composer require drupal/taxonomy_access_fix
drush en taxonomy_access_fix -y

Or for more control:

composer require drupal/tac_lite
drush en tac_lite -y

Testing Permissions

Masquerade as Another User

Install Masquerade module:

composer require drupal/masquerade
drush en masquerade -y

Usage:

  1. Navigate to /admin/people
  2. Click Masquerade as link next to user
  3. Test permissions as that user
  4. Click Stop masquerading to return

Or via Drush:

# Generate one-time login link for user
drush user:login johndoe

Permission Audit

Check user's permissions:

<?php

$current_user = \Drupal::currentUser();

// Check specific permission
if ($current_user->hasPermission('edit any article content')) {
  // User can edit articles
}

// Get all user permissions (expensive operation)
$permissions = $current_user->getPermissions();

List all permissions for role:

# Via Drush (custom command needed)
drush role:list --format=json | jq '.content_editor.permissions'

Security Best Practices

Principle of Least Privilege

Grant only the minimum permissions needed:

Good:

  • Content Creator: Create/edit own articles only
  • Site Editor: Edit content but not users
  • Marketing Manager: Manage content and taxonomy, not configuration

Bad:

  • Giving everyone administrator role
  • Granting "Administer site configuration" broadly
  • Allowing untrusted users to use PHP filter

Dangerous Permissions

Use with extreme caution:

☐ Administer modules (can install malicious code)
☐ Administer permissions (can grant themselves any permission)
☐ Administer users (can create admin accounts)
☐ Synchronize configuration (can import malicious config)
☐ Use PHP for settings (arbitrary code execution)
☐ Bypass content access control (see all content)

Alternative approaches:

  • Create specific administrative roles
  • Use workflow modules instead of admin access
  • Implement approval processes
  • Regular permission audits

Permission Auditing

Regular checks:

# Export current permissions
drush config:export -y

# Review user.role.*.yml files
cat config/sync/user.role.*.yml

# Check for overprivileged roles
grep -r "is_admin: true" config/sync/

Automated monitoring:

<?php

/**
 * Implements hook_cron().
 */
function mymodule_cron() {
  // Check for users with dangerous permissions
  $dangerous_permissions = [
    'administer modules',
    'administer permissions',
    'use PHP for settings',
  ];

  foreach ($dangerous_permissions as $permission) {
    $accounts = \Drupal::entityTypeManager()
      ->getStorage('user')
      ->loadByProperties();

    foreach ($accounts as $account) {
      if ($account->hasPermission($permission)) {
        // Log or alert
        \Drupal::logger('security')->warning('User @user has dangerous permission: @perm', [
          '@user' => $account->getAccountName(),
          '@perm' => $permission,
        ]);
      }
    }
  }
}

Advanced Permission Scenarios

Content Workflow Permissions

Using Workflows module:

composer require drupal/workflows
drush en workflows content_moderation -y

Configure:

  1. Create workflow (Draft → Review → Published)
  2. Assign workflow to content types
  3. Create roles for each stage:
    • Content Creator: Create draft
    • Reviewer: Move draft to review
    • Publisher: Publish reviewed content

Navigate to: /admin/config/workflow/workflows

Time-Based Permissions

Scheduler module:

composer require drupal/scheduler
drush en scheduler -y

Permissions:

☑ Schedule content for publication
☑ Schedule content for unpublication

Organic Groups / Group Permissions

composer require drupal/group
drush en group -y

Features:

  • Create groups (teams, projects, departments)
  • Group-specific content
  • Group-specific roles (group admin, group member)
  • Inherit global roles

Troubleshooting Permissions

User Can't See Content

Check:

  1. User has "View published content" permission
  2. Content is published (status = 1)
  3. User has permission for that content type
  4. No node access modules blocking access

User Can't Edit Content

Check:

  1. User has "Edit own" or "Edit any" permission
  2. User is owner (for "edit own")
  3. Content is not locked by another user
  4. Field-level permissions aren't restricting

Permission Changes Not Taking Effect

Solutions:

# Clear all caches
drush cr

# Rebuild permissions
drush php:eval "node_access_rebuild();"

# Check configuration
drush config:export -y

Migration & Deployment

Exporting Permission Configuration

# Export all configuration
drush config:export -y

# Commit configuration to git
git add config/sync/user.role.*.yml
git commit -m "Update role permissions"
git push

Importing on Production

# Pull latest code
git pull

# Import configuration
drush config:import -y

# Clear cache
drush cr

# Verify
drush role:list

Resources


Next Steps


Quick Reference

Essential Drush Commands

# Role management
drush role:create MACHINE_NAME "Human Name"
drush role:list

# Assign roles
drush user:role:add "ROLE" USERNAME
drush user:role:remove "ROLE" USERNAME

# Permission operations
drush config:get user.role.ROLE permissions
drush config:set user.role.ROLE permissions.X "permission name"

# Export/Import
drush config:export -y
drush config:import -y

Common Permission Sets

View-only access:

☑ Access content
☑ Use the toolbar

Basic content creator:

☑ Access content
☑ Create article content
☑ Edit own article content
☑ Use text format basic_html
☑ Use the toolbar

Full content editor:

☑ Access content
☑ Create/Edit/Delete any article/page content
☑ Administer taxonomy
☑ Create/Edit media
☑ Use text format full_html
☑ Use the administration pages