I store the access token and refresh token in separate cookies, with both set to expire after 7 days. The access token itself expires every 10 minutes. I’ve implemented a refresh token function that runs 1 minute before the access token expires, automatically updating the token state. The tokens remain valid while actively using the website, but if I become idle for some time, the access token value becomes null.
`"use client";
import { createContext, useContext, useState, useEffect } from "react";
import axios from "axios";
import Cookies from "js-cookie";
import jwt from "jsonwebtoken";
import { useRouter } from "next/navigation";
const AuthContext = createContext();
export const AuthProvider = ({
children
}) => {
const apiURL = process.env.NEXT_PUBLIC_API_URL;
const router = useRouter();
const [user, setUser] = useState(null);
const [token, setToken] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const storedToken = Cookies.get("token");
if (storedToken) {
setToken(storedToken);
} else {
logoutAction();
}
}, []);
useEffect(() => {
const storedUser = JSON.parse(localStorage.getItem("user"));
if (storedUser) {
if (storedUser.roleTypeId === 3) {
router.push("/dashboard");
}
}
}, [user]);
useEffect(() => {
const initializeAuth = async () => {
setLoading(true);
console.log(token);
try {
const storedUser = localStorage.getItem("user");
if (storedUser) setUser(JSON.parse(storedUser));
const currentToken = Cookies.get("token");
console.log(currentToken);
if (currentToken) {
const decodedToken = jwt.decode(currentToken);
if (Date.now() >= decodedToken?.exp * 1000) {
await handleTokenRefresh();
}
} else {
logoutAction();
}
} catch (error) {
console.error("Error during auth initialization:", error);
} finally {
setLoading(false);
}
};
initializeAuth();
}, [token]);
useEffect(() => {
const intervalId = setInterval(async () => {
try {
if (token) {
const decodedToken = jwt.decode(token);
if (Date.now() >= decodedToken?.exp * 1000) {
await handleTokenRefresh();
}
}
} catch (error) {
throw error;
}
}, 60000);
return () => {
clearInterval(intervalId);
};
});
const handleTokenRefresh = async () => {
try {
const currentRefreshToken = Cookies.get("refreshToken");
const currentToken = Cookies.get("token");
const { data } = await axios.post(
`${apiURL}/Authentication/RefreshToken`,
{
refreshToken: currentRefreshToken,
token: currentToken,
},
{
headers: {
"Content-Type": "application/json",
Accept: "application/json",
Authorization: `bearer ${token}`,
},
}
);
updateTokens(data.token, data.refreshToken);
return data;
} catch (error) {
console.error("Error refreshing token:", error);
logoutAction();
throw error;
}
};
const updateTokens = (
newToken
, newRefreshToken) => {
const cookieOptions = {
secure: true,
sameSite: "strict",
expires: 7,
path: "/",
domain: window.location.hostname,
};
Cookies.set("token",
newToken
, cookieOptions);
Cookies.set("refreshToken",
newRefreshToken
, cookieOptions);
setToken(
newToken
);
};
const LoginAction = async (
loginData
) => {
setLoading(true);
try {
const { data } = await axios.post(
`${apiURL}/Authentication/LoginUser`,
loginData
,
{
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
}
);
updateTokens(
data.authenticationResult.token,
data.authenticationResult.refreshToken
);
localStorage.setItem("user", JSON.stringify(data.user));
setUser(data.user);
return data;
} catch (error) {
throw error.response;
} finally {
setLoading(false);
}
};
const logoutAction = () => {
Cookies.remove("token");
Cookies.remove("refreshToken");
localStorage.removeItem("user");
setUser(null);
setToken(null);
router.push("/");
};
return (
<AuthContext.Provider
value
={{ LoginAction, logoutAction, user, loading }}>
{
children
}
</AuthContext.Provider>
);
};
export const useAuth = () => useContext(AuthContext);`