Open sk8Guerra opened 4 years ago
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;
@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?
The example in https://github.com/newsiberian/apollo-link-token-refresh/issues/29#issuecomment-700336766 has a security issue. Storing JWT tokens in localStorage can make a public app vulnerable to credential theft by XSS.
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:
how should I extract it?