Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How exactly shoud I get the new acces token in handleResponse function? #29

Open
sk8Guerra opened this issue Jul 24, 2020 · 3 comments
Open

Comments

@sk8Guerra
Copy link

I'm trying to extract the new token that is generated when the old one has expired. But when I try to access it, it is undefined:

handleResponse: (operation, accessTokenField) => response => {
    console.log({ ac: response.refreshToken }); // -> {ac: undefined}
},

how should I extract it?

@sturoid
Copy link

sturoid commented Sep 28, 2020

Here is my implementation that has been working great. Hopefully it helps. This is how I create the apollo "client". I then pass that to ApolloProvider.

import jwtDecode from 'jwt-decode';
import { ApolloClient, InMemoryCache, HttpLink, ApolloLink } from '@apollo/client';
import { setContext } from '@apollo/client/link/context';
import { onError } from '@apollo/client/link/error';
import { TokenRefreshLink } from 'apollo-link-token-refresh';

const httpLink = new HttpLink({ uri: `${process.env.REACT_APP_API_URL}/graphql` });

const authLink = setContext((_, { headers }) => {
  // Get the authentication token from local storage if it exists
  const token = localStorage.getItem('sict');
  // Return the headers to the context so httpLink can read them
  return {
    headers: {
      ...headers,
      authorization: token ? `Bearer ${token}` : ''
    }
  };
});

const refreshTokenLink = new TokenRefreshLink({
  accessTokenField: 'tokens',
  isTokenValidOrUndefined: () => {
    const token = localStorage.getItem('sict');

    if (!token) return true;

    try {
      const { exp } = jwtDecode(token);
      const expires = new Date(exp * 1000);
      if (Date.now() >= expires) return false;
      return true;
    } catch {
      return false;
    }
  },
  fetchAccessToken: () => {
    return fetch(`${process.env.REACT_APP_API_URL}/refresh_token`, {
      method: 'GET',
      headers: {
        authorization: `Bearer ${localStorage.getItem('sict')}`,
        sicrt: localStorage.getItem('sicrt')
      }
    });
  },
  handleFetch: (newTokens) => {
    const { token, refreshToken } = newTokens;

    if (!token || !refreshToken) {
      localStorage.removeItem('sict');
      return localStorage.removeItem('sicrt');
    }

    localStorage.setItem('sict', token);
    return localStorage.setItem('sicrt', refreshToken);
  },
  handleError: () => {
    localStorage.removeItem('sict');
    localStorage.removeItem('sicrt');
    return window.location.reload();
  }
});

const client = new ApolloClient({
  link: ApolloLink.from([
    refreshTokenLink,
    // eslint-disable-next-line
    onError(({ graphQLErrors, networkError }) => {
      // TODO: Custom error handler here.
      // eslint-disable-next-line
      // console.log('apollo.js onError graphQLErrors: ', graphQLErrors);
      // eslint-disable-next-line
      // console.log('apollo.js onError networkError: ', networkError);
    }),
    authLink,
    httpLink
  ]),
  cache: new InMemoryCache({})
});

export default client;

@themathiou
Copy link

themathiou commented Jul 28, 2021

@sturoid what url do you use for the refresh_token?
what is ${process.env.REACT_APP_API_URL}/refresh_token in your case?
Do you have a custom implementation for refresh token? What server do you use?

@MarttiR
Copy link

MarttiR commented Mar 3, 2022

The example in #29 (comment) has a security issue. Storing JWT tokens in localStorage can make a public app vulnerable to credential theft by XSS.

See: https://auth0.com/docs/secure/security-guidance/data-security/token-storage#don-t-store-tokens-in-local-storage

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants