Invalid Auth Token with Rails, Graphql, Apollo Client

好久不见. 提交于 2019-12-03 08:03:38

Since Apollo 2.0 and according to

https://github.com/apollographql/apollo-client/blob/master/Upgrade.md

Just do this way

const csrfToken = document.querySelector('meta[name=csrf-token]').getAttribute('content');
const client = new ApolloClient({
    link: new HttpLink({
        credentials: 'same-origin',
        headers: {
            'X-CSRF-Token': csrfToken
        }
    }),
    cache: new InMemoryCache()
});

I was experimenting with Apollo on Rails the other day, here's the configuration that worked for me:

var RailsNetworkInterface = apollo.createNetworkInterface('/graphql', {
  credentials: 'same-origin',
  headers: {
    'X-CSRF-Token': $("meta[name=csrf-token]").attr("content"),
  }
});

var client = new apollo.ApolloClient({networkInterface: RailsNetworkInterface})

client.query({ query: gql`{ event(id: 7) { name } }`})

But, it seems like yours would work just as well!

Can you confirm that the proper token is being sent to the server? For example, if you open the network tab of Chrome devtools, then make a query, can you see the X-CSRF-Token in the "Request Headers" section?

Also, it's possible that Rails is updating the CSRF token in the DOM, but the NetworkInterface keeps the old, stale CSRF token. Can you confirm that the token in the "Request Headers" section matches the current value in the <meta> tag? (I was surprised that I didn't encounter this problem myself, using Turbolinks Classic.)

To clarify some of the above answers, since one of the users noted that passing in the uri as a first argument to createNetworkInterface works but logs a deprecation message in the console: you have to pass in options like "credentials" and "headers" in as properties of an options object like so:

const networkInterface = createNetworkInterface({
  uri: '/graphql',
  opts: {
    credentials: 'same-origin',
    headers: {
      'X-CSRF-TOKEN': $('meta[name=csrf-token]').attr('content'),
    },
  },
});

See the second example under Fetch in the docs: http://dev.apollodata.com/core/network.html

Using apollo-boost, it's a little different.

import ApolloClient from 'apollo-boost'

const client = new ApolloClient({
  fetchOptions: {
    credentials: 'same-origin',
  },
  request: (operation) => {
    const csrfToken = document.querySelector('meta[name=csrf-token]').getAttribute('content')
    operation.setContext({
      headers: { "X-CSRF-Token": csrfToken }
    })
  },
})

This worked for me (I'm using react_on_rails):

import { ApolloClient, createNetworkInterface } from 'react-apollo';
import ReactOnRails from 'react-on-rails';

const networkInterface = createNetworkInterface({
  uri: '/graphql',
  opts: {
    credentials: 'same-origin'
  }
});
networkInterface.use([{
  applyMiddleware(req, next) {
    if (!req.options.headers) {
      req.options.headers = {
        "X-CSRF-Token": ReactOnRails.authenticityToken()
      }
    }
    next();
  }
}]);

const client = new ApolloClient({
  networkInterface
});

export default client

I was missing opts: { credentials: 'same-origin' } , resulting in the same error: Can't verify CSRF token authenticity. Completed 422 Unprocessable Entity

this one works fine for me.

const csrfToken = document.querySelector('meta[name=csrf-token]').getAttribute('content');
const link = createHttpLink({
  uri: '/graphql',
  credentials: 'same-origin',
  headers: {
    'X-CSRF-Token': csrfToken
  }
});

const client = new ApolloClient({
  cache: new InMemoryCache(),
  link,
});
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!