Answers.Body: <p>The trick is to inject the CSRF field using JavaScript.</p>
  
  <ol>
  <li>Omit the standard <code>getCsrfInput</code> Twig tag.</li>
  <li>Give your form(s) the class of <code>csrf</code>.</li>
  <li>Add this Twig code <strong>outside of the cached area:</strong></li>
  </ol>
  
  <pre class="lang-javascript prettyprint-override"><code>{% includejs %}
      $(function() {
          $('form.csrf').prepend('&lt;input type="hidden" name="{{ craft.config.get('csrfTokenName') }}" value="{{ craft.request.getCsrfToken }}" /&gt;');
      });
  {% endincludejs %}
  </code></pre>
  
  <p>This will dynamically inject the correct CSRF input field into every form with the <code>csrf</code> class.</p>
  
  <hr>
  
  <p><em>* Disclaimer: This example assumes you're using jQuery. A similar solution can be enacted without jQuery, but some adjustments would need to be made.</em></p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-10-03T06:45:18.463Z
Answers.Text: This is IMHO the prettiest solution.
Answers.UserDisplayName: KSPR
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-02-23T20:42:59.477Z
Answers.LastActivityDate: 2016-02-23T20:42:59.477Z
Answers.UserDisplayName: Lindsey D
Answers.Body: <p>Further to Ben’s answer, it may be inconvenient to <code>set</code> and <code>replace</code> every time the partial with the CSRF token is required, in which case the replacing can instead be done in one go for each page’s content in the layout.</p>
  
  <p><strong>_some_partial.twig:</strong></p>
  
  <pre class="lang-html prettyprint-override"><code>&lt;form method="post" action="" accept-charset="UTF-8"&gt;
      ${getCsrfInput}
      # ...
  &lt;/form&gt;
  </code></pre>
  
  <p><strong>some_page.twig:</strong></p>
  
  <pre><code>{% block content %}
      {% include '_some_partial.twig' %}
  {% endblock %}
  </code></pre>
  
  <p><strong>_layout.twig:</strong></p>
  
  <pre><code>{{ block('content')|replace({'${getCsrfInput}': getCsrfInput()})|raw }}
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2018-04-09T18:45:55.517Z
Answers.LastActivityDate: 2018-04-09T18:45:55.517Z
Answers.UserDisplayName: David Oliver
Answers.Body: <p>I was just looking for a way to do something similar without Javascript. Someone has released a cache escaping extension giving you the ability to wrap content you want esacped with a <code>{% nocache %}</code> tag.</p>
  
  <p>Basic example:</p>
  
  <pre><code>{% cache %}
      This will be cached
      {% nocache %}
          This won't be
      {% endnocache %}
  {% endcache %}
  </code></pre>
  
  <p>Extension: <a href="https://github.com/benjamminf/craft-nocache" rel="nofollow noreferrer">https://github.com/benjamminf/craft-nocache</a></p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-04-03T16:55:34.933Z
Answers.LastActivityDate: 2017-04-03T16:55:34.933Z
Answers.UserDisplayName: jthomas
Answers.Body: <p>Thanks Lindsey and Ben!</p>
  
  <p>I was hoping to avoid using Javascript to handle CSRF, because our site otherwise is not dependent on it. I took Ben's suggestion of creating a variable outside of the cache, and using it within the cache. I ran a quick test to verify that it indeed would use the uncached value.</p>
  
  <p>I wound up making a Twig extension to get uncached CSRF input, which we can set in our <code>_layout.html</code>:</p>
  
  <pre><code>{# in craft/templates/_layout.html #}
  {% set csrfToken = craft.request.getCsrfToken() %}
  </code></pre>
  
  <p>Then we build the twig extension to access the <code>csrfToken</code> from the Twig context, and render a hidden input element:</p>
  
  <pre><code>// craft/plugins/ourplugin/twigextensions/OurPluginTwigExtension.php
  
  public function getFunctions() {
      return [
          'getUncachedCsrfInput' =&gt; new \Twig_Function_Method($this, 'getUncachedCsrfInput', ['needs_context' =&gt; true])
      ];
  }
  
  public function getUncachedCsrfInput($context) {
      if (craft()-&gt;config-&gt;get('enableCsrfProtection') === true) {
          $charset = craft()-&gt;templates-&gt;getTwig()-&gt;getCharset();
          //access the csrfToken variable from the Twig context,
          //    or fall back on craft()-&gt;request otherwise
          $csrf = array_key_exists('csrfToken', $context) ? $context['csrfToken'] : craft()-&gt;request-&gt;getCsrfToken();
  
          return new \Twig_Markup('&lt;input type="hidden" name="'.craft()-&gt;config-&gt;get('csrfTokenName').'" value="'. $csrf .'"&gt;', $charset);
      }
      return '';
  }
  </code></pre>
  
  <p>Then, we can get an uncached <code>&lt;input /&gt;</code> element in all of our forms using:</p>
  
  <pre><code>{# any form #}
  &lt;form action="" method="POST"&gt;
      ...
      {{ getUncachedCsrfInput }}
      ...
  &lt;/form&gt;
  </code></pre>
  
  <p>Thanks for your help!</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-02-24T00:44:37.890Z
Answers.Text: If `{{ getUncachedCsrfInput() }}` is happening inside a `{% cache %}` tag, this won't work since the `{% cache %}` tag will cache its entire output and use that cached output on subsequent requests (and each user session gets its own CSRF token value). Also not sure what the point of all this added complexity over just using `getCsrfInput()`.
Answers.UserDisplayName: Brandon Kelly
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-02-23T22:45:22.423Z
Answers.LastActivityDate: 2016-02-23T22:45:22.423Z
Answers.UserDisplayName: Peter Compernolle
Answers.Body: <p>You can do something like this:</p>
  
  <pre><code>// First, set all your cached content to a variable:
  {% set myContent %}
    {% cache %}
      {# YOUR CACHED CONTENT #}
      %%MY_CSRF%%
    {% endcache %}
  {% endset %}
  
  // Then, run a replace on your cached content to insert the new CSRF
  {{ myContent|replace({'%%MY_CSRF%%': getCsrfInput()}) }}
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-02-23T20:51:04.940Z
Answers.Text: Also, courtesy hat tip to this post for the general idea of the second solution: http://craftcms.stackexchange.com/questions/4782/adding-active-class-to-globally-cached-navigation
Answers.UserDisplayName: Ben Wilkins
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-02-24T00:42:52.723Z
Answers.Text: [Removed](http://craftcms.stackexchange.com/posts/13855/revisions) the first solution since it wouldn't work. But the `|replace` tag method would definitely work.
Answers.UserDisplayName: Brandon Kelly
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2018-04-09T18:46:37.537Z
Answers.Text: I believe the `|raw` filter is required. See my answer for an example.
Answers.UserDisplayName: David Oliver
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-02-23T20:49:55.270Z
Answers.LastActivityDate: 2017-11-20T20:36:58.030Z
Answers.LastEditDate: 2017-11-20T20:36:58.030Z
Answers.UserDisplayName: Ben Wilkins
Body: <p>We have a Craft site in which we include a partial that includes in several different places. CSRF is enabled, and we're appending <code>{{ getCsrfInput() }}</code> to the form.</p>
  
  <p>Because of the way we've set up the site, and are including this partial in so many places, nearly all of the forms we're rendering are using <em>cached</em> CSRF tokens, which invalidates them.</p>
  
  <p>Is there a way to prevent Craft's <code>{% cache %}</code> tag from including the generated CSRF token without ending the cache and starting it up again each time? (eg, <code>{% endcache %}{{ getCsrfInpt() }}{% cache %}</code>) </p>
  
  <p>I worry doing so would be risky, because we may include this partial in a part of the site that is <em>not</em> cached, so there'd be no cache tag to end.</p>
  
  <p>Thanks!</p>
  
  <p>Update: I failed to mention that our site works right now without Javascript, so I'd like to avoid it. Otherwise, Lindsey's answer is perfect.</p>
  
Tags: <templating><cache><csrf>
Title: How can I Prevent CSRF Tokens from being Cached?
ThreadText: # How can I Prevent CSRF Tokens from being Cached?
  
  (Asked by: username_0 on 2016-02-23)
  
  We have a Craft site in which we include a partial that includes in several different places. CSRF is enabled, and we're appending `{{ getCsrfInput() }}` to the form.
  
  Because of the way we've set up the site, and are including this partial in so many places, nearly all of the forms we're rendering are using *cached* CSRF tokens, which invalidates them.
  
  Is there a way to prevent Craft's `{% cache %}` tag from including the generated CSRF token without ending the cache and starting it up again each time? (eg, `{% endcache %}{{ getCsrfInpt() }}{% cache %}`)
  
  I worry doing so would be risky, because we may include this partial in a part of the site that is *not* cached, so there'd be no cache tag to end.
  
  Thanks!
  
  Update: I failed to mention that our site works right now without Javascript, so I'd like to avoid it. Otherwise, username_1's answer is perfect.
  
  **Tags:** templating, cache, csrf
  
  
  ---
  
  ## 5 answers
  
  ### Answer by username_6 on 2016-02-23. Score: 11 | Accepted answer
  
  You can do something like this:
  
  ```
  // First, set all your cached content to a variable:
  {% set myContent %}
    {% cache %}
      {# YOUR CACHED CONTENT #}
      %%MY_CSRF%%
    {% endcache %}
  {% endset %}
  
  // Then, run a replace on your cached content to insert the new CSRF
  {{ myContent|replace({'%%MY_CSRF%%': getCsrfInput()}) }}
  
  ```
  
  > **Comments:**
  > **username_6**: Also, courtesy hat tip to this post for the general idea of the second solution: http://craftcms.stackexchange.com/questions/4782/adding-active-class-to-globally-cached-navigation  
  > **username_5**: [Removed](http://craftcms.stackexchange.com/posts/13855/revisions) the first solution since it wouldn't work. But the `|replace` tag method would definitely work.  
  > **username_3**: I believe the `|raw` filter is required. See my answer for an example.  
  
  ---
  
  ### Answer by username_1 on 2016-02-23. Score: 9
  
  The trick is to inject the CSRF field using JavaScript.
  
  1. Omit the standard `getCsrfInput` Twig tag.
  2. Give your form(s) the class of `csrf`.
  3. Add this Twig code **outside of the cached area:**
  
  ```javascript
  {% includejs %}
      $(function() {
          $('form.csrf').prepend('<input type="hidden" name="{{ craft.config.get('csrfTokenName') }}" value="{{ craft.request.getCsrfToken }}" />');
      });
  {% endincludejs %}
  
  ```
  
  This will dynamically inject the correct CSRF input field into every form with the `csrf` class.
  
  ---
  
  *\* Disclaimer: This example assumes you're using jQuery. A similar solution can be enacted without jQuery, but some adjustments would need to be made.*
  
  > **Comments:**
  > **username_2**: This is IMHO the prettiest solution.  
  
  ---
  
  ### Answer by username_3 on 2018-04-09. Score: 3
  
  Further to Ben’s answer, it may be inconvenient to `set` and `replace` every time the partial with the CSRF token is required, in which case the replacing can instead be done in one go for each page’s content in the layout.
  
  **\_some\_partial.twig:**
  
  ```html
  <form method="post" action="" accept-charset="UTF-8">
      ${getCsrfInput}
      # ...
  </form>
  
  ```
  
  **some\_page.twig:**
  
  ```
  {% block content %}
      {% include '_some_partial.twig' %}
  {% endblock %}
  
  ```
  
  **\_layout.twig:**
  
  ```
  {{ block('content')|replace({'${getCsrfInput}': getCsrfInput()})|raw }}
  
  ```
  
  
  ---
  
  ### Answer by username_4 on 2017-04-03. Score: 2
  
  I was just looking for a way to do something similar without Javascript. Someone has released a cache escaping extension giving you the ability to wrap content you want esacped with a `{% nocache %}` tag.
  
  Basic example:
  
  ```
  {% cache %}
      This will be cached
      {% nocache %}
          This won't be
      {% endnocache %}
  {% endcache %}
  
  ```
  
  Extension: <https://github.com/benjamminf/craft-nocache>
  
  
  ---
  
  ### Answer by username_0 on 2016-02-23. Score: 0
  
  Thanks username_1 and Ben!
  
  I was hoping to avoid using Javascript to handle CSRF, because our site otherwise is not dependent on it. I took Ben's suggestion of creating a variable outside of the cache, and using it within the cache. I ran a quick test to verify that it indeed would use the uncached value.
  
  I wound up making a Twig extension to get uncached CSRF input, which we can set in our `_layout.html`:
  
  ```
  {# in craft/templates/_layout.html #}
  {% set csrfToken = craft.request.getCsrfToken() %}
  
  ```
  
  Then we build the twig extension to access the `csrfToken` from the Twig context, and render a hidden input element:
  
  ```
  // craft/plugins/ourplugin/twigextensions/OurPluginTwigExtension.php
  
  public function getFunctions() {
      return [
          'getUncachedCsrfInput' => new \Twig_Function_Method($this, 'getUncachedCsrfInput', ['needs_context' => true])
      ];
  }
  
  public function getUncachedCsrfInput($context) {
      if (craft()->config->get('enableCsrfProtection') === true) {
          $charset = craft()->templates->getTwig()->getCharset();
          //access the csrfToken variable from the Twig context,
          //    or fall back on craft()->request otherwise
          $csrf = array_key_exists('csrfToken', $context) ? $context['csrfToken'] : craft()->request->getCsrfToken();
  
          return new \Twig_Markup('<input type="hidden" name="'.craft()->config->get('csrfTokenName').'" value="'. $csrf .'">', $charset);
      }
      return '';
  }
  
  ```
  
  Then, we can get an uncached `<input />` element in all of our forms using:
  
  ```
  {# any form #}
  <form action="" method="POST">
      ...
      {{ getUncachedCsrfInput }}
      ...
  </form>
  
  ```
  
  Thanks for your help!
  
  > **Comments:**
  > **username_5**: If `{{ getUncachedCsrfInput() }}` is happening inside a `{% cache %}` tag, this won't work since the `{% cache %}` tag will cache its entire output and use that cached output on subsequent requests (and each user session gets its own CSRF token value). Also not sure what the point of all this added complexity over just using `getCsrfInput()`.  
  
  ---
  
  