From 2d60fefc0e973f064e6416dfdf33a523b9b1d940 Mon Sep 17 00:00:00 2001 From: Justin Campbell Date: Wed, 25 Nov 2020 18:06:57 -0500 Subject: [PATCH] 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 (