Hot answers tagged

20

Disabling the CSRF protection is probably a bad idea... it's in there for a reason. But you can easily add your CSRF data to an AJAX call, and it works very well! The key is to make your CSRF token name & value available in your front-end JS. You can then pass that into your AJAX call as an additional value. There are a few ways to push the CSRF data ...


15

In Craft 3 this is a cinch: class PluginController extends Controller { // Disable CSRF validation for the entire controller public $enableCsrfValidation = false; ... See the Yii2 docs for more control over inividual actions: https://github.com/yiisoft/yii2/blob/master/docs/guide/security-best-practices.md#avoiding-csrf


13

Craft is piggybacking off of Yii's CSRF support for 90% of the work here and they've implemented it at the Request level (specifically onBeginRequest). That happens way before Craft gets a chance to determine what type of request this is, much less figure out where to route it. I think your best bet is going to be to put some logic in Craft's general.php ...


11

As Brad's answer suggests, you can conditionally enable or disable CSRF production via the General Config, based on any criteria you want. Some use cases might be: match a SERVER['REQUEST_URI'] string or substring, to open up a particular set of controllers or actions check the $_SERVER['REMOTE_ADDR'], to allow token-less requests from a particular IP or ...


10

This is the syntax for Craft 3: <script type="text/javascript"> window.csrfTokenName = "{{ craft.app.config.general.csrfTokenName }}"; window.csrfTokenValue = "{{ craft.app.request.csrfToken }}"; </script>


10

UPDATE: This is not necessary to do when using Commerce 2. I modified Michael's answer to add support for query strings + make it nicer to check for multiple routes: if ( !function_exists('isApiRequest') ) { function isApiRequest () { $path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); $query = parse_url($_SERVER['REQUEST_URI']...


10

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()}) }}


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('<input type="hidden" name="{{ craft.config.get('csrfTokenName') }}" value="{{ craft.request.getCsrfToken }}"...


8

We got this sorted before I finished my Stack Exchange question so I figured I'd share if anyone else runs into similar behavior. After some troubleshooting, we learned that the issue here was that some of our Forms were being cached by Craft's {% cache %} tag and others were not. CSRF Cookies are unique per user per session, so you don't want to cache ...


5

actionUrl() and UrlHelper::getActionUrl() always force the script name to show up despite the omitScriptNameInUrls config setting for two reasons: Action URLs are generally not actually visible to end users, so there’s no point in hiding “index.php” from them (computers don’t care about aesthetics). They are often used for POST requests, and your index.php ...


5

You need to pass the token and name into javascript. Easiest is to just have a script tag somewhere. <script type="text/javascript"> window.csrfTokenName = "{{ craft.config.csrfTokenName }}"; window.csrfTokenValue = "{{ craft.request.csrfTokenValue }}"; </script> Now they will be available to your ajax call.


4

This is the syntax for Craft 3: <script type="text/javascript"> window.csrfTokenName = "{{ craft.app.config.general.csrfTokenName }}"; window.csrfTokenValue = "{{ craft.app.request.csrfToken }}"; </script>


4

I don't think you can cache that, since the tag is run server-side and rendered with template output, and will be unique on every page load. If you have content that's unique on every page load, you'd have to either ignore that page from CDN caching, or dynamically load in the unique content after page load via an AJAX call to a page that is ignored from CDN ...


3

Just found the solution: npm install qs and import qs from 'qs' ... const actions = { auth({ commit }, { email, password }) { axios.post('url', qs.stringify({ your token data here })).then((res) => { console.log(res.data) }).catch((err) => { console.log(err) }) } }


3

Enable CSRF protection in your config again and add {{ getCsrfInput() }} right after the <form> opening tag on all forms on your site, regardless if they are amforms or mailchimp subscribe. I can verify that it won't interfere with the mailchimp plugin as I am currently (and just recently) installed it on a project I'm working on and it works fine.


3

If CSRF protection is enabled (and it is by default for the latest versions of Craft), Stripe was getting a server error when using the Charge webhook url. The solution is to disable CSRF for the webhook URI - you can read more about it here or simply add this to your config/general.php file: 'enableCsrfProtection' => (!isset($_SERVER['REQUEST_URI']) || ...


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: <form method="post" action="" accept-charset="UTF-8"> ${getCsrfInput} # ... </form> some_page....


2

After the page loads with the form loads, delete the CSRF cookie, then submit the form. It should fail CSRF token validation.


2

Chris is quite correct – CSRF does not work with GET requests (see this answer by Brad Bell for an explanation). I'm posting my workaround as an additional answer in case anyone else ever needs to have CSRF validation for GET requests working. To get around the issue, I set up a custom config key in /config/general.php called tokenGetParam. This is because ...


2

According to https://craftcms.com/support/csrf-protection CSRF does require POST requests With CSRF protection enabled, all of your site’s visitors will get a “CRAFT_CSRF_TOKEN” cookie set on their browser, and all POST requests must be accompanied by a POST parameter with a matching name and value (the CSRF Token). On top of that, you'll need to (...


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


2

Maybe try craft()->request->getCsrfToken(), see if that does it? Edit Sorry, misunderstood the question, since you are saying your plugin has a CP section then i'm assuming you're actually looking for a twig way to output the CSRF input, not so much a PHP way. To output the CRSF input in your template simply do {{ getCsrfInput() }}


2

Once the same problem happened for me because of server caching and it may happen because of client-side cookie/cache. Sometimes, server caching will cache the entire form including CSRF token. So if there any option to use the minimal cache on the server, apply it/remove the server cache option itself. it may fix this problem. Note: This only my experience....


2

I have exactly the same issue, clearing cookies worked for me


2

I guesss this could be accomplished using the cookies plugin or a simple jquery cookies library like js-cookie. This is how you would go about it with the cookies plugin: set the cookies name without any value: {{ setCookie( NAME ) }}


2

the CSRF field its a hidden field not part of the form attributes. You don't have to manually type it, craft twig comes with {{ getCsrfInput() }} that recreates a hidden field between the <form></form> tags. <form method="post"> {{ getCsrfInput() }} <!-- ... --> </form> Also, that seems to be a Javascript call if you are ...


2

You can take a look at the guide Enabling CSRF Protection <script type="text/javascript"> window.csrfTokenName = "{{ craft.app.config.general.csrfTokenName|e('js') }}"; window.csrfTokenValue = "{{ craft.app.request.csrfToken|e('js') }}"; </script> var data = { // ... }; // Add the CSRF Token data[csrfTokenName] = csrfTokenValue; $...


2

For Craft 2, these are the values you're looking for... window.csrfTokenName = "{{ craft.config.get('csrfTokenName') }}"; window.csrfTokenValue = "{{ craft.request.getCsrfToken }}"; They changed slightly in Craft 3, which can be seen here...


2

It is actually possible but it's a little bit difficult for beginners. You'll need make use of Service Locators and overwrite craft\web\Response to change this method foreach ($this->getCookies() as $cookie) { $value = $cookie->value; if ($cookie->expire != 1 && isset($validationKey)) { $value = Yii::$app->getSecurity()-&...


2

You could make the CSRF token available via an element API endpoint, then submit the form with that; 'api/csrf-token' => [ 'elementType' => GlobalSet::class, 'paginate' => false, 'one' => true, 'transformer' => function () { $newCSRFtoken = Craft::$app->request->getCsrfToken(); // sets a new CSRF cookie; ...


Only top voted, non community-wiki answers of a minimum length are eligible