Skip to content

Static-cache-safe CSRF input#14625

Merged
brandonkelly merged 11 commits into4.9from
feature/cms-1282-static-cache-safe-csrfinput
Apr 12, 2024
Merged

Static-cache-safe CSRF input#14625
brandonkelly merged 11 commits into4.9from
feature/cms-1282-static-cache-safe-csrfinput

Conversation

@timkelty
Copy link
Copy Markdown
Contributor

@timkelty timkelty commented Mar 19, 2024

Description

  • Adds \craft\config\GeneralConfig::$asyncCsrfInputs
  • csrfInput options now take a async boolean to override the \craft\config\GeneralConfig::$asyncCsrfInputs default
  • no-cache headers are added if CSRF is rendered traditionally

@linear
Copy link
Copy Markdown

linear Bot commented Mar 19, 2024

@timkelty timkelty changed the title Feature/cms 1282 static cache safe csrfinput Static-cache-safe CSRF input Mar 19, 2024
@timkelty timkelty requested a review from brandonkelly March 19, 2024 16:04
@timkelty timkelty self-assigned this Mar 19, 2024
@brandonkelly brandonkelly changed the base branch from develop to 4.9 March 19, 2024 16:34
@timkelty timkelty marked this pull request as draft March 28, 2024 15:44
Up to brandon, but I like this better.
@timkelty timkelty requested a review from brianjhanson April 8, 2024 15:44
@timkelty timkelty marked this pull request as ready for review April 8, 2024 15:44
Comment thread src/templates/_special/csrf-input.twig Outdated
@brandonkelly
Copy link
Copy Markdown
Member

@timkelty Would it make more sense to return a placeholder <div> with a unique ID where the CSRF input should go, and then register the JS via View::registerJs(), so the Ajax request doesn’t block page rendering?

@timkelty
Copy link
Copy Markdown
Contributor Author

timkelty commented Apr 9, 2024

@timkelty Would it make more sense to return a placeholder <div> with a unique ID where the CSRF input should go, and then register the JS via View::registerJs(), so the Ajax request doesn’t block page rendering?

@brandonkelly for that reason, I don't think so – we can achieve the same thing with aync or defer attributes on the script (check me here @brianjhanson).

However, if we wanted to support multiple forms/csrfs with a single fetch, IDs and View::registerJs() would probably be the way to go.

Blitz's CSRF tags do this, but I thought it was maybe too much for the initial core functionality.

@brandonkelly
Copy link
Copy Markdown
Member

In theory each CSRF input will have the same name and value right? So it might make sense to just set a data-csrf-placeholder attribute on a placeholder div, and have the JS swap out all placeholder instances with the input. At that point the JS code would be identical each time, so it would only get registered once (View::registerJs() ensures uniqueness).

@timkelty
Copy link
Copy Markdown
Contributor Author

timkelty commented Apr 10, 2024

In theory each CSRF input will have the same name and value right? So it might make sense to just set a data-csrf-placeholder attribute on a placeholder div, and have the JS swap out all placeholder instances with the input. At that point the JS code would be identical each time, so it would only get registered once (View::registerJs() ensures uniqueness).

The way it is implemented now, each instance will get a new CSRF…which initially I was thinking was desirable, but I guess there's no reason they couldn't all be the same, right?

@brandonkelly
Copy link
Copy Markdown
Member

The token values will be different each time, but as long as the user session doesn’t change, any of them will work in place of one another. And they can be reused—Craft’s control panel JS will just get a single CSRF token, and reuse it for each Ajax request.

@timkelty
Copy link
Copy Markdown
Contributor Author

timkelty commented Apr 12, 2024

In theory each CSRF input will have the same name and value right? So it might make sense to just set a data-csrf-placeholder attribute on a placeholder div, and have the JS swap out all placeholder instances with the input. At that point the JS code would be identical each time, so it would only get registered once (View::registerJs() ensures uniqueness).

@brandonkelly ok, refactored.

  • uses a custom element, <craft-csrf-input> as a placeholder. While it doesn't get registered as a web component (because it doesn't need to), it seems better to use as a placeholder/selector. The craft- prefix follows the web component stuff @brianjhanson has been using.
  • I'm using View::registerHtml instead of View::registerJs for a couple reasons:
    • I need to pass the URL as a variable
    • I loathe JS in PHP

@brandonkelly brandonkelly merged commit 1f162d3 into 4.9 Apr 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants