Franek Madej
Franek Madej

Reputation: 1179

CSRF token gets passed in the header when performing POST

I'm setting up VueJS SPA on top of Django. I have Graphene endpoint running on /api and queries in graphiql run fine. I have set up frontend and I'm using Apollo Client to query 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 the 'X-CSRFToken' header with value provided by Cookies. Screenshot below: Request Headers

Unfortunately Django forbids access (error 403) with message: "CSRF cookie missing".

I have searched through the web but can't find anything related.

Thanks in advance!

Upvotes: 4

Views: 2174

Answers (1)

Franek Madej
Franek Madej

Reputation: 1179

TL;DR: The issue is lack of the cookies in the headers, including csrftoken.

To fix this, append

  opts: {
    credentials: 'same-origin'
  }

to the createNetworkInterface initialization, like below.

// headers for auth
const networkInterface = createNetworkInterface({
  uri: '//localhost:8000/api',
  transportBatching: true,
  opts: {
    credentials: 'same-origin'
  }
})

Long story:

I've been fiddling with this for the last two days, asking around on Django and Apollo community channels. I was really desperate, so I considered switching from Apollo to other GraphQL client. I looked at the reference implementation over 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 have thrown it into my code, added the CSRF token cookie into headers and checked - it worked. I was really happy, but wanted to know why does one work, while other does not. As written above, I have discovered that the Apollo's request lacked Cookies Header. Actually XMLHttpRequest con is that you can't send request without adding Cookies - while Fetch API allows you to do so. And Apollo's based on Fetch API. I checked the documentation of the client and it was there. :)

Upvotes: 4

Related Questions