How to wait for JWT to be set before initial render

Hello, I am using the standard apollo-client setup with the micrososft authentication library MSAL.

Once someone is logged in, the authorization token is not set before the first render, so the useQuery in my app.js does not return data.

So upon login, the bearer token is set as undefined, however the JWT is in session storage. When immediately refreshing the page, the useQuery works, as it picks up the JWT.

const httpLink = createHttpLink({
  uri: "http://localhost:5000/graphql",
});

const authLink = setContext(async (_, { headers }) => {
  // get the authentication token from local storage if it exists
  const token = await returnToken(
    msalInstance,
    protectedResources.apiHello.scopes
  );

  // return the headers to the context so httpLink can read them
  return {
    headers: {
      ...headers,
      authorization: `Bearer ${token}`,
    },
  };
});


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


// MSAL function to get access token

async function returnToken(msalInstance: any, scope: any) {
  const accounts = msalInstance.getAllAccounts();
  const account = accounts[0];

  const accessTokenRequest = {
    scopes: scope,
    account: account,
  };

  if (account) {
    let resp = await msalInstance
      .acquireTokenSilent(accessTokenRequest)
      .then(function (accessTokenResponse: any) {
        // Acquire token silent success
        let accessToken = accessTokenResponse.accessToken;
        return accessToken;
      })
      .catch(function (error: any) {
        console.log(error);
      });
    return resp;
  }
}

It ended up that the setup above was fine. Within the component queries, I had to ensure that the account, and session tokens were set when being redirected back from the authentication flow prior to sending the query for info.

For the Microsoft MSAL platform, I did the below which uses the user context from the MSAL provider.

Future readers, I haven’t thoroughly tested the solution at time of writing.

const UserInfo: React.FC = () => {
  const { instance, accounts, inProgress } = useMsal();
  const account = useAccount(accounts[0] || {});

  const [loadingQuery, { loading, error, data }] = useLazyQuery(RETURN_USER);

  useEffect(() => {
    if (account) {
      loadingQuery();
    }
  }, [account, instance]);
...