First off, I just wanted to say that I have read through all of the other threads relating to this topic, but haven't had any luck. Here's a breakdown of the issue:
Goals
To satisfy goal 1, I created an Ember Initializer that runs when the application first boots up (if there is a better place for this, I'm totally open to suggestions). To satisfy goal 2, I retrieve the CSRF token from Sails and then attempt to use Ember.$.ajaxSetup()
to ensure the CSRF token is passed either as a header (X-CSRF-Token
) or parameter (_csrf
). I also ensure that I'm using the withCredentials
option to ensure the cookie is set. Here's 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 of this appears to work as I can see in Chrome dev tools that the CSRF token is being retrieved and when I make an AJAX request, I see the data appended to the POST data or added as a header (tried both options). Here's the code I'm running and all of the associated headers:
Ember.$.post(config.APP.API_URL + '/auth/register', {
'email': _this.get('email'),
'password': _this.get('password')
}).then(function(response) {
console.log('It worked!');
});
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
_csrf:yP7GDiU2-YGmLBfBvQtMPT3-hRpnfK0x-AfA
email:[email protected]
password:q1w2e3r4
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 you can see from the Response headers, I end up receiving a 403 Forbidden - CSRF Mismatch
from Sails. Now, here's where it gets a little weird: first, I'm able to run this just fine with Postman. I retrieve a token and then post that token along with the data to the /auth/register
url and it works as expected.
I'm 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!');
});
});
This works. However, at this point, I'm at somewhat of a loss as to what the issue actually is. Appreciate any help I can get.
Thanks in advance! James
To fetch a CRSF token, the app must send a request header called X-CSRF-Token with the value fetch in this call. The server generates a token, stores it in the user's session table, and sends the value in the X-CSRF-Token HTTP response header.
@jdixon04, Can you try URL-encoding the CSRF token before sending it through POST? The token mismatch will occur if the token is getting altered from the original.
I found this issue in Github: https://github.com/balderdashy/sails/issues/2266.
I hope this will solve your issue. Do try it and let me know if it works. Thanks.
@jdixon04, got here from your post on my github issue. Actually, isn't the CSRF token going to change at each request made to the server? Then you approach to fix the token when the frontend load cannot cope with this, you may have to fetch the token before each request and use ajaxPrefilter
to pass it to the request.
Is that actually related to ember-data-sails? It seems to me you're doing pure ajax here! If you look in my config, you'll realise that pure ajax calls (for authentication as well) are exempted from csrf as I could not make it work as I wished :\ .
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With