CSRF access checking

Last updated on
20 February 2024

This documentation needs review. See "Help improve this page" in the sidebar.

CSRF (Cross-Site Request Forgery) protection is now integrated into the routing access system and should be used for any URLs that perform actions or operations that do not use a form callback. In previous versions of Drupal, it was necessary to add a generated token as a query parameter to a URL and check this token manually in either the callback or the access callback. Now you can simply use the '_csrf_token' requirement on a route definition. Doing so will automatically add a token to the query string, and this token will be checked for you.

# example.routing.yml

example:
  path: '/example'
  defaults:
    _controller: '\Drupal\example\Controller\ExampleController::content'
  requirements:
    _csrf_token: 'TRUE'

To generate the URL for the _csrf_token: 'TRUE', use the code snippet below. The CSRF token will be added and validated implicitly.

$url = Url::fromRoute(
  'node_test.report',
  ['node' => $entity->id()],
);

Explicitly add and validate tokens:

Note that, in order for the token to be added, the link must be generated using the url_generator service via route name rather than as a manually constructed path.

$url = Url::fromRoute(
  'node_test.report',
  ['node' => $entity->id()],
  ['query' => [
    'token' => \Drupal::getContainer()->get('csrf_token')->get("node/{$entity->id()}/report")
  ]]);

API reference [9.0]: CsrfTokenGenerator::get

To validate token manually (e.g. without adding _csrf_token: 'TRUE' to [module].routing.yml file) at the route destination use token and value used for generating it. 

// Validate $token from GET parameter.
\Drupal::getContainer()->get('csrf_token')->validate($token, "node/{$entity->id()}/report");

Anonymous Users

Currently the _csrf_token check fails for users without an active session, which includes most anonymous users. See: #2730351: CSRF check always fails for users without a session

Tags

Help improve this page

Page status: Needs review

You can: