问题
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