-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Passing X-CSRF-Token (Ruby on Rails) #424
Comments
Passing Are you sure the correct token gets passed? Can you use Chrome devtools or a debugging HTTP proxy to inspect the actual HTTP headers sent with the fetch POST request? |
Hey Mislav, thanks for the answer. Yes, I'm quite sure everything is properly passed - token is the same as the one in jQuery post request. I've added I've done some additional debugging and comparing between those two requests, then I've tried to send the same headers but didn't work. There's a "Cookie" sent in jQuery request header (which is not sent in fetch) and some other headers are bit different...don't know if this could be the reason. Anyway, I'll go with jQuery here. Thanks for helping out. |
@peric You need to set fetch(url, {
method: 'POST',
headers: {
'X-Requested-With': 'XMLHttpRequest',
'X-CSRF-Token': token
},
body: ,
credentials: 'same-origin'
}) Updated: to make rails accept JSON post, add the following code to header: 'Content-Type': 'application/json',
'Accept': 'application/json' |
I went back to jQuery for this, but thanks! |
Yeah, jQuery is a very good solution. The only problem is when you test, you need a DOM to make jQuery work (jsdom...) which I don't want to import to all my redux tests. But anyways those headers look ugly |
You could wrap fetch in your app to set those headers by default: var originalFetch = window.fetch
function myFetch(req, init) {
var request = new Request(req, init)
request.headers.set('X-Requested-With', 'XMLHttpRequest')
if (request.method !== 'GET') init.headers.set('X-CSRF-Token', getCsrfToken())
request.credentials = 'same-origin'
return originalFetch(request)
} You could even override |
As RoR5 has Per-form CSRF Tokens:
How will we be able to use One solution is to set this option to |
The way we do this in GitHub.com is to generate an actual fetch(form.action, {
method: 'POST',
body: new FormData(form)
}) |
Thanks for these steps. After following them I got mildly frustrated, but then realized my problem is that Django expects the header to be called |
I just want to say that this works on Laravel too but you gotta add
to the request. |
Thanks @simioluwatomi , this was the problem for me too. full code (coffescript) buildRequest: ()->
headers = new Headers()
headers.append('X-Requested-With', 'XMLHttpRequest')
headers.append('X-CSRF-TOKEN', @csrfToken)
headers.append('Content-Type', 'application/json')
new Request('/blogs', {
headers: headers,
credentials: 'same-origin',
method: 'POST',
body: JSON.stringify(
"blog": {
title: @blog.title,
body: @blog.body
}
)
}) |
here's an updated typescript version of @origamih 's snippet function apiFetch(req: string | Request, init: RequestInit) {
init = Object.assign(init, {
credentials: 'same-origin',
headers: {
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/json'
},
});
const csrfToken = 'TEST123';
let request = new Request(req, init);
if (request.method != 'GET')
init.headers['X-CSRF-Token'] = csrfToken;
return fetch(request, init);
} |
I also ran into this issue in rails, and had to modify @origamih's code, then it worked nicely. I set up a function which I export and use to wrap fetch requests, as shown below: const getHeaders = () => {
let headers = new window.Headers({
'Content-Type': 'application/json',
'Accept': 'application/json',
'X-Requested-With': 'XMLHttpRequest'
})
const csrfToken = document.head.querySelector("[name='csrf-token']")
if (csrfToken) { headers.append('X-CSRF-Token', csrfToken) }
return headers
}
export const createRequest = (url, method = 'get') {
const request = new window.Request(url, {
headers: getHeaders(),
method: method,
credentials: 'same-origin',
dataType: 'json'
})
return request
} And use it like so: import { createRequest } from './lib/createRequest'
fetch(createRequest('my-url', 'get'))
.then(response => response.json())
.then(data => {
console.log(data)
}) |
In Ruby on Rails, you need to pass
X-CSRF-Token
in POST request header in order to properly handle the form.jquery-ujs
basically handles that by default, but if you are not using it or you want to send requests with some other libraries (likefetch
), you need to pass this header by your own.In jQuery, this can be handle (and this works) like:
With
fetch
, I've tried:And this example never works - controller will always raise a
InvalidAuthenticityToken
exception.Any ideas how can this be solved with fetch?
The text was updated successfully, but these errors were encountered: