Invalid Auth Token with Rails, Graphql, Apollo Client

瘦欲@ 提交于 2019-12-21 02:30:54

问题


I am trying to get a basic Rails, Graphql, Apollo-Client setup working but having trouble with 422 errors 'invalid auth token' on the rails side.

Does my use of apollo look wrong?

It is a Rails 5 app with graphql gem and apollo client.

const csrfToken = document.getElementsByName('csrf-token')[0].content
const client = new ApolloClient({
  networkInterface: createNetworkInterface({
    uri: '/graphql',
    credentials: 'same-origin',
    headers: {
      'X-CSRF-Token': csrfToken
    }
  }),
});
client.query({
query: gql`
    query Camillo2 {
      user {
        id
        email
        created_at
      }
    }
  `,
})
.then(data => console.log(data))
.catch(error => console.error(error));  

Rails log:

Started POST "/graphql" for ::1 at 2017-03-10 08:51:58 -0800
Processing by GraphqlController#create as */*
Parameters: {"query"=>"query Camillo2 {\n  user {\n    id\n    email\n    created_at\n    __typename\n  }\n}\n", "operationName"=>"Camillo2", "graphql"=>{"query"=>"query Camillo2 {\n  user {\n    id\n    email\n    created_at\n    __typename\n  }\n}\n", "operationName"=>"Camillo2"}}
Can't verify CSRF token authenticity.
Completed 422 Unprocessable Entity in 2ms (ActiveRecord: 0.0ms)

回答1:


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()
});



回答2:


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.)




回答3:


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




回答4:


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 }
    })
  },
})



回答5:


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




回答6:


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,
});


来源:https://stackoverflow.com/questions/42723989/invalid-auth-token-with-rails-graphql-apollo-client

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