Skip to content
This repository has been archived by the owner on Apr 14, 2023. It is now read-only.

setContext in the errorLink is not updating the global header token #1320

Open
boboci9 opened this issue Jul 12, 2020 · 0 comments
Open

setContext in the errorLink is not updating the global header token #1320

boboci9 opened this issue Jul 12, 2020 · 0 comments

Comments

@boboci9
Copy link

boboci9 commented Jul 12, 2020

Hi,

I am having an issue with updating the token in the headers after I call a cognito refreshToken operation.
Can anyone help me what am I going wrong because this should work like this for sure.
Thank you for everyone's help in advance.

Expected Behavior
Expected behavior would be that after the refresh token call is executed (1 hour after the initial login) we get the new token from cognito (this part works) and we updated the global header so all future calls have the new token in their header.

Actual Behavior
Actual behavior is that first the token is registered globally but then 1 hour later when it expires and I call refreshtoken the global header doesn't get updated with the new setContext call but instead every graphql call from this point on first returns a 401 error then it goes into the refreshtoken algorithm and executes the call with the newly calculated token but this doesn't get stored globally (although this token again would be valid for 1 hour) instead next call again returns the 401 error and so on.
Although the operation which failed get recalled with the newly calculated token due to the forward operation but this way after the first hour passes every call get's called double due to the first 401 instead of a global token update.

A simple reproduction

 const token = localStorage.getItem("token");
  const cache = new InMemoryCache();

  const httpLink = new HttpLink({
    uri: `${config.endpoint}/graphql`,
  });

  const authLink = setContext((_, { headers }) => {
    return {
      headers: {
        ...headers,
        authorization: token ? `Bearer ${token}` : '',
      },
    };
  });

  const errorLink = onError(({ graphQLErrors, networkError, operation, forward }) => {
    console.log("graphQLErrors, networkError", graphQLErrors, networkError, networkError?.statusCode);
   
    // User access token has expired
    if (networkError && networkError.statusCode === 401) {
      // Let's refresh token 
      return new Observable(async observer => {
        const cognitoUser = await Auth.currentAuthenticatedUser();
        const { refreshToken } = await Auth.currentSession();
        if (refreshToken && token) {
          cognitoUser.refreshSession(refreshToken, (e, session) => {
            if (e) {
              console.error('Unable to refresh session', e);

              observer.error(e);
              return
            }
            console.log(`%c 👌 REFRESH COGNITO TOKEN, error ${e}`, "color:blue");
            console.log("session", session); // the new token here is valid for an other 1 hour so I would like to update it globally

            const token = session.idToken.jwtToken;
            localStorage.setItem("token", token);
            operation.setContext(context => ({
              ...context,
              headers: {
                ...context.headers,
                authorization: token ? `Bearer ${token}` : '',
              }
            }));

            const subscriber = {
              next: observer.next.bind(observer),
              error: observer.error.bind(observer),
              complete: observer.complete.bind(observer)
            };
            forward(operation).subscribe(subscriber);

          })
        }
      });

    }

  });

  const link = ApolloLink.from([
    authLink,
    errorLink,
    httpLink
  ]);

  return new ApolloClient({
    link,
    cache,
  });
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant