Apollo-client: docs: Add apollo-boost authentication headers example

Created on 23 Aug 2019  路  19Comments  路  Source: apollographql/apollo-client

Currently docs have a bit outdated Apollo Client example with a footnote that this won't work with newer apollo-boost package. It would be nice to add a proper example like that one to the docs.

Most helpful comment

@jordanmmck not sure what exactly can go wrong but here is my working code:

const apolloClient = new ApolloClient({
  uri: 'https://graphql.anilist.co',
  request: (operation) => {
    const token = localStorage.getItem('token')
    operation.setContext({
      headers: {
        authorization: token ? `Bearer ${token}` : ''
      }
    })
  }
})

Seems like no one is gonna update docs so I think I will send PR in few days myself.

All 19 comments

@IAmVisco do you know of any working examples anywhere else? I'm just trying to get a basic query working to an API that requires a token in the header. Should the second snippet in the comment you linked work? I've tried everything in there, and a million other ways, and can't get a query to work.

@jordanmmck not sure what exactly can go wrong but here is my working code:

const apolloClient = new ApolloClient({
  uri: 'https://graphql.anilist.co',
  request: (operation) => {
    const token = localStorage.getItem('token')
    operation.setContext({
      headers: {
        authorization: token ? `Bearer ${token}` : ''
      }
    })
  }
})

Seems like no one is gonna update docs so I think I will send PR in few days myself.

https://github.com/apollographql/apollo-client/issues/5229#issuecomment-526722226
Which version of apollo-boost are you using?
I am using 0.4.4 but it doesn't allow uri parameter directly instead asks for Link instance.
Also I am new to nodejs/apollo and spent whole day figuring out how to add http headers.
Thank you.

@sonugk I can't check right now because I am way from PC but make sure you are importing correct ApolloClient. I am doing it like that import ApolloClient from 'apollo-boost'. Also since you mentioned node.js, my example is for the client. If you are writing server side part I doubt I can help you with that one.

@IAmVisco Thank you for the reply. Sorry I may have confused you with NodeJs but I am using it in Expo managed react-native client app below is my example, while the headers in HttpLink works fine but it is static one time assignment unlike request for each Http Request. The request: (operation) => {} part doesnt seem to have any effect on Http headers. Below is partial extract of my code.

import React from 'react';
import { Image } from 'react-native';
import { AppLoading } from 'expo';
import { ApolloClient,InMemoryCache,HttpLink } from 'apollo-boost';
import { ApolloProvider } from '@apollo/react-hooks';
const cache = new InMemoryCache();

const client = new ApolloClient({
  cache,
  link: new HttpLink({
      uri: 'http://localhost:4000',
      headers:{
        test: Date.now()
      },
    //uri: 'https://48p1r2roz4.sse.codesandbox.io',
  }),

  request: (operation) => {
    operation.setContext({
      headers: {
        //authorization: token ? `Bearer ${token}` : ''
        test2: 'test2'
      }
    })
  }
});

@sonugk despite the fact that the same client is exported in the lib (see here) you somehow ended up using old version of client that still has cache and link options (see new API) here. Check that you are importing correct client and library, I doubt I can help you with more.

@IAmVisco I found the solution and it was very simple, as I was importing named ApolloClient export I just had to import the default export i.e.

import ApolloClient,{InMemoryCache, HttpLink } from 'apollo-boost';

instead of

import {ApolloClient, InMemoryCache, HttpLink } from 'apollo-boost';

The named export is old apollo client they have added for backward compatibility.
And now I am able to pass fresh header value on each request.
Solution post.
-Thank you

@IAmVisco do you know of any working examples anywhere else? I'm just trying to get a basic query working to an API that requires a token in the header. Should the second snippet in the comment you linked work? I've tried everything in there, and a million other ways, and can't get a query to work.

@jordanmmck
I am putting this partial example to get rough idea please note the default import of ApolloClient from apollo-boost package

import ApolloClient,{InMemoryCache, HttpLink } from 'apollo-boost';
import { ApolloProvider } from '@apollo/react-hooks';

const client = new ApolloClient({
  uri: 'http://localhost:4000',
  request: operation => {
    operation.setContext({
      headers: {
        authorization: 'Bearer '+Date.now(), //Your Auth token extraction logic
      },
    });
  },
})

Check this snac for example(non-tested)

@sonugk I was expecting that but it's kinda weird, index.ts exports the same client object, I checked and sent you the link. Welp, good that you made it work.

Here is what worked on my end

  import {
    ApolloClient,
    InMemoryCache,
    HttpLink,
    ApolloLink
  } from 'apollo-boost';
  const client = new ApolloClient({
    link: new ApolloLink((operation, forward) => {
      operation.setContext({
        headers: {
          authorization: 'Bearer '+Date.now(), //Your Auth token extraction logic
        }
      });
      return forward(operation);
    }).concat(
      new HttpLink({
        uri: 'http://localhost:8080/v1/graphql', // Server URL
      })
    ),
    cache: new InMemoryCache()
  });

@geocine I keep getting `Error: Network error: undefined is not a function (near '...inner.subscribe...'

```

const client = new ApolloClient({
link: new ApolloLink(async(operation, forward) => {
const token = await AsyncStorage.getItem('accessToken')// async function
operation.setContext({
headers: {
authorization: token ? token : ''
}
});
return forward(operation);
}).concat(
new HttpLink({
uri: 'MY SERVER URL', // Server URL
})
),
cache: new InMemoryCache()
});
```

https://github.com/apollographql/apollo-client/issues/5229#issuecomment-615195181
@yilakt You need to add URL of your GraphQL API server in below code
Original code
new HttpLink({ uri: 'MY SERVER URL', })

Modify it to something like below if your are on development server e.g.
new HttpLink({ uri: 'http://localhost:4000', })

@sonugk I had my actual remote server url on there. the MY SERVER URL is just a placeholder I put for the sake of the question.

I'm still getting this error.

@yilakt Hi, I was also getting "inner.subscribe..." error, removing node_modules and reinstalling them helped

Related: #6231

if one does not want an empty authorization to be in the header

import ApolloClient from 'apollo-boost';

const client = new ApolloClient({
  //init param for comm with graphql
  uri: 'https://api.alfredetnestor.com',
  credentials: 'same-origin',
  cache: new InMemoryCache(),
  request: (operation) => {
    const token = localStorage.getItem('token')
    operation.setContext({
      headers: token ? {
        authorization: `Bearer ${token}`
      } : {}
    })
  },
  onError: ({ networkError, graphQLErrors }) => {
    if (graphQLErrors) {
      console.warn('graphQLErrors', graphQLErrors)
    }
    if (networkError) {
      console.warn('networkError', networkError)
    }
  },
});

Okay, but how do we do this from the server in SSR?!

Okay, but how do we do this from the server in SSR?!

any solution here?

Okay, but how do we do this from the server in SSR?!

Same question. Keep getting:

(node:32061) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
Was this page helpful?
0 / 5 - 0 ratings