Access control is a foundational part of Drupal’s core architecture. Every request that reaches Drupal is evaluated to determine who can see what, who can do what, and under which conditions. This evaluation happens before content is rendered and, in many cases, before controllers are executed.
Starting with Drupal 8, access control was formalized into a unified, object oriented system that integrates permissions, roles, routes, entities, and caching. This system is critical for security, correctness, and performance.
The focus here is architectural understanding, not just permission syntax.
Why Access Control Belongs in Core Architecture
Access control is not a UI concern. It is a core system that protects data and behavior across the entire application.
Drupal’s access system is responsible for:
- Protecting routes and controllers
- Securing entity operations
- Controlling field level visibility
- Enforcing role and permission rules
- Integrating with cache contexts
Incorrect access handling can lead to data leaks or broken caching.
Core Access Concepts
Drupal access control is built on a few key concepts:
- Accounts represent users
- Permissions define allowed actions
- Roles group permissions
- Access results express allow, deny, or neutral decisions
All access decisions eventually resolve to an AccessResult object.
AccessResult
AccessResult is the core value object used throughout Drupal.
It can represent:
- Allowed
- Forbidden
- Neutral
AccessResult also carries cacheability metadata.
Example:
use Drupal\Core\Access\AccessResult;
return AccessResult::allowed();
Returning simple booleans is discouraged in modern Drupal.
Route Access Control
Routes define access requirements declaratively.
Common route requirements:
- _permission
- _role
- _custom_access
Example:
requirements:
_permission: 'administer site configuration'
Access checks defined in routing are executed before the controller runs.
Custom Route Access Checks
Custom access logic can be implemented using access check services.
requirements:
_custom_access: '\\Drupal\\my_module\\Access\\ExampleAccess::access'
Access methods must return an AccessResult.
Entity Access Control
Entity access is handled by the Entity Access API.
Common operations:
- view
- update
- delete
- create
Example:
$node->access('view', $account);
Entity access integrates with permissions, ownership, and bundles.
Field Level Access
Fields can define their own access rules.
Field access is evaluated when:
- Viewing entities
- Editing entities
- Rendering fields
This allows sensitive fields to be hidden even when the entity is accessible.
Access Control Handlers
Each entity type has an access control handler.
Handlers:
- Centralize entity access logic
- Return AccessResult objects
- Attach cache metadata
Custom entity types often require custom access handlers.
Access and Caching
Access decisions affect caching.
Important cache contexts:
- user.permissions
- user.roles
- user
Failing to attach proper cache contexts can expose protected content.
Drupal automatically propagates cacheability from AccessResult when used correctly.
Access in Controllers
Controllers should not perform access checks directly.
Correct pattern:
- Access enforced by routing
- Access enforced by entity access API
- Controller assumes access is granted
Manual checks inside controllers are error prone.
Access in Forms
Forms use access checks to:
- Control form visibility
- Control submit buttons
- Control operations
Form access often relies on entity access checks.
Access vs Authentication
Authentication answers:
- Who is the user
Access control answers:
- What the user can do
These systems are related but separate.
Common Mistakes
- Returning booleans instead of AccessResult
- Performing access checks in controllers
- Ignoring cache contexts
- Hard coding role checks
- Duplicating access logic
Access logic should be centralized and reusable.
Drupal 10 and 11 Best Practices
- Always return AccessResult
- Attach cacheability metadata
- Use routing requirements
- Use entity access API
- Keep access logic centralized
How Access Control Fits with Other Core Systems
Access control integrates tightly with:
- Routing system
- Controllers
- Entity API
- Cache API
- User system
Access decisions influence nearly every layer of Drupal.
Acquia Exam Notes and Cheat Sheet
Key points to remember:
- AccessResult is central
- Routes enforce access before controllers
- Entity access uses access handlers
- Cache contexts are critical
- Permissions are strings, not logic
Common exam traps:
- Using if ($account->hasPermission()) everywhere
- Forgetting cache contexts on access checks
- Mixing authentication with authorization
- Performing access checks in controllers
Quick decision guide:
- Route access: routing.yml
- Entity access: entity access API
- Field access: field definitions
- Custom logic: access check service
If the question mentions security plus caching, AccessResult is the answer.
Summary
Access control is a core architectural system that protects Drupal applications at every layer. It combines permissions, roles, routing, entities, and caching into a unified decision framework. Mastering access control is essential for building secure Drupal 10 and 11 systems and is a frequent focus of Acquia certification exams.
This article prepares you for advanced topics such as custom access handlers, dynamic permissions, and access caching strategies.