diff --git a/src/auth/index.js b/src/auth/index.js index 714fe5d..5bf7bc3 100644 --- a/src/auth/index.js +++ b/src/auth/index.js @@ -15,6 +15,11 @@ import {useDispatch} from "react-redux"; import { REFRESH_TOKEN } from 'utils/ApiPathConst'; import { getMessage } from 'utils/getI18nMessage'; +// Guard so we only register interceptors once (ThemeRoutes re-renders add duplicate handlers otherwise) +let axiosInterceptorsSetup = false; +// In-memory guard so only one 401/logout flow shows the alert (avoids race when multiple 401s or interceptors run) +let expiredAlertShownInMemory = false; + // ** Handle User Login export const handleLogin = data => { return dispatch => { @@ -95,7 +100,8 @@ export const handleLogoutFunction = () => { localStorage.removeItem('transactionid') localStorage.removeItem('searchCriteria') //localStorage.removeItem(config.storageUserRoleKeyName) - localStorage.removeItem('expiredAlertShown') + localStorage.removeItem('expiredAlertShown'); + expiredAlertShownInMemory = false; localStorage.removeItem(refreshIntervalName) localStorage.removeItem(windowCount) localStorage.removeItem(predictProductionQty) @@ -110,7 +116,13 @@ export const SetupAxiosInterceptors = () => { const dispatch = useDispatch(); //const updateLastRequestTime = useContext(TimerContext); let isRefreshToken= false; - + + // Avoid stacking interceptors on every ThemeRoutes re-render (would cause multiple alerts on 401) + if (axiosInterceptorsSetup) { + return; + } + axiosInterceptorsSetup = true; + axios.interceptors.request.use( config => { // ** Get token from localStorage @@ -158,7 +170,8 @@ export const SetupAxiosInterceptors = () => { }) .catch((refreshError) => { isRefreshToken = false; - if (localStorage.getItem("expiredAlertShown") === null) { + if (!expiredAlertShownInMemory && localStorage.getItem("expiredAlertShown") === null) { + expiredAlertShownInMemory = true; localStorage.setItem("expiredAlertShown", "true"); alert(getMessage("autoLogout")); } @@ -168,10 +181,11 @@ export const SetupAxiosInterceptors = () => { throw refreshError; }); } else { - if (error.response.status === 401) { - if (localStorage.getItem("expiredAlertShown") === null) { - localStorage.setItem("expiredAlertShown", true) - alert(getMessage("autoLogout")) + if (error.response && error.response.status === 401) { + if (!expiredAlertShownInMemory && localStorage.getItem("expiredAlertShown") === null) { + expiredAlertShownInMemory = true; + localStorage.setItem("expiredAlertShown", "true"); + alert(getMessage("autoLogout")); } } diff --git a/src/components/AutoLogoutProvider.js b/src/components/AutoLogoutProvider.js index a7b9744..124de6f 100644 --- a/src/components/AutoLogoutProvider.js +++ b/src/components/AutoLogoutProvider.js @@ -98,7 +98,11 @@ const AutoLogoutProvider = ({ children }) => { if (timeElapsed >= logoutInterval * 60 * 1000) { if (isUserLoggedIn() && !idleLogoutTriggeredRef.current) { idleLogoutTriggeredRef.current = true; - alert(intl.formatMessage({ id: "autoLogout" })); + // Skip alert if token-expiry (axios 401) already showed one, to avoid duplicate alerts + if (localStorage.getItem("expiredAlertShown") === null) { + localStorage.setItem("expiredAlertShown", "true"); + alert(intl.formatMessage({ id: "autoLogout" })); + } dispatch(handleLogoutFunction()); navigate('/login'); window.location.reload();