Custom Access Checking
When to Use
Use when built-in access checks (
_permission,_role,_entity_access) are insufficient. Complex business logic, multi-factor checks, or context-dependent access require custom checkers.
Decision
| Situation | Choose | Why |
|---|---|---|
| AND logic for permissions | Custom access checker | Built-in only supports OR |
| Time-based access | Custom checker checking current time | No built-in time-based access |
| Entity relationship access | Custom checker with entity loading | Check ownership, references, etc. |
| Configuration-based access | Custom checker reading config | Access rules from admin settings |
| Complex multi-factor access | Custom checker with multiple conditions | Full control over access logic |
Pattern
// src/Access/CustomAccessChecker.php
namespace Drupal\my_module\Access;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Routing\Access\AccessInterface;
use Drupal\Core\Session\AccountInterface;
class CustomAccessChecker implements AccessInterface {
public function access(AccountInterface $account) {
// Custom logic here
if ($account->hasPermission('access content')
&& $account->hasPermission('use admin toolbar')) {
return AccessResult::allowed()->cachePerPermissions();
}
return AccessResult::forbidden()->cachePerPermissions();
}
}
# my_module.services.yml
services:
my_module.custom_access_checker:
class: Drupal\my_module\Access\CustomAccessChecker
tags:
- { name: access_check, applies_to: _custom_access_check }
# my_module.routing.yml
my_module.custom_page:
path: '/custom-page'
defaults:
_controller: '\Drupal\my_module\Controller\CustomController::build'
requirements:
_custom_access_check: 'TRUE'
Reference: core/lib/Drupal/Core/Access/AccessInterface.php, core/modules/user/src/Access/
Common Mistakes
- Wrong: Not implementing cache metadata → Right: Add
->cachePerPermissions()or appropriate cache context - Wrong: Using
AccessResult::allowed()without cache contexts → Right: Always specify cache metadata - Wrong: Missing service tag
access_check→ Right: Add tag withapplies_toparameter - Wrong: Not injecting dependencies properly → Right: Use dependency injection, avoid static calls
- Wrong: Overly complex access logic → Right: Consider simplifying or using existing patterns
- Wrong: Forgetting to handle edge cases → Right: Test all access scenarios thoroughly
See Also
- Route Subscribers
- Testing and Debugging
- Reference: Custom route access checking - Drupal.org
- Reference: Advanced route access checking - Drupal.org
- Reference: Custom access check - Axelerant
- Reference: Custom route access checker - Bhimmu