1

I am trying to create a flow for refreshing JWT token when a request fails because of an invalid token. My flow is as follows:

  1. make the request with authentication header
  2. catch the failed request because of invalid token
  3. make an API call to refresh token and store it in local storage
  4. set the new token in the authentication header
  5. retry the old request with new authentication header

But step 4 of the flow is not working. I am able to fetch new token but I am unable to set it in the authorization header. So the old request is sent with the old token rather than a new one.

If anyone can figure out why it's happening. it would be of great help.

Here's the function that executes the refresh token mutation.

public graphqlMutation(mutation:any, variable?:any){
return this.apollo.mutate({ mutation:mutation, variables:variable});
}

public getNewToken(refresh_token:any){
const token_variable = {"refresh_token": refresh_token}
this.graphqlMutation(REFRESH_TOKEN_MUTATION, token_variable)
.subscribe(
  (result:any) =>{
    const token = result.data.refreshToken.token;
    const refresh_token = result.data.refreshToken.refreshToken;
    localStorage.setItem('auth_token', token);
    localStorage.setItem('refresh_token', refresh_token);
  }
)
}

Here's the HttpLink terminating link

const http = this.httpLink.create({
  uri: 'http://127.0.0.1:8000/graphql/',
  withCredentials: true
});

Here's the headerMiddleware to set the authentication header.

const headerMiddleware = new ApolloLink((operation, forward) => {
const token = 'JWT '+ localStorage.getItem('auth_token');
operation.setContext({
  headers: {
    'Accept': 'charset=utf-8',
    'Authorization': token ? token : ''
  }
});
return forward(operation);
});

Here's the onError function which catches the failed request, gets the new token, sets the authorization header, and retries the old request.

const graphqlError = onError(({ graphQLErrors, operation, forward }) =>{
if (graphQLErrors){
  for (let err of graphQLErrors){
    switch (err.message) {
      case 'Signature has expired':
        this.getNewToken(localStorage.getItem('refresh_token'));
        const oldHeaders = operation.getContext().headers;
        operation.setContext({
          headers: {
            ...oldHeaders,
            Authorization: 'JWT ' + localStorage.getItem('auth_token')
          }
        });
        return forward(operation);
    }
  }
}

});

Here's the Link

const Link = ApolloLink.from([graphqlError, headerMiddleware, http]);

And here's my package.json file

"apollo-angular": "^1.10.0",
"apollo-angular-link-http": "^1.11.0",
"apollo-cache-inmemory": "^1.6.6",
"apollo-client": "^2.6.10",
"apollo-link-context": "^1.0.20",
"apollo-link-error": "^1.1.13",
"apollo-link-ws": "^1.0.20",
"graphql": "^15.3.0",
"graphql-tag": "^2.10.4",

And thank you in advance for helping!!

0 Answers0