CSRF toner is passed in the header when doing POST
I am setting up a VueJS SPA on top of Django. I have a Graphene endpoint working on /api
, and requests in graphiql
are working fine. I have installed the frontend and I am using Apollo Client to query the server. There goes my setup:
const CSRFtoken = Cookies.get('csrftoken')
const networkInterface = createNetworkInterface({
uri: '/api',
transportBatching: true
})
networkInterface.use([{
applyMiddleware (req, next) {
if (!req.options.headers) {
req.options.headers = {} // Create the header object if needed.
}
req.options.headers['X-CSRFToken'] = CSRFtoken
console.log('applied middleware')
next()
}
}])
const apolloClient = new ApolloClient({
networkInterface,
connectToDevTools: true
})
Vue.use(VueApollo)
const apolloProvider = new VueApollo({
defaultClient: apolloClient
})
new Vue({
el: '#app',
apolloProvider,
render: h => h(App)
});
My POST requests have a "X-CSRFToken" header with the value provided Cookies
. Screenshot below:
Unfortunately Django denies access (error 403) with the message "CSRF cookie missing".
I have searched the web but cannot find anything related.
Thanks in advance!
source to share
TL; DR: The problem is the absence of cookies in the headers including csrftoken
.
To fix this add
opts: {
credentials: 'same-origin'
}
to initialize createNetworkInterface
as shown below.
// headers for auth
const networkInterface = createNetworkInterface({
uri: '//localhost:8000/api',
transportBatching: true,
opts: {
credentials: 'same-origin'
}
})
Long story:
I've been doing this for the past two days asking about Django and Apollo community feeds. I was desperate, so I decided to switch from Apollo to another GraphQL client. I looked at the referenced implementation at http://graphql.org/graphql-js/graphql-clients/ . It looks like this:
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.open("POST", "/graphql");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("Accept", "application/json");
xhr.onload = function () {
console.log('data returned:', xhr.response);
}
xhr.send(JSON.stringify({query: "{ hello }"}));
I threw it into my code, added a CSRF cookie to the headers and checked - it worked. I was really happy, but wanted to know why it works and the other doesn't. As written above, I found that the Apollo request was missing the Cookies Header. In fact, XMLHttpRequest
con is that you cannot send a request without adding Cookies - while the Fetch API allows you to do this. Apollo is based on the Fetch API. I checked the client documentation and it was there. :)
source to share