Nischal Singh
Nischal Singh

Reputation: 1

setContext not setting the token call before API call when token expires

Token API should get called before the GraphQL API but it's being called at the same time

I am fetching the headers inside setContext Inside commonAuthHeaders I am calling the API to get refresh token

const authLink = setContext((_, { headers }) => {
  return new Promise( async (resolve, reject) => {
    // get the authentication headers
    const updatedHeaders = await commonAuthHeaders(headers)
    resolve ({
      headers: updatedHeaders
    }
    )
  });
});


export const client = new ApolloClient({
  link: from([authLink, errorLink , httpLink]),
  cache,
  connectToDevTools: process.env.NODE_ENV !== "production",
  defaultOptions: {
    watchQuery: {
      fetchPolicy: "network-only",
      nextFetchPolicy: "network-only",
    },
  },
});



export async function commonAuthHeaders(headers) {
    const supportedLoginModes = ["autodesk", "google"]

    const logInMode = getCookie("__login_mode");
    let access_token = getCookie("__bauhub_token");
    const refresh_token = getCookie("__bauhub_refresh_token")
    const lang = getCookie("__bauhub_lang");
    const currentOrgId = getCookie("__current_organization");
    const pluginType = getCookie("pluginType")

    const newHeaders = {
        ...headers,
        "Apollo-Require-Preflight": true,
    };

    if (lang) newHeaders["Accept-Language"] = lang;

    if (supportedLoginModes.includes(logInMode)) {

        if (logInMode === "autodesk" && !access_token && refresh_token) {
            access_token = await refreshAutodeskAccessToken()
        }

        if (logInMode === "google" && !access_token) {
            access_token = await getFirebaseToken()
        }

        if (access_token && currentOrgId) newHeaders.organizationId = currentOrgId;

        if (logInMode && access_token) newHeaders.logInMode = logInMode;

        if (pluginType) newHeaders.pluginType = pluginType

        newHeaders.authorization = access_token ? `Bearer ${access_token}` : "";
        return newHeaders
    } else {
        return headers
    }
}

First token API should get called and then after getting the token the next GraphQL call should get placed.

Upvotes: 0

Views: 20

Answers (1)

Anton
Anton

Reputation: 310

I also couldn't do it via setContext, but I did it using the ApolloLink interface:

import {ApolloLink, Observable} from '@apollo/client';

const getToken = async () => {
  let token: string | undefined;
  
  // await get token
  
  return token
}

const authLink = new ApolloLink((operation, forward) => {
  return new Observable((subscriberObserver) => {
    getToken()
      .then(
        (token) => {
          if (subscriberObserver.closed) return;
          if (token) {
            operation.setContext(({headers = {}}) => ({
              ...headers,
              Authorization: `Bearer ${token}`
            }));
          }
          subscriberObserver.complete();
        },
        (err) => subscriberObserver.error(err)
      );
  })
    .flatMap(() => forward(operation));
});

Upvotes: 0

Related Questions