Peter Kellner
Peter Kellner

Reputation: 15478

ApolloGraphQL useQuery not respecting my context/headers setting

When I create my ApolloGraph client, I set a header to "xxx" with code like the following:

new ApolloClient({
    link: new HttpLink({
    uri: 'http://localhost:5000/graphql',
    credentials: 'same-origin',
    headers: {
      authorization:
          'bearer xxx',
    },
  }),

Then, I wrap my react component with the ApolloGrapql Provider so I can use useQuery in my components.

I want to pass in a new authorization header with useQuery, so I call it with code like this:

const authorization = user && user.jwtToken.length > 0 ? 'bearer ' + user.jwtToken : ' ';
console.log(authorization);
const { loading, error, data } = useQuery(q, {
  context: {
    headers: { authorization }
  }
});

My console.log shows I have a valid authentication token, but when I look at what is POST with chrome dev tools, that is what the authorization header really being sent is and it shows me xxx ignoring what I put into the useQuery context.

Any thoughts as to how to get my headers being sent to reflect what I have in my useQuery?

Upvotes: 1

Views: 2857

Answers (1)

Deniz
Deniz

Reputation: 321

You should have a mechanism for authentication, like login, logout, check token etc functions (auth.js) Then you can wrap your components in high order component wrapping an Apollo client.

Below is my working code with Strapi Backend.

import { InMemoryCache } from "apollo-cache-inmemory";
import { ApolloClient } from "apollo-client";
import { ApolloLink } from "apollo-link";

import { HttpLink } from "apollo-link-http";
import { setContext } from "@apollo/link-context";
import React from "react";
import auth from "../auth/auth";

const httpLink = new HttpLink({
  uri: process.env.REACT_APP_API_URL,
  cors: false,
});
const authLink = setContext((_, { headers }) => {
  const token = auth.getToken() || null;
  return token
    ? {
        headers: {
          ...headers,
          authorization: token ? `Bearer ${token}` : "",
        },
      }
    : null;
});

export const client = new ApolloClient({
  link: authLink.concat(httpLink),
  cache: new InMemoryCache(),
 
});

const AppProvider = ({ children }) => {
  return <ApolloProvider client={client}>{children}</ApolloProvider>;
};

auth.js for getting/setting credentials:

import { isEmpty } from "lodash";

const TOKEN_KEY = "jwtToken";
const USER_INFO = "userInfo";

const parse = JSON.parse;
const stringify = JSON.stringify;

const auth = {
 
  clear(key) {
    if (localStorage && localStorage.getItem(key)) {
      return localStorage.removeItem(key);
    }
    if (sessionStorage && sessionStorage.getItem(key)) {
      return sessionStorage.removeItem(key);
    }
    return null;
  },

  clearAppStorage() {
    if (localStorage) {
      localStorage.clear();
    }

    if (sessionStorage) {
      sessionStorage.clear();
    }
  },

  clearToken(tokenKey = TOKEN_KEY) {
    return auth.clear(tokenKey);
  },

  clearUserInfo(userInfo = USER_INFO) {
    return auth.clear(userInfo);
  },

  get(key) {
    if (localStorage && localStorage.getItem(key)) {
      return parse(localStorage.getItem(key)) || null;
    }

    if (sessionStorage && sessionStorage.getItem(key)) {
      return parse(sessionStorage.getItem(key)) || null;
    }

    return null;
  },

  getToken(tokenKey = TOKEN_KEY) {
    return auth.get(tokenKey);
  },

  getUserInfo(userInfo = USER_INFO) {
    return auth.get(userInfo);
  },
  
  set(value, key, isLocalStorage) {
    if (isEmpty(value)) {
      return null;
    }

    if (isLocalStorage && localStorage) {
      return localStorage.setItem(key, stringify(value));
    }

    if (sessionStorage) {
      return sessionStorage.setItem(key, stringify(value));
    }
    return null;
  },

  setToken(value = "", isLocalStorage = false, tokenKey = TOKEN_KEY) {
    return auth.set(value, tokenKey, isLocalStorage);
  },

  setUserInfo(value = "", isLocalStorage = false, userInfo = USER_INFO) {
    return auth.set(value, userInfo, isLocalStorage);
  },
};
export default auth;

Upvotes: 1

Related Questions