Invalid Auth Token with Rails, Graphql, Apollo Client

后端 未结 7 1644
北海茫月
北海茫月 2021-02-09 13:06

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 apoll

相关标签:
7条回答
  • 2021-02-09 13:42

    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

    0 讨论(0)
  • 2021-02-09 13:50

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

    0 讨论(0)
  • 2021-02-09 13:51

    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()
    });
    
    0 讨论(0)
  • 2021-02-09 13:54

    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 }
        })
      },
    })
    
    0 讨论(0)
  • 2021-02-09 13:54

    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

    0 讨论(0)
  • 2021-02-09 13:57

    Was running into a 422 error myself on the /graphql endpoint when firing Apollo query client side (React in my case).

    There are 2 major things that could be happening.

    1.) Make triple, quadruple, quintuple... sure that you have not made any typos. the Apollo client config can get quite terse, so just be super prudent about the token setup code you write.

    // Get Token from Meta Tags on Application.html.erb
    
    const getToken = () => document.querySelector('meta[name="csrf-token"]').getAttribute('content');
    
    const token = getToken();
    
    // MiddleWare Operationt that sets the CSRF token on requests to protect from forgery
    const setTokenForOperation = async operation =>
      operation.setContext({
        headers: {
          'X-CSRF-Token': token,
        },
      });
    
    // Link With CSRF Token
    const createLinkWithToken = () =>
      new ApolloLink(
        (operation, forward) =>
          new Observable(observer => {
            let handle;
            Promise.resolve(operation)
              .then(setTokenForOperation)
              .then(() => {
                handle = forward(operation).subscribe({
                  next: observer.next.bind(observer),
                  error: observer.error.bind(observer),
                  complete: observer.complete.bind(observer),
                });
              })
              .catch(observer.error.bind(observer));
    
            return () => {
              if (handle) handle.unsubscribe();
            };
          })
      );
    
    ... other apollo-link middleware stuff like error logging etc
    
    // Tell Apollo client about the endpoint for making queries: (HTTP LINK) - this was default endpoint added by graphql install
    
    
    
    const createHttpLink = () =>
      new HttpLink({
        uri: '/graphql',
        credentials: 'include',
      });
    
    // and finally put it all together 
    
    export const createClient = (cache, requestLink) =>
      new ApolloClient({
        link: ApolloLink.from([createErrorLink(), createLinkWithToken(), createHttpLink()]),
        cache,
      });
    
    

    2.) Protect from Forgery Session fail on 3rd party authentication strategies (ie Devise + CanCan or w/e )

    If your apollo middleware patterns are kosher, then it could be that your authentication strategy might be impeding the request.

    for example I am using devise + cancan, which was also causing some seeming random 422s which was easily solved with some research (see this article https://blog.bigbinary.com/2016/04/06/rails-5-default-protect-from-forgery-prepend-false.html)

    long story short on this part, you may need to have application controller (especially if you are upgrading from a legacy version) load and authorize your current user/resource AFTER the protect from forgery setup (more deets on the article referenced)

    class ApplicationController < ActionController::Base
    protect_from_forgery prepend: true, with: :exception
    
    ... 
    before_action .. whatever else you have going on hereafter
    
    

    Hope this helps.

    Cheers

    0 讨论(0)
提交回复
热议问题