Answers.Body: <p>I think the token needs to be refreshed with each request. When Blitz caches the page, you will have always the same token as the meta tags will include the token that was assigned at the time.</p>
  <p>If you want to keep caching the page with Blitz, you can for example use one of Blitz's functions to get a new one via Javascript. See the Documentation on <a href="https://putyourlightson.com/plugins/blitz#csrf-controller-actions" rel="nofollow noreferrer">CSRF Controller Actions</a></p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2024-06-27T11:59:42.537Z
Answers.Text: Thank you. That is correct. I had already looked at the documentation. I should have seen it. Sorry.
Answers.UserDisplayName: user3086053
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2024-06-28T12:03:59.843Z
Answers.Text: Happens to the best :)
Answers.UserDisplayName: Max Strebel
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2024-06-26T17:45:20.173Z
Answers.LastActivityDate: 2024-06-26T17:45:20.173Z
Answers.UserDisplayName: Max Strebel
Body: <p>I'm not sure if this happens due to the Blitz cache.
  In Craft CMS 5:
  In the head:</p>
  <pre><code>&lt;meta name=&quot;csrf-token&quot; content=&quot;{{ craft.app.request.getCsrfToken() }}&quot;&gt;
  &lt;meta name=&quot;csrf-param&quot; content=&quot;{{ craft.app.config.general.csrfTokenName }}&quot;&gt;
  </code></pre>
  <p>When executing the ajax call:</p>
  <pre><code>...
  const csrfTokenMeta = document.head.querySelector('meta[name=&quot;csrf-token&quot;]');
  const csrfParamMeta = document.head.querySelector('meta[name=&quot;csrf-param&quot;]');
  ...
  formData.append(csrfTokenName, csrfToken);
  ...
  
      fetch(`/ajax/my-request`, {
          method: 'POST',
          body: formData,
          headers: {
              'Accept': 'application/json',
              'X-Requested-With': 'XMLHttpRequest'
          }
      })
          .then(response =&gt; {
              ...
              if (!response.ok) {
                  throw new Error('Network response was not ok');
              }
              return response.json();
          })
          .then(data =&gt; {
              if (data.success) {
                  ...
              } else {
                  console.error('Failed to load.', data.message);
              }
          })
          .catch(error =&gt; {
              console.error('Error:', error);
              ...
          })
          .finally(() =&gt; {
              ...
          });
  </code></pre>
  <p>From the storage/logs I can see:</p>
  <pre><code>[web.ERROR] [yii\web\HttpException:400] yii\web\BadRequestHttpException: Unable to verify your data submission. in /craft/vendor/yiisoft/yii2/web/Controller.php
  </code></pre>
  <p>Could it be that this error occurs when the posted CSRF token param doesn't match the one in the CSRF cookie?</p>
  <p>When I clear the cache the problem is resolved. But that is just a temporary solution.
  What can I do to resolve that issue so that the ajax calls keeps working?
  What am I missing here?</p>
  
Tags: <cache><craft4><ajax><csrf><plugin-blitz>
Title: Ajax call returns 400 error after enable Blitz cache
ThreadText: # Ajax call returns 400 error after enable Blitz cache
  
  (Asked by: username_0 on 2024-06-26)
  
  I'm not sure if this happens due to the Blitz cache.
  In Craft CMS 5:
  In the head:
  
  ```
  <meta name="csrf-token" content="{{ craft.app.request.getCsrfToken() }}">
  <meta name="csrf-param" content="{{ craft.app.config.general.csrfTokenName }}">
  
  ```
  
  When executing the ajax call:
  
  ```
  ...
  const csrfTokenMeta = document.head.querySelector('meta[name="csrf-token"]');
  const csrfParamMeta = document.head.querySelector('meta[name="csrf-param"]');
  ...
  formData.append(csrfTokenName, csrfToken);
  ...
  
      fetch(`/ajax/my-request`, {
          method: 'POST',
          body: formData,
          headers: {
              'Accept': 'application/json',
              'X-Requested-With': 'XMLHttpRequest'
          }
      })
          .then(response => {
              ...
              if (!response.ok) {
                  throw new Error('Network response was not ok');
              }
              return response.json();
          })
          .then(data => {
              if (data.success) {
                  ...
              } else {
                  console.error('Failed to load.', data.message);
              }
          })
          .catch(error => {
              console.error('Error:', error);
              ...
          })
          .finally(() => {
              ...
          });
  
  ```
  
  From the storage/logs I can see:
  
  ```
  [web.ERROR] [yii\web\HttpException:400] yii\web\BadRequestHttpException: Unable to verify your data submission. in /craft/vendor/yiisoft/yii2/web/Controller.php
  
  ```
  
  Could it be that this error occurs when the posted CSRF token param doesn't match the one in the CSRF cookie?
  
  When I clear the cache the problem is resolved. But that is just a temporary solution.
  What can I do to resolve that issue so that the ajax calls keeps working?
  What am I missing here?
  
  **Tags:** cache, craft4, ajax, csrf, plugin-blitz
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2024-06-26. Score: 2 | Accepted answer
  
  I think the token needs to be refreshed with each request. When Blitz caches the page, you will have always the same token as the meta tags will include the token that was assigned at the time.
  
  If you want to keep caching the page with Blitz, you can for example use one of Blitz's functions to get a new one via Javascript. See the Documentation on [CSRF Controller Actions](https://putyourlightson.com/plugins/blitz#csrf-controller-actions)
  
  > **Comments:**
  > **username_0**: Thank you. That is correct. I had already looked at the documentation. I should have seen it. Sorry.  
  > **username_1**: Happens to the best :)  
  
  ---
  
  