Skip to content
This repository was archived by the owner on Apr 14, 2023. It is now read-only.
This repository was 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

Description

@boboci9

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,
  });

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions