diff --git a/package-lock.json b/package-lock.json index 214b506..b918c04 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9054,6 +9054,11 @@ "object.assign": "^4.1.0" } }, + "jwt-decode": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", + "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==" + }, "killable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", diff --git a/package.json b/package.json index 71b539c..8b496df 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "@testing-library/user-event": "^7.2.1", "clsx": "^1.1.1", "history": "^5.0.0", + "jwt-decode": "^3.1.2", "material-table": "^1.63.1", "react": "^16.13.1", "react-cookie": "^4.0.3", diff --git a/src/components/AuthProvider/AuthProvider.js b/src/components/AuthProvider/AuthProvider.js index ae5b6fa..6643208 100644 --- a/src/components/AuthProvider/AuthProvider.js +++ b/src/components/AuthProvider/AuthProvider.js @@ -1,6 +1,7 @@ import React, { useState, createContext, useContext, useEffect } from "react"; import { useCookies } from "react-cookie"; import { refresh } from "../../auth/"; +import decodeJWT from "jwt-decode"; @@ -22,24 +23,46 @@ export default function AuthProvider({ children }) { const [cookies] = useCookies(); + async function tryRefresh(csrf_refresh_token){ + if (csrf_refresh_token === undefined){ + return false; + } + + const new_access_token = await refresh(csrf_refresh_token); + if (!new_access_token){ + console.error("Failed to refresh access token.") + return false; + } + + setToken(new_access_token); + setLoggedIn(true); + } + + // Attempt to refresh token on page load useEffect( _ => { - async function tryRefresh(csrf_refresh_token){ - console.log("CSRF Token", csrf_refresh_token) - if (csrf_refresh_token === undefined){ - return false; - } - - let new_access_token = await refresh(csrf_refresh_token); - if (!new_access_token){ - console.error("Failed to refresh access token.") - return false; - } - - setToken(new_access_token); - setLoggedIn(true); + (async () => { + await tryRefresh(cookies.csrf_refresh_token); + })(); + }, [cookies]); + + // Auto update token + useEffect( () => { + if (token === null) { + return undefined; } - tryRefresh(cookies.csrf_refresh_token); - }, []); + + // 5 second buffer for access token refresh + const refersh_buffer_time = 5000; + const access_token_expiration_claim = decodeJWT(token).exp + const access_token_expiration_time = new Date(0).setUTCSeconds(access_token_expiration_claim); + const miliseconds_to_access_token_expiration = (access_token_expiration_time - Date.now()) + + const timer = setTimeout( async () => { + await tryRefresh(cookies.csrf_refresh_token); + }, miliseconds_to_access_token_expiration - refersh_buffer_time); + + return () => clearTimeout(timer); + }, [token, cookies]); return (