I am using CSRF tokens in a form on CraftCMS. Submissions are successful with a standard configuration.

Introducing "fresh" CSRF tokens via AJAX on page load is causing some trouble. This is necessary as production has caching.

Here are some observations:

  1. Disabling CSRF validation in config/general.php resolves the issue entirely; however, of course, this is not the solution.
  2. Disabling CSRF cookies does not resolve the issue.
  3. Failed attempts appear most commonly in iOS on Safari. It also occurs sometimes on Edge. It appears to work always in Chrome.
  4. Regarding Safari: one idea here was that the browser disrespects Cache-Control and thinks it should be caching this request, hence resulting in a failed CSRF validation. Adding in a timestamp to the request in a query string did not resolve the issue.
  5. Failed attempts result in a "400 Bad Request" response. The body sometimes reads: Bad Request: Unable to verify your data submission.
  6. Failed attempts occur regardless of server side caching. This has been tested on local environments (Homestead) with no non-standard caching configurations.
  7. The token returned on the CSRF AJAX request is different each time.
  8. The form is built with FreeForm, but I do not think that is of significance.


  1. How does one track the request further to find the reason for failure?
  2. Is providing CSRF tokens via an AJAX request sensible? The typical response I see is adding in the token via an inline Javascript variable. (Read) That route is not an option here.

Any pointers here would be very appreciated. Thanks in advanced!

1 Answer 1


Trying to understand the issue in general. These are my thoughts, not sure if they will help you.

I assume that by caching, you mean some sort of full page cache and the comments below are based on that.

AJAX requests to support CSRF in craft, require the tokens name/value passed as a param in the request data.

In general, if you introduce a full page cache system on your system, you generally need a 'hole punching' mechanism to exclude from caching, any dynamically set variables.

This is a common use for eCommerce websites. For example where you might have a mini-cart feature on your page which needs refreshing when you perform an 'add to cart' action using AJAX. So the page does not refresh, but that bit of template needs refreshing.

Within Craft, I would try to exclude from caching the javascript lines that introduce the CSRF token, as well as excluding from cache any twig methods that generate the CSRF token in the templates

The way to perform 'hole punching' depends on the type of full page caching you are using. Each system have their own method.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.