66 lines
1.5 KiB
TypeScript
66 lines
1.5 KiB
TypeScript
import jwt_decode from "jwt-decode";
|
|
import { useEffect, useRef } from "react";
|
|
|
|
interface AppToken {
|
|
exp?: number;
|
|
iat?: number;
|
|
}
|
|
|
|
const TIME_BEFORE_REFRESH = 30 * 1000; // 30 seconds
|
|
|
|
const useTokenRefresh = (token?: string, refetch?: () => void) => {
|
|
let decoded: AppToken = {
|
|
exp: 0,
|
|
iat: 0,
|
|
};
|
|
|
|
// For some reason jwt_decode causes seemingly unrelated error in tests
|
|
// It seems like at some point undefined token is passed
|
|
// Wrapping it in try..catch and if fixes the issue
|
|
try {
|
|
if (token) {
|
|
decoded = jwt_decode(token) as AppToken;
|
|
}
|
|
} catch (e) {
|
|
console.warn(e);
|
|
}
|
|
|
|
const decodedSuccesfully = !!decoded?.iat && !!decoded?.exp;
|
|
|
|
const refreshTimeout = useRef<null | ReturnType<typeof setTimeout>>(null);
|
|
|
|
const tokenLife = ((decoded?.exp || 0) - (decoded?.iat || 0)) * 1000; // in ms
|
|
const refreshTime = tokenLife - TIME_BEFORE_REFRESH;
|
|
|
|
const setUpTimeout = () => {
|
|
if (refetch) {
|
|
refetch();
|
|
}
|
|
createTimeout();
|
|
};
|
|
|
|
const createTimeout = () => {
|
|
refreshTimeout.current = setTimeout(setUpTimeout, refreshTime);
|
|
};
|
|
|
|
const deleteTimeout = () => {
|
|
if (refreshTimeout?.current) {
|
|
clearTimeout(refreshTimeout.current);
|
|
refreshTimeout.current = null;
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
if (refetch && decodedSuccesfully) {
|
|
createTimeout();
|
|
}
|
|
|
|
return () => {
|
|
if (!!refetch && decodedSuccesfully) {
|
|
deleteTimeout();
|
|
}
|
|
};
|
|
}, [token]);
|
|
};
|
|
|
|
export default useTokenRefresh;
|