From a3d78854a9c5d64dd97492ed41f450c661a813ac Mon Sep 17 00:00:00 2001 From: Justin Campbell Date: Wed, 25 Nov 2020 11:35:54 -0500 Subject: [PATCH 1/3] Remove log for CSRF token --- src/components/AuthProvider/AuthProvider.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/AuthProvider/AuthProvider.js b/src/components/AuthProvider/AuthProvider.js index ae5b6fa..cd11258 100644 --- a/src/components/AuthProvider/AuthProvider.js +++ b/src/components/AuthProvider/AuthProvider.js @@ -24,7 +24,6 @@ export default function AuthProvider({ children }) { useEffect( _ => { async function tryRefresh(csrf_refresh_token){ - console.log("CSRF Token", csrf_refresh_token) if (csrf_refresh_token === undefined){ return false; } From 6c7b28e49f0313fdb11cf1c249caf186426ad883 Mon Sep 17 00:00:00 2001 From: Justin Campbell Date: Wed, 25 Nov 2020 17:48:04 -0500 Subject: [PATCH 2/3] Add jwt-decode to npm dependencies --- package-lock.json | 5 +++++ package.json | 1 + 2 files changed, 6 insertions(+) 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", From 2d60fefc0e973f064e6416dfdf33a523b9b1d940 Mon Sep 17 00:00:00 2001 From: Justin Campbell Date: Wed, 25 Nov 2020 18:06:57 -0500 Subject: [PATCH 3/3] Add auto refresh for access tokens --- src/components/AuthProvider/AuthProvider.js | 54 +++++++++++++++------ 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/src/components/AuthProvider/AuthProvider.js b/src/components/AuthProvider/AuthProvider.js index cd11258..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,23 +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){ - 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 (