Problem/Motivation

GeneratedUrl objects can have cache metadata.

When generating a URL for a route with the _csrf_token requirement, Drupal automatically adds a token GET param containing a CSRF token.
In the context of a non-HTML response the GeneratedUrl object does not have any cache context so it risks being cached incorrectly.

Steps to reproduce

Create JSON controller that returns this:

    $url = Url::fromRoute('user.logout')->toString(TRUE);
    $response = new CacheableJsonResponse([$url->getGeneratedUrl()]);
    $response->addCacheableDependency($url);

    return $response;

(Note that you have to call it with ?_format=json if you want the real CSRF token and not a placeholder.)

Proposed resolution

Add the session cache context to the URL object when adding a CSRF token to the URL.

Remaining tasks

User interface changes

Introduced terminology

API changes

Data model changes

Release notes snippet

Issue fork drupal-3563538

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

prudloff created an issue. See original summary.

prudloff’s picture

Issue summary: View changes
prudloff’s picture

Issue summary: View changes

My bad, just noticed that in HTML responses the token in the URL is a placeholder that is replaced when rendering the page.
However the problem exists in non-HTML responses.

prudloff’s picture

Tests reveal this impacts some JSON/XML config entity routes because they return a Link HTTP header with the enable/disable URLs.

However I don't understand the remaining failures (in BlockJsonBasicAuthTest for example).
It seems simply adding the cache context makes the generated token different:

1) Drupal\Tests\block\Functional\Rest\BlockJsonBasicAuthTest::testGet
Failed asserting that two arrays are identical.
--- Expected
+++ Actual
@@ @@
     'Link' => Array &4 [
         0 => '<http://localhost/drupal-core/admin/structure/block/manage/llama/delete>; rel="https://drupal.org/link-relations/delete-form"',
         1 => '<http://localhost/drupal-core/admin/structure/block/manage/llama>; rel="edit-form"',
-        2 => '<http://localhost/drupal-core/admin/structure/block/manage/llama/enable?token=wKFf7Br7Nwf4ds4zzkT8i5mH4cwHYMvH8rLnGa8Jw4M>; rel="https://drupal.org/link-relations/enable"',
-        3 => '<http://localhost/drupal-core/admin/structure/block/manage/llama/disable?token=MhdyZVr5dBFq-JyvmmJbUlMVIv2sagpg3oB5WEPyuQA>; rel="https://drupal.org/link-relations/disable"',
+        2 => '<http://localhost/drupal-core/admin/structure/block/manage/llama/enable?token=8MkJHxIkkIzBd1s74zI7wWNatIBXwJXhVuOxS2hQlnE>; rel="https://drupal.org/link-relations/enable"',
+        3 => '<http://localhost/drupal-core/admin/structure/block/manage/llama/disable?token=n64NxBwWKVZ85VCg4Ru7cD-IKQm_ea6GwLQjK2wXNJg>; rel="https://drupal.org/link-relations/disable"',
     ],
     'Content-language' => Array &5 [
         0 => 'en',

/home/pierre/www/drupal-core/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php:641

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.

prudloff’s picture

Status: Active » Needs review

The problem was that the test assumes that the response is cacheable by dynamic page cache so it reuses the headers from the first request to test if they are the same in the seconds request.
But adding the session cache context disables dynamic page cache so this does not work. The test already has some conditions to use a different logic when the response is not cacheable in dynamic page cache so I also did this.

smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Needs change record

Think this needs a CR, since multiple tests had to be updated to pass there is a chance it could break contrib. May seem overkill.

prudloff’s picture

Yes I think it is a duplicate.

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.