I have looked into this a lot now and I think this is a bug in Core.
When doing something like this:
$build['link'] = [
// …
'#ajax' => [
'url' => Uri::fromRoute('…'),
],
];
With a route that requires a CSRF token, it seems the URL set inside the AJAX settings will contain a wrong token parameter – apparently the internal "lazy build" placeholder instead of the CSRF token by which it should be replaced.
I think this is due to the fact that in \Drupal\Core\Render\HtmlResponseAttachmentsProcessor::renderPlaceholders(), the markup only contains a placeholder for the complete Javascript (including settings), which means that the placeholders inside the settings won't be replaced properly. The replacement (placeholder to token) seems to be generated fine, but then doesn't seem to take effect – the final JS settings sent to the client still have the placeholder instead of the CSRF token.
Comments
Comment #14
smustgrave commentedThank you for reporting this problem. We rely on issue reports like this one to resolve bugs and improve Drupal core.
Since there has been no activity here for over 8 years we are asking if this problem persists on a currently supported version of Drupal. To help, add a comment explaining if the problem still occurs or not. Any extra detail you can provide can help others who experienced this.
Since we need more information to move forward with this issue, the status is now Postponed (maintainer needs more info). If we don't receive additional information to help with the issue, it may be closed after three months.
Thanks!
Comment #15
drunken monkeyYes, this problem still seems to be present. I currently have the following (working) code in the Search API module (in
src/Form/IndexFieldsForm.php), where the given route uses a CSRF token:However, it stops working when changing this to use style given in the issue description:
An AJAX request to the right URL is sent, but with the wrong
tokenvalue.