Drupal comes equipped with various tools for handling CSRF protection.
—(OWASP)
One such tool is for handling the addition of a CSRF token to a route built using the Drupal API automatically. Let's take a look at an example.
Imagine that you have a route that is used as some sort of a callback. Hitting this route triggers a process (for logged-in users), so you need to make sure that users only end up on this route from the place they should come (part of the flow that needs to trigger that process). Tokens can be used for this, and Drupal 8 has this covered.
There are two things we need to do: add a requirement to the route for CSRF protection and then build that link using the regular Drupal API we saw in Chapter 2, Creating Your First Module. Here's the requirement:
_csrf_token: 'TRUE'
Also, note that this can go together with other access-based requirements such as the ones we've been talking about in this section.
Adding the CSRF token requirement now makes the route inaccessible if simply accessed by navigating to the path in the browser. To make it accessible, we will need to print a link to it somewhere using the Drupal API:
$url = Url::fromRoute('my_module.my_route'); $link = [ '#type' => 'link', '#url' => $url, '#title' => 'Protected callback' ];
This is one way, but we can also use the LinkGenerator service or the Link class, as we've seen in Chapter 2, Creating Your First Module. They will all render the link with a token appended to the URL as a query parameter. Drupal will then evaluate that token as part of the access control and make sure that it is valid. As a matter of fact, the link building actually plays no role. It is the URL generator that handles it. So, if you get the string URL this way, you will have the token on it automatically:
$path = $url->toString();
Under the hood, to manage the creation and validation of the tokens, Drupal uses the CsrfTokenGenerator service, which we can also use if we need to. For example, after getting our hands on the service (csrf_token), we can create a token:
$token = $generator->get('my_value');
Here, my_value is an optional string that the generator can use to make the token unique. It also uses the current user session and the private site key. Keep in mind that if the user is anonymous and no session has been started, the token will be unique on each request.
We can then validate this token as follows:
$valid = $generator->validate($token, 'my_value');
Here, $generator is the same service we used for creating it.
Using the token generator manually can be handy, but as we saw, it is very easy to just put a requirement on the route, and let Drupal do the rest. Moreover, CSRF protection is embedded in the Form API, so we don't have to do anything at all when it comes to forms for additional protection.