Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The best way to pass authorization header in nextJs using Apollo client? ReferenceError: localStorage is not defined

I am trying to fetch protected resource from my graphql server using nextJs and apollo client. I stored the authorization token in the client browser (localstorage) and try to read the token from apolloClient.Js file; but it throws a ReferenceError (ReferenceError: localStorage is not defined). This makes me to understand quickly that the server side was trying to reference localStorage from the backend; but fails because it is only available in the client. My question is, what is the best way to solve this issue? I am just using apollo client for the first time in my project. I have spent more than 10 hours trying to figure out the solution to this problem. I have tried so many things on web; not lucky to get the solution. Here is the code am using in apolloClient file:

import { useMemo } from 'react'
import { ApolloClient, HttpLink, InMemoryCache } from '@apollo/client'
import { concatPagination } from '@apollo/client/utilities'
import { GQL_URL } from '../utils/api'

let apolloClient

const authToken = localStorage.getItem('authToken') || '';

function createApolloClient() {
  return new ApolloClient({
    ssrMode: typeof window === 'undefined',
    link: new HttpLink({
      uri: GQL_URL, // Server URL (must be absolute)
      credentials: 'include', // Additional fetch() options like `credentials` or `headers`
      headers: {
        Authorization: `JWT ${authToken}`
      }

    }),

    
    cache: new InMemoryCache({
      typePolicies: {
        Query: {
          fields: {
            allPosts: concatPagination(),
          },
        },
      },
    }),
  })
}

export function initializeApollo(initialState = null) {
  const _apolloClient = apolloClient ?? createApolloClient()

  // If your page has Next.js data fetching methods that use Apollo Client, the initial state
  // gets hydrated here
  if (initialState) {
    _apolloClient.cache.restore(initialState)
  }
  // For SSG and SSR always create a new Apollo Client
  if (typeof window === 'undefined') return _apolloClient
  // Create the Apollo Client once in the client
  if (!apolloClient) apolloClient = _apolloClient

  return _apolloClient
}

export function useApollo(initialState) {
  const store = useMemo(() => initializeApollo(initialState), [initialState])
  return store
}
like image 648
Emeka Augustine Avatar asked Oct 27 '25 07:10

Emeka Augustine


1 Answers

I was able to solve the problem by accessing the local storage only when the window object is not 'undefined'; since it will be 'undefined' in the server side. This will work well because we don't want the server to access local storage.

import { useMemo } from 'react'
import { ApolloClient, createHttpLink, InMemoryCache } from '@apollo/client';
import { setContext } from '@apollo/client/link/context';
import { GQL_URL } from '../utils/api'

let apolloClient

function createApolloClient() {
  // Declare variable to store authToken
  let token;
   
  const httpLink = createHttpLink({
    uri: GQL_URL,
    credentials: 'include',
  });

  const authLink = setContext((_, { headers }) => {
    // get the authentication token from local storage if it exists
    if (typeof window !== 'undefined') {
      token = localStorage.getItem('authToken');
    }
    // return the headers to the context so httpLink can read them
    return {
      headers: {
        ...headers,
        Authorization: token ? `JWT ${token}` : "",
      }
    }
  });

  const client = new ApolloClient({
    ssrMode: typeof window === 'undefined',
    link: authLink.concat(httpLink),
    cache: new InMemoryCache()
  });

  return client;
}
like image 195
Emeka Augustine Avatar answered Oct 28 '25 22:10

Emeka Augustine



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!