Routing Access Check Headers
This module allows you to restrict access to specific routes on your Drupal site based on the presence of certain HTTP headers. It's useful for creating private APIs or sections of your site that should only be accessible via specific applications or services.
Provides a Drupal route access check that validates incoming HTTP requests against configurable header profiles:
requirements:
_routing_access_check_headers: 'xhr' # or 'iframe' or 'your_custom_header_check'
This is a developer module! - No UI, does nothing on its own. Typically useful if you have public (internal) API routes or embeds like iframes that should be protected against external calls, like widget_provider_api module or go-headless modules.
Overview
This module adds the _routing_access_check_headers route requirement. When a route uses this requirement, the access handler loads a routing access check headers profile plugin and calls checkAccess() on it.
The routing_access_check_headers module allows you to validate HTTP headers (like Origin or Referer) for internal API routes (e.g., XHR, JSON, or headless endpoints, e.g., from your frontend or iframe) that should never be accessed from external sources. Especially in cases where these endpoints need to be public and can't be secured by authentication. By enforcing header checks, you add a layer of protection against unauthorized cross-origin requests. Custom headers can also be validated for additional control.
While header validation makes it harder for external actors to query the endpoint, by blocking requests without the expected Origin or Referer, it is not a safe security measure on its own. Headers can be spoofed or omitted, so this should be combined with other protections like authentication, CSRF tokens (combination is possible, see below), or rate limiting. The module uses a plugin architecture, providing default plugins for xhr and iframe use cases, but you can also simply implement custom logic for specific needs.
Should you have further ideas how to add further hardening to this module, please create a feature request.
Profiles are defined as plugins and can validate:
- custom request headers
- the
Originheader - the
Refererheader
Installation
Install as you would normally install a contributed Drupal module. For further information, see Installing Drupal Modules.
Route usage
Add the profile plugin ID to a route's requirements:
my_module.api_endpoint:
path: '/api/example'
defaults:
_controller: '\Drupal\my_module\Controller\ExampleController::handle'
methods: [GET]
requirements:
_routing_access_check_headers: 'my_profile_id'
The value (my_profile_id) must match the id of a profile plugin.
Combining with CSRF token
For routes that accept state-changing requests (for example POST), consider adding Drupal's CSRF access check alongside the header profile. See CSRF access checking.
requirements:
_routing_access_check_headers: 'my_profile_id'
_csrf_token: 'TRUE'
Built-in profiles
Profile ID
Description
xhr
Allows programmatic requests (X-Requested-With: '').
iframe
Allows requests loaded inside an iframe (@todo).
Example:
requirements:
_routing_access_check_headers: 'xhr'
Creating a profile plugin
Profile plugins live in the Plugin/RoutingAccessCheckHeadersProfile namespace of any module that depends on routing_access_check_headers.
Example:
'secret-value',
'X-Client-Id' => '',
],
validateOrigins: [
'https://example.com',
],
validateReferer: [
'https://example.com/some-page',
],
)]
class MyProfile extends ProfilePluginBase {}
No additional code is required unless you want to customize the access logic.
Profile attribute options
Option
Type
Description
id
string
Unique plugin ID. Referenced in routing requirements.
customValidationHeaders
array
Required headers keyed by header name. Values are expected header values. Use an empty string to require the header without validating its value.
validateHostOrigin
bool
Whether the server origin is included in Origin header checks. Defaults to FALSE.
validateHostReferer
bool
Whether the server origin is included in Referer header checks. Defaults to FALSE.
validateOrigins
array
Allowed Origin header prefixes.
validateReferer
array
Allowed Referer header prefixes.
An empty customValidationHeaders array skips the custom header check. Origin and referer checks are skipped when no allowed values are configured for that header.
Access check logic
ProfilePluginBase evaluates checks in this order:
checkAccess()checkHeaders()checkCustomHeaders()checkOrigin()checkReferer()
All checks must pass.
Custom headers
- Skipped when no custom headers are configured.
- Every configured header must be present on the request.
- Configured values must match exactly.
Origin
- Skipped when no allowed values are configured (
validateOriginsis empty andvalidateHostOriginis disabled). - When configured, requires the
Originheader. - Allowed values are the configured
validateOriginsand, whenvalidateHostOriginis enabled, the server origin. - The
Originvalue must start with one of the allowed values.
Referer
- Skipped when no allowed values are configured (
validateRefereris empty andvalidateHostRefereris disabled). - When configured, requires the
Refererheader. - Allowed values are the configured
validateRefererand, whenvalidateHostRefereris enabled, the server origin. - The
Referervalue must start with one of the allowed values.
Extending a profile
Extend ProfilePluginBase and override protected methods when you need custom logic:
checkAccess()checkHeaders()checkCustomHeaders()checkOrigin()checkReferer()startsWithAllowedValue()allowsSameOrigin()
Plugin definitions are read via:
getCustomHeaders()getOriginsArray()getReferer()getHostOrigin()
Services
Both services use Symfony autowiring with service closures for lazy dependency resolution.
Service ID Descriptionplugin . manager . routing_access_check_headers_profile
Plugin manager for profile plugins. Uses service closures for cache . discovery and module_handler.
routing_access_check_headers . access_check
Route access check service tagged for _routing_access_check_headers. Uses a service closure for the profile plugin manager.
Alter hook
Profile plugin definitions can be altered with hook_routing_access_check_headers_profile_info_alter().
See routing_access_check_headers . api . php for hook documentation and example implementations.
Depends on
Dependencies of the latest stable release
No dependencies recorded for this project.
Required by
Tracked projects that depend on this one
No tracked projects depend on this one yet.
Activity
Release Timeline
Releases
| Version | Type | Core | Notes | Release date | |
|---|---|---|---|---|---|
| 1.0.0-alpha2 | Pre-release | 11 | Jul 16, 2026 | ||
| 1.0.0-alpha1 | Pre-release | 11 | Jul 16, 2026 | ||
| 1.x-dev | Dev | 11 | Jul 14, 2026 |