1
I have an API that issues a JWT token with a maximum validity of 2h per token, after which it is no longer processed by my application. I need that every time this token is expired, a new token is generated.
However, how to implement a JWT token refresh function in some authentication context?
I got something similar using "useEffect" in my authentication context, but a new token is only generated after the entire application is restarted. I would like the function to be checked always when changing route (React-router-dom V6).
I leave below all my context, and also the repository in which all the code is hosted.
import React, { createContext, useState, useEffect, useContext } from 'react';
import ContextDevTool from 'react-context-devtool';
import decode from 'jwt-decode';
import api from '../services/api';
import Loading from '../pages/Loading';
const AuthContext = createContext();
export function AuthProvider({ children }) {
const [authenticated, setAuthenticated] = useState(false);
const [token, setToken] = useState('');
const [expiredToken, setExpiredToken] = useState(false);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function loadStorage() {
const storagedToken = localStorage.getItem('token');
if (storagedToken) {
const decodedToken = decode(storagedToken);
await new Promise((resolve) => setTimeout(resolve, 2000));
// if token expiry date is lower than actual date
if (decodedToken.exp <= Math.floor(new Date() / 1000)) setExpiredToken(true);
setAuthenticated(true);
setToken(decodedToken);
api.defaults.headers['Authorization'] = `Bearer ${storagedToken}`;
}
setLoading(false);
}
loadStorage();
}, []);
async function Login(username, password) {
const { data } = await api.get(`login?usuario=${username}&senha=${password}`);
const decodedToken = decode(data.token);
setAuthenticated(true);
setToken(decodedToken);
api.defaults.headers['Authorization'] = `Bearer ${data.token}`;
localStorage.setItem('token', data.token);
}
async function refreshToken() {
console.log('token refreshed');
}
async function Logout() {
localStorage.clear();
setAuthenticated(false);
setToken('');
}
while (loading) return <Loading />;
if (expiredToken) {
refreshToken();
setExpiredToken(false);
}
return (
<AuthContext.Provider value={{ authenticated, token, expiredToken, Login, Logout }}>
<ContextDevTool context={AuthContext} id="auth" displayName="Authentication Context" />
{children}
</AuthContext.Provider>
);
}
export function useAuth() {
const context = useContext(AuthContext);
return context;
}
https://github.com/medeiroshudson/React-Context
From now on, thank you.
Let me get this straight... This function will redirect the user to login if the token is expired?
– Hudson Medeiros
@Hudsonright depends on the function you created that renews the token, if there is any reason why the token cannot be renewed, you redirect to some error page, then just exchange the /login for a component. If there is no reason just take the if and call the direct function and then Children
– Bruno Santi