Currently, when I authenticate a user with firebase, I store their auth token in localStorage
to be used later to connect to my backend like so:
const httpLink = new HttpLink({uri: 'http://localhost:9000/graphql'})
const authMiddleware = new ApolloLink((operation, forward) => {
// add the authorization token to the headers
const token = localStorage.getItem(AUTH_TOKEN) || null
operation.setContext({
headers: {
authorization: token ? `Bearer ${token}` : ''
}
})
return forward(operation)
})
const authAfterware = onError(({networkError}) => {
if (networkError.statusCode === 401) AuthService.signout()
})
function createApolloClient() {
return new ApolloClient({
cache: new InMemoryCache(),
link: authMiddleware.concat(authAfterware).concat(httpLink)
})
}
My problem with this is that I have no way to refresh the token once it expires. So I tried to use the following to set the authorization token for apollo:
const httpLink = new HttpLink({uri: 'http://localhost:9000/graphql'})
const asyncAuthLink = setContext(
() => {
return new Promise((success, reject) => {
firebase.auth().currentUser.getToken().then(token => {
success({
headers: {
authorization: token ? `Bearer ${token}` : ''
}
})
}).catch(error => {
reject(error)
})
})
}
)
const authAfterware = onError(({networkError}) => {
if (networkError.statusCode === 401) AuthService.signout()
})
function createApolloClient() {
return new ApolloClient({
cache: new InMemoryCache(),
link: asyncAuthLink.concat(authAfterware.concat(httpLink))
})
}
This works when the user first authenticates, but once the user refreshes the page, firebase is no longer initialized when my graphql queries are sent to my backend, so the token is not sent with it. Is there a way I can asynchronously wait for firebase.auth().currentUser
so this will work? Or is there another approach I should take entirely? As far as I know (100% sure) currentUser.getIdToken
only makes a network call if the current token is no longer valid. I think this is acceptable as in cases where the token is not valid, the backend can't respond anyway, so I will need to wait for a token refresh to continue.
Some other ideas I thought of:
- Continue to use
localStorage
to store the auth token, refresh it inauthAfterware
if my backend sends a 401 response back and retry the request. - Set a delay on getting the auth token (not desirable)
- Any other ideas?
Thanks!