CSRF Inconsistency when sending POST from Ember to Sails Backend

Firstly, I just wanted to say that I read all the other topics related to this topic, but no luck. Here's a breakdown of the problem:

purpose

  • Get CSRF Token from Sails on Ember Application Launch
  • Embed this CSRF token in every AJAX request initiated with the Ember app

To meet goal 1, I created the Ember Initializer, which starts when the application first loads (if there is a better place for this, I am completely open to suggestions). To meet goal 2, I extract the CSRF token from Sails and then try to use Ember.$.ajaxSetup() to ensure that the CSRF token is passed either as a header ( X-CSRF-Token ) or as a parameter ( _csrf ). I also guarantee that I use the withCredentials parameter to make sure the cookie is set. Here is the code:

 // initializers/csrf.js import Ember from 'ember'; import config from '../config/environment'; export function initialize() { Ember.$.get(config.APP.API_URL + '/csrfToken').then(function(result) { Ember.$.ajaxSetup({ data: { '_csrf': result._csrf }, xhrFields: { withCredentials: true } }); }, function(error) { console.log(error); }); } export default { name: 'csrf', initialize: initialize }; 

All this works the way I see in Chrome dev tools that extract the CSRF token, and when I make an AJAX request, I see that the data is added to the POST data or added as a header (both options). Here's the code I'm running and all the related headers:

 Ember.$.post(config.APP.API_URL + '/auth/register', { 'email': _this.get('email'), 'password': _this.get('password') }).then(function(response) { console.log('It worked!'); }); 

Request header

 POST /auth/register HTTP/1.1 Host: localhost:1337 Connection: keep-alive Content-Length: 82 Accept: */* Origin: http://localhost:4200 CSP: active User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36 Content-Type: application/x-www-form-urlencoded; charset=UTF-8 DNT: 1 Referer: http://localhost:4200/signup Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.8 Cookie: sails.sid=s%3AbrABhErTY3-ytTWOKFJ2KBj7DCAzaLDc.apD60Sd%2BW85GSbTfJ7E3B2PrUwnhOsW6GlNpZTu9jFg 

Form data

 _csrf:yP7GDiU2-YGmLBfBvQtMPT3-hRpnfK0x-AfA email: test@test.com password:q1w2e3r4 

Answer Headers

 HTTP/1.1 403 Forbidden Vary: X-HTTP-Method-Override Access-Control-Allow-Origin: http://localhost:4200 Access-Control-Allow-Credentials: true Content-Type: text/html; charset=utf-8 Content-Length: 13 Date: Thu, 09 Jul 2015 08:11:34 GMT Connection: keep-alive 

As seen from the Response headers, I get 403 Forbidden - CSRF Mismatch from Sails. Now, here, where it gets a little weird: first, I can run it just fine with Postman. I extract the token and then send that token along with the data to the /auth/register url and it works as expected.

I also tried removing the initializer and running the following code:

 Ember.$.ajaxSetup({ xhrFields: { withCredentials: true } }); Ember.$.get(config.APP.API_URL + '/csrfToken').then(function(result) { Ember.$.post(config.APP.API_URL + '/auth/register', { 'email': _this.get('email'), 'password': _this.get('password'), '_csrf': result._csrf }).then(function(response) { console.log('It worked!'); }); }); 

It works. However, at the moment I am losing a little, which is actually a problem. Appreciate any help I can get.

Thanks in advance! James

+7
javascript jquery ajax
source share
3 answers

@ jdixon04. Can you try the URL encoding of the CSRF token before submitting via POST? Token mismatch will occur if the token is changed from the original.

I found this problem on Github: https://github.com/balderdashy/sails/issues/2266 .

I hope this solves your problem. Try and let me know if that works. Thanks.

+2
source share

@ jdixon04, got here from your post on my github problem . In fact, does the CSRF token change with every request made to the server? Then you come to the token fixing, when the external load does not cope with this, you may need to extract the token before each request and use ajaxPrefilter to transmit its request.

Is it really related to sails with ember data? I think you are doing pure ajax here! If you look in my configuration, you will realize that pure ajax calls (for authentication as well) are exempt from csrf, since I could not get it working as I wanted: \.

+2
source share

Add the x-csrf-token header as follows:

 Ember.$.ajaxSetup({ headers: { 'X-CSRF-TOKEN': result._csrf }, xhrFields: { withCredentials: true } }); 
0
source share

All Articles