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


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


12

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


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

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


8

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>


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

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

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

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

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

as jQuery docs says you have to pass data object or string via data. so you should change var data = []; to var data = {}; in your code


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


1

You can disable the token for a certain controller via use Craft; ... Yii::$app->controller->enableCsrfValidation = false; or inside a Controller for a certain request /** * @inheritdoc */ public function beforeAction($action) { if ($action->id == 'my-method') { $this->enableCsrfValidation = false; } return ...


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