<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>

CC BY-SA 4.0
2019-10-03T06:45:18.463Z
This is IMHO the prettiest solution.
KSPR
CC BY-SA 3.0
2016-02-23T20:42:59.477Z
2016-02-23T20:42:59.477Z
Lindsey D
<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>

CC BY-SA 3.0
2018-04-09T18:45:55.517Z
2018-04-09T18:45:55.517Z
David Oliver
<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>

CC BY-SA 3.0
2017-04-03T16:55:34.933Z
2017-04-03T16:55:34.933Z
jthomas
<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>

CC BY-SA 3.0
2016-02-24T00:44:37.890Z
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()`.
Brandon Kelly
CC BY-SA 3.0
2016-02-23T22:45:22.423Z
2016-02-23T22:45:22.423Z
Peter Compernolle
<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>

CC BY-SA 3.0
2016-02-23T20:51:04.940Z
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
Ben Wilkins
CC BY-SA 3.0
2016-02-24T00:42:52.723Z
[Removed](http://craftcms.stackexchange.com/posts/13855/revisions) the first solution since it wouldn't work. But the `|replace` tag method would definitely work.
Brandon Kelly
CC BY-SA 3.0
2018-04-09T18:46:37.537Z
I believe the `|raw` filter is required. See my answer for an example.
David Oliver
CC BY-SA 3.0
2016-02-23T20:49:55.270Z
2017-11-20T20:36:58.030Z
2017-11-20T20:36:58.030Z
Ben Wilkins
<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>

<templating><cache><csrf>
How can I Prevent CSRF Tokens from being Cached?
# 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, Lindsey'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.

Omit the standard getCsrfInput Twig tag.
Give your form(s) the class of csrf.
Add this Twig code outside of the cached area:

{% includejs %}
    $(function() {
        $('form.csrf').prepend('');
    });
{% 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:

    ${getCsrfInput}
    # ...


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 Lindsey 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('', $charset);
    }
    return '';
}

Then, we can get an uncached  element in all of our forms using:
{# any form #}

    ...
    {{ getUncachedCsrfInput }}
    ...


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()`.  

---

