Menu APIs provide invalid CSRF tokens

Created on 2 November 2024, 21 days ago

Problem

Both, the core menu linkset, and the REST menu items module face the same issue: Since Drupal 10.3/11 the user logout link contains a CSRF token. However, the token provided by the API is invalid.

Note that this worked fine for Drupal 10.2 and before, so this is a regression that causes decoupled solutions that fetch the "account" menu to break.

Related issue for REST menu items module: πŸ› Wrong user logout CSRF token Active

Steps to reproduce

* Access the "account" menu
* Try using the logout link, when the token is valid, it should work without confirmation form.
* The token is not valid, a confirmation form is shown

The token does not work, because it's not the token. The value for the token is the render-placeholder, but the placeholder never gets replaced. API modules rendering to JSON to not use the render system, thus never get placeholders replaced. Still, RouteProcessorCsrf() placeholders the value.

Analysis

The problematic logic is in `\Drupal\Core\Access\RouteProcessorCsrf::processOutbound`.

      // Adding this to the parameters means it will get merged into the query
      // string when the route is compiled.
      if (!$bubbleable_metadata) {
        $parameters['token'] = $this->csrfToken->get($path);
      }
      else {
        // Generate a placeholder and a render array to replace it.
        $placeholder = Crypt::hashBase64($path);
        $placeholder_render_array = [
          '#lazy_builder' => ['route_processor_csrf:renderPlaceholderCsrfToken', [$path]],
        ];
 ....

However, the assumption "we have cachemetadata, thus we can use placeholders" is wrong. JSON API response should use cache metadata, but cannot use render API placeholders. Not sure what else would be a good indicator on when to placeholder it, but the current one isn't it.

To reproduce, a simple generated URL like

> \Drupal\Core\Url::fromUri('internal:/user/logout')->toString();

will generate an invalid token. (note that you need to use the right session also!)

Remaining tasks

Figure out when it's safe to placeholder the token and change the logic. Maybe we check for an active render context instead?

πŸ› Bug report
Status

Active

Version

10.3 ✨

Component

system.module

Created by

πŸ‡¦πŸ‡ΉAustria fago Vienna

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @fago
  • πŸ‡¦πŸ‡ΉAustria fago Vienna

    It's probably safe to assume that every non-html request is not going to use the render sytem and thus a placeholder should not be created. Not perfect, but a better check than it was before.

    This works for rest_menu_items and for core-linkset endpoint once it's correctly specified as json. Patch attached. Will work on a test also.

  • Pipeline finished with Failed
    20 days ago
    Total: 206s
    #328007
  • Pipeline finished with Failed
    20 days ago
    Total: 641s
    #328291
  • πŸ‡¦πŸ‡ΉAustria fago Vienna
  • Pipeline finished with Failed
    19 days ago
    Total: 482s
    #328587
  • Pipeline finished with Canceled
    19 days ago
    Total: 1232s
    #328608
  • Pipeline finished with Failed
    19 days ago
    Total: 651s
    #328628
  • Pipeline finished with Failed
    19 days ago
    Total: 694s
    #328678
  • Pipeline finished with Success
    18 days ago
    Total: 606s
    #329658
  • πŸ‡ΊπŸ‡ΈUnited States smustgrave

    Left comments on MR.

  • First commit to issue fork.
  • Pipeline finished with Success
    2 days ago
    Total: 550s
    #345640
  • πŸ‡¦πŸ‡ΉAustria arthur_lorenz Vienna

    Adressed @smustgrave's comments.

Production build 0.71.5 2024