diff --git a/src/auth/index.js b/src/auth/index.js
index e92350c..7392f0c 100644
--- a/src/auth/index.js
+++ b/src/auth/index.js
@@ -12,6 +12,7 @@ export const predictUsageCount = 'predictUsageCount'
export const windowCount = 'windowCount'
import {useNavigate} from "react-router-dom";
import {useDispatch} from "react-redux";
+import { REFRESH_TOKEN } from 'utils/ApiPathConst';
// ** Handle User Login
export const handleLogin = data => {
@@ -104,6 +105,8 @@ export const SetupAxiosInterceptors = () => {
const navigate = useNavigate()
const dispatch = useDispatch();
//const updateLastRequestTime = useContext(TimerContext);
+ let isRefreshToken= false;
+
axios.interceptors.request.use(
config => {
// ** Get token from localStorage
@@ -126,39 +129,73 @@ export const SetupAxiosInterceptors = () => {
//updateLastRequestTime(Date.now());
return response;
},
- error => {
+ async (error) => {
// ** const { config, response: { status } } = error
- const {response} = error
- if (error.response.status === 401) {
- if (localStorage.getItem("expiredAlertShown") === null) {
- localStorage.setItem("expiredAlertShown", true)
- alert("登入驗證已過期,請重新登入。")
+ if (error.response.status === 401 && error.config.url !== apiPath + REFRESH_TOKEN) {
+ // Make a request to refresh the access token
+ const refreshToken = localStorage.getItem('refreshToken');
+ if (isRefreshToken) {
+ return;
}
-
- }
-
- // ** if (status === 401) {
- if (response.status === 401) {
- if (localStorage.getItem("expiredAlertShown") === null) {
- localStorage.setItem("expiredAlertShown", true)
- alert("登入驗證已過期,請重新登入。")
+ isRefreshToken = true;
+ return axios
+ .post(`${apiPath}${REFRESH_TOKEN}`, {
+ refreshToken: refreshToken // Replace with your refresh token
+ })
+ .then((response) => {
+ if (response.status === 200) {
+ const newAccessToken = response.data.accessToken;
+ const newRefreshToken = response.data.refreshToken;
+ localStorage.setItem('accessToken', newAccessToken);
+ localStorage.setItem('refreshToken', newRefreshToken);
+ isRefreshToken = false;
+ window.location.reload();
+ }
+ })
+ .catch((refreshError) => {
+ dispatch(handleLogoutFunction());
+ navigate('/login');
+ isRefreshToken = false;
+ window.location.reload();
+ throw refreshError;
+ });
+ } else {
+ // if (error.response.status === 401) {
+ // await dispatch(handleLogoutFunction());
+ // await navigate('/login');
+ // await window.location.reload();
+ // }
+ if (error.response.status === 401) {
+ if (localStorage.getItem("expiredAlertShown") === null) {
+ localStorage.setItem("expiredAlertShown", true)
+ alert("登入驗證已過期,請重新登入。")
+ }
+
}
- }
-
- if (response && response.status === 401) {
- if (localStorage.getItem("expiredAlertShown") === null) {
- localStorage.setItem("expiredAlertShown", true)
- alert("登入驗證已過期,請重新登入。")
+
+ // ** if (status === 401) {
+ if (response.status === 401) {
+ if (localStorage.getItem("expiredAlertShown") === null) {
+ localStorage.setItem("expiredAlertShown", true)
+ alert("登入驗證已過期,請重新登入。")
+ }
+ }
+
+ if (response && response.status === 401) {
+ if (localStorage.getItem("expiredAlertShown") === null) {
+ localStorage.setItem("expiredAlertShown", true)
+ alert("登入驗證已過期,請重新登入。")
+ }
+ }
+
+ if (localStorage.getItem("expiredAlertShown")) {
+ dispatch(handleLogoutFunction());
+ navigate('/login');
}
- }
-
- if (localStorage.getItem("expiredAlertShown")) {
- dispatch(handleLogoutFunction());
- navigate('/login');
}
return Promise.reject(error)
- },
+ }
)
}
diff --git a/src/components/AutoLogoutProvider.js b/src/components/AutoLogoutProvider.js
index 8387458..fb9128c 100644
--- a/src/components/AutoLogoutProvider.js
+++ b/src/components/AutoLogoutProvider.js
@@ -1,17 +1,29 @@
import React, { createContext, useState, useEffect } from 'react';
-//import {useNavigate} from "react-router-dom";
+import {useNavigate} from "react-router-dom";
//import axios from "axios";
import {getUserData} from "../auth/utils";
import {isObjEmpty} from "../utils/Utils";
import {useIdleTimer} from "react-idle-timer";
+import { handleLogoutFunction } from 'auth/index';
+import { useDispatch } from "react-redux";
+import {
+ isUserLoggedIn,
+ isGLDLoggedIn,
+ // isPrimaryLoggedIn,
+ // isCreditorLoggedIn,
+ // isINDLoggedIn,
+ // isORGLoggedIn,
+ // getUserId
+} from "utils/Utils";
const TimerContext = createContext();
const AutoLogoutProvider = ({ children }) => {
const [lastRequestTime, setLastRequestTime] = useState(Date.now());
- //const navigate = useNavigate();
- const [logoutInterval /*, setLogoutInterval*/] = useState(1);
+ const navigate = useNavigate();
+ const [logoutInterval, setLogoutInterval] = useState(1);
const [state, setState] = useState('Active');
+ const dispatch = useDispatch()
const onIdle = () => {
setLastRequestTime(Date.now());
@@ -30,7 +42,7 @@ const AutoLogoutProvider = ({ children }) => {
} = useIdleTimer({
onIdle,
onActive,
- timeout: 10_000,
+ timeout: 1_000,
throttle: 500,
crossTab: true,
syncTimers: 200,
@@ -43,19 +55,23 @@ const AutoLogoutProvider = ({ children }) => {
const userData = getUserData();
if(!isObjEmpty(userData)){
//TODO: get auto logout time here
-
+ if(isGLDLoggedIn()){
+ setLogoutInterval(240);
+ }else{
+ setLogoutInterval(1);
+ }
// axios.get(`${apiPath}${GET_IDLE_LOGOUT_TIME}`,
// )
- // .then((response) => {
- // if (response.status === 200) {
- // setLastRequestTime(Date.now());
- // setLogoutInterval(parseInt(response.data.data));
- // }
- // })
- // .catch(error => {
- // console.log(error);
- // return false;
- // });
+ // .then((response) => {
+ // if (response.status === 200) {
+ // setLastRequestTime(Date.now());
+ // setLogoutInterval(parseInt(response.data.data));
+ // }
+ // })
+ // .catch(error => {
+ // console.log(error);
+ // return false;
+ // });
}
else{
//navigate('/login');
@@ -68,13 +84,14 @@ const AutoLogoutProvider = ({ children }) => {
getRemainingTime();
if(state !== "Active" && lastActiveTab){
const timeElapsed = currentTime - lastRequestTime;
- // console.log(timeElapsed);
+ // console.log(parseInt(timeElapsed/1000));
+ // console.log(logoutInterval* 60);
if (timeElapsed >= logoutInterval * 60 * 1000) {
- //TODO: auto logout here
- // console.log("logout");
- //await dispatch(handleLogoutFunction());
- //await navigate('/login');
- //await window.location.reload();
+ if(isUserLoggedIn()){
+ alert("登入驗證已過期,請重新登入。")
+ dispatch(handleLogoutFunction());
+ navigate('/login');
+ }
}
}
else if(state === "Active"){
diff --git a/src/components/RefreshTokenProvider.js b/src/components/RefreshTokenProvider.js
new file mode 100644
index 0000000..0978d79
--- /dev/null
+++ b/src/components/RefreshTokenProvider.js
@@ -0,0 +1,72 @@
+import { createContext, useEffect, useRef, useCallback } from 'react';
+import { apiPath } from 'auth/utils';
+import { REFRESH_TOKEN } from 'utils/ApiPathConst';
+import axios from 'axios';
+
+const RefreshTokenContext = createContext();
+
+const RefreshTokenProvider = ({ children }) => {
+ const token = useRef(localStorage.getItem('accessToken'));
+ const isRefresh = useRef(false);
+
+ // handle Refresh Token Logic
+ const handleRefreshToken = useCallback(() => {
+ if (!isRefresh.current) {
+ const refreshToken = localStorage.getItem('refreshToken');
+ isRefresh.current = true;
+ axios
+ .post(`${apiPath}${REFRESH_TOKEN}`, {
+ refreshToken: refreshToken
+ })
+ .then((response) => {
+ if (response.status === 200) {
+ const newAccessToken = response.data.accessToken;
+ const newRefreshToken = response.data.refreshToken;
+ localStorage.setItem('accessToken', newAccessToken);
+ localStorage.setItem('refreshToken', newRefreshToken);
+ token.current = newAccessToken;
+ isRefresh.current = false;
+ } else {
+ token.current = null;
+ isRefresh.current = false;
+ }
+ })
+ .catch((refreshError) => {
+ console.log('Failed to refresh token');
+ console.log(refreshError)
+ token.current = null
+ isRefresh.current = false;
+ });
+ }
+ }, []);
+
+ // Function to check token expiry
+ const checkTokenExpiry = useCallback(() => {
+ // Check if token is present and its expiry time
+ if (token.current) {
+ const tokenExp = JSON.parse(atob(token.current.split('.')[1])).exp;
+ const currentTime = Math.floor(Date.now() / 1000);
+ const expiryTime = tokenExp - 30; // Refresh 30 seconds before expiry
+ // console.log("check refresh Token");
+ // console.log(currentTime);
+ // console.log(new Date(currentTime*1000).toLocaleString());
+ // console.log(expiryTime);
+ // console.log(new Date(expiryTime*1000).toLocaleString());
+ // console.log('accessToken: ' + localStorage.getItem('accessToken'));
+ // console.log('refreshToken: ' + localStorage.getItem('refreshToken'));
+ if (currentTime >= expiryTime) {
+ handleRefreshToken();
+ }
+ }
+ }, [token]);
+
+ // Start the timer on component mount
+ useEffect(() => {
+ const timer = setInterval(checkTokenExpiry, 10000); // Check every 10 second
+ return () => clearInterval(timer); // Cleanup timer on unmount
+ }, [checkTokenExpiry]);
+
+ return {children};
+};
+
+export { RefreshTokenContext, RefreshTokenProvider };
diff --git a/src/index.js b/src/index.js
index 2c85d6f..c58b3ca 100644
--- a/src/index.js
+++ b/src/index.js
@@ -18,6 +18,7 @@ import { store } from 'store';
import reportWebVitals from './reportWebVitals';
import {I18nProvider} from "./components/I18nProvider";
import {AutoLogoutProvider} from "./components/AutoLogoutProvider";
+import {RefreshTokenProvider} from "./components/RefreshTokenProvider";
// ==============================|| MAIN - REACT DOM RENDER ||============================== //
@@ -29,11 +30,13 @@ root.render(
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/src/utils/ApiPathConst.js b/src/utils/ApiPathConst.js
index 76f0519..5b6c13d 100644
--- a/src/utils/ApiPathConst.js
+++ b/src/utils/ApiPathConst.js
@@ -1,6 +1,8 @@
import {apiPath} from "../auth/utils";
// GET request
+export const REFRESH_TOKEN = "/refresh-token"
+export const CHANGE_PASSWORD_PATH = "/user/change-password"
//Group Config
export const GET_GROUP_LIST_PATH = '/group';