I do something like this on the the client side, from within a Saga. I don't use it for direct access to Firebase - just to allow the user to authenticate to a Node server. The Node server uses the token sent from the same front end to authenticate to Firebase through Firebase admin, and the user doesn't have to authenticate to two different services. You might have to approach it differently depending on your use case (Especially this question: is there an active Firebase client device?)
1. Client side
2. It just needs the currentUser object
3. You do need a way to run a background process
while (true) {
let token;
try {
token = yield currentUser.getIdToken(true);
} catch (error) {
if (error.code === "auth/network-request-failed") {
console.log("Unable to refresh login token due to connectivity at: ", (new Date()).toLocaleString());
console.log("Retrying in one minute.");
yield delay(1000 * 60);
continue;
} else {
const retryMinutes = (2 ** (Math.min(retryCounter, 5))) // Cap it at 32 minutes
retryCounter = retryCounter + 1;
console.log("Error refreshing login token at: ", (new Date()).toLocaleString())
console.log(`Retrying in ${retryMinutes} minute(s).`)
yield delay(1000 * retryMinutes * 60);
continue;
}
}
// Reset the retry counter
retryCounter = 0;
const jwt = jwtDecode(token);
const expires_at = jwt.exp;
const issued_at_time = jwt.iat;
const delay_ms = (expires_at - issued_at_time) * 900;
// Put the fresh token where it's needed:
yield put(setUserToken(token));
yield delay(delay_ms);
}