Problem/Motivation
When creating a route that makes use of the nojs functionality of Drupal Ajax (the one that replaces "nojs" with "ajax" in your link when the link has the "use-ajax" class) in combination with the "_csrf_token" requirement on your route, the CSRF validation breaks on ajax requests as the path doesn't match the original rendered path anymore for which the token was generated.
For example:
My original link is:
/flag/flag/bookmark/1/nojs?destination=node/1&token=BKjZye8PPzpXvn_VlslxaXv_XdT1KoD5e-mGeaRmMlk
Drupal changes this path into:
/flag/flag/bookmark/1/ajax?destination=node/1&token=BKjZye8PPzpXvn_VlslxaXv_XdT1KoD5e-mGeaRmMlk
The new URL makes us able to return a proper response if the user has JS disabled (or just opened the link in a new tab).
However, "_csrf_token" bases it's token on the generated path, including all parameters, so when requested Ajax URL get's validated with \Drupal\Core\Access\CsrfAccessCheck, it denies access.
Proposed resolution
How I'm seeing it there are 2 possible solutions:
- We use a predefined parameter for such URLs, maybe {js}? Example: "/flag/flag/{flag}/{entity_id}/{js}". That parameter is replaced inside \Drupal\Core\Access\CsrfAccessCheck and \Drupal\Core\Access\RouteProcessorCsrf to always contain the same value, so that CSRF thinks our path always is /flag/flag/{flag}/{entity_id}/js
- We move the nojs/ajax from the path to the query string.