Last active
September 23, 2021 11:22
-
-
Save GiselaMD/c6005e28016000fa235422ff900ab8a6 to your computer and use it in GitHub Desktop.
ApolloClient with token authentication and refresh token
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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: [], | |
}, | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { ApolloLink, Observable } from 'apollo-link'; | |
import { getAccessToken } from 'helpers/accessToken'; | |
export const requestLink = new ApolloLink( | |
(operation, forward) => | |
new Observable(observer => { | |
let handle: any; | |
Promise.resolve(operation) | |
.then(operation => { | |
const accessToken = getAccessToken(); | |
if (accessToken) { | |
operation.setContext({ | |
headers: { | |
Authorization: `bearer ${accessToken}`, | |
}, | |
}); | |
} | |
}) | |
.then(() => { | |
handle = forward(operation).subscribe({ | |
next: observer.next.bind(observer), | |
error: observer.error.bind(observer), | |
complete: observer.complete.bind(observer), | |
}); | |
}) | |
.catch(observer.error.bind(observer)); | |
return () => { | |
if (handle) handle.unsubscribe(); | |
}; | |
}) | |
); |
Oi Gisela! Nice work, thanks! a quick question, have you tested this with concurrent requests?
very nice, just a quick question, what do you have on errorLink?
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}`);
});
quick
hey @ozer, I don't remember testing with concurrent requests...
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
@kannan007