Skip to content

Instantly share code, notes, and snippets.

@GiselaMD
Last active September 23, 2021 11:22
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save GiselaMD/c6005e28016000fa235422ff900ab8a6 to your computer and use it in GitHub Desktop.
Save GiselaMD/c6005e28016000fa235422ff900ab8a6 to your computer and use it in GitHub Desktop.
ApolloClient with token authentication and refresh token
import { HttpLink } from 'apollo-link-http';
import { ApolloClient, DefaultOptions } from 'apollo-client';
import { InMemoryCache, NormalizedCacheObject } from 'apollo-cache-inmemory';
import { ApolloLink } from 'apollo-link';
import { resolvers } from './resolvers';
import { typeDefs } from './schema/typeDefs';
import { errorLink } from './error';
import { requestLink } from './requestLink';
import customFetch from './customFetch';
const httpLink = new HttpLink({
uri: 'YOUR_GRAPHQL_API',
fetch: customFetch,
});
const link = ApolloLink.from([errorLink, requestLink, httpLink]);
const cache = new InMemoryCache({});
export const client = new ApolloClient<NormalizedCacheObject>({
cache,
link,
resolvers,
typeDefs,
});
cache.writeData({
data: {
errors: [],
},
});
import {
getAccessToken,
getRefreshToken,
setAccessToken,
} from 'helpers/accessToken';
import {refreshTokenMutation } from './utils';
const isTokenValidOrUndefined = () => {
const token = getAccessToken();
if (!token) return true;
try {
const { exp } = JwtDecode(token);
if (Date.now() >= exp * 1000) {
//token expired
console.log('TOKEN EXPIRADO');
return false;
} else {
return true;
}
} catch {
return false; //token is invalid
}
};
export default async (uri: any, options: any) => {
const initialRequest = await fetch(uri, options);
if (!isTokenValidOrUndefined()) {
const refreshToken = getRefreshToken();
const accessToken = getAccessToken();
//here you can use a REST API request or a work around to use your mutation as shown below
await fetch('YOUR_GRAPHQL_API', {
headers: {
'content-type': 'application/json',
Authorization: `bearer ${accessToken}`,
},
method: 'POST',
body: refreshTokenMutation(refreshToken),
}).then(res => {
res
.text()
.then(JSON.parse)
.then((res: any) => {
const {
data: {
refreshToken: { access_token },
},
} = res;
console.log('response', access_token);
setAccessToken(access_token);
});
});
}
return initialRequest;
};
@simplecommerce
Copy link

What code do these contain?

import {
  getAccessToken,
  getRefreshToken,
  setAccessToken,
} from 'helpers/accessToken';

@GiselaMD
Copy link
Author

GiselaMD commented Feb 20, 2020

I was just testing with a constant to save the tokens, like this:

let accessToken = '';

export const setAccessToken = (value: string) => {
  accessToken = value;
};

export const getAccessToken = () => {
  return accessToken;
};

let refreshToken = '';

export const setRefreshToken = (value: string) => {
  refreshToken = value;
};

export const getRefreshToken = () => {
  return refreshToken;
};

But I recommend to save on localStorage

@ivanrenedo
Copy link

Muchas gracias cariño por el aporte

@kannan007
Copy link

What code this file contains?

import {refreshTokenMutation } from './utils';

@GiselaMD
Copy link
Author

GiselaMD commented Aug 3, 2020

What code this file contains?

import {refreshTokenMutation } from './utils';

@kannan007

export const refreshTokenMutation = (refreshToken: string) => {
  return JSON.stringify({
    variables: { refresh_token: refreshToken },
    query: `mutation RefreshToken($refresh_token: String!){
    refreshToken(refresh_token: $refresh_token) {
      access_token
      account {
        id_account
        ds_email
        nm_account
      }
    }
  }`,
  });
};

@ozer
Copy link

ozer commented Sep 24, 2020

Oi Gisela! Nice work, thanks! a quick question, have you tested this with concurrent requests?

@RicardoBrito1938
Copy link

very nice, just a quick question, what do you have on errorLink?

@GiselaMD
Copy link
Author

very nice, just a quick question, what do you have on errorLink?

@RicardoBrito1938 This is an old project, but here's what I found:

const errorLink = onError(({ graphQLErrors, networkError }) => {
  if (graphQLErrors)
    graphQLErrors.map(({ message, locations, path }) =>
      console.log(
        `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
      )
    );
  if (networkError) console.log(`[Network error]: ${networkError}`);
});

@GiselaMD
Copy link
Author

quick

hey @ozer, I don't remember testing with concurrent requests...

@RicardoBrito1938
Copy link

very nice, just a quick question, what do you have on errorLink?

@RicardoBrito1938 This is an old project, but here's what I found:

const errorLink = onError(({ graphQLErrors, networkError }) => {
  if (graphQLErrors)
    graphQLErrors.map(({ message, locations, path }) =>
      console.log(
        `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
      )
    );
  if (networkError) console.log(`[Network error]: ${networkError}`);
});

thank you so much

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