|
|
|
|
@ -7,6 +7,8 @@ import { |
|
|
|
|
import { useHistory } from 'react-router' |
|
|
|
|
|
|
|
|
|
import type { User } from 'oidc-client' |
|
|
|
|
// @ts-expect-error
|
|
|
|
|
import duel from 'dueljs' |
|
|
|
|
|
|
|
|
|
import isString from 'lodash/isString' |
|
|
|
|
import isBoolean from 'lodash/isBoolean' |
|
|
|
|
@ -21,14 +23,12 @@ import { |
|
|
|
|
readToken, |
|
|
|
|
setCookie, |
|
|
|
|
removeCookie, |
|
|
|
|
TOKEN_KEY, |
|
|
|
|
} from 'helpers' |
|
|
|
|
|
|
|
|
|
import { |
|
|
|
|
useLocalStore, |
|
|
|
|
useSessionStore, |
|
|
|
|
useToggle, |
|
|
|
|
useEventListener, |
|
|
|
|
} from 'hooks' |
|
|
|
|
|
|
|
|
|
import { useLexicsStore } from 'features/LexicsStore' |
|
|
|
|
@ -172,27 +172,6 @@ export const useAuth = () => { |
|
|
|
|
markUserLoaded, |
|
|
|
|
]) |
|
|
|
|
|
|
|
|
|
useEventListener({ |
|
|
|
|
callback: useCallback(async (e: StorageEvent) => { |
|
|
|
|
const loadedUser = await userManager.getUser() |
|
|
|
|
|
|
|
|
|
if ( |
|
|
|
|
e.storageArea !== localStorage |
|
|
|
|
|| e.key !== TOKEN_KEY |
|
|
|
|
|| !e.newValue |
|
|
|
|
|| !loadedUser |
|
|
|
|
|| loadedUser.access_token === e.newValue |
|
|
|
|
) return |
|
|
|
|
|
|
|
|
|
userManager.storeUser({ |
|
|
|
|
...loadedUser, |
|
|
|
|
access_token: e.newValue, |
|
|
|
|
toStorageString: loadedUser.toStorageString, |
|
|
|
|
}) |
|
|
|
|
}, []), |
|
|
|
|
event: 'storage', |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
|
const isRedirectedBackFromAuthProvider = history.location.pathname === '/redirect' |
|
|
|
|
isRedirectedBackFromAuthProvider ? signinRedirectCallback() : checkUser() |
|
|
|
|
@ -238,28 +217,24 @@ export const useAuth = () => { |
|
|
|
|
setIsNewDeviceLogin, |
|
|
|
|
]) |
|
|
|
|
|
|
|
|
|
duel.channel('active_page') // поле в LS, определяющее активность вкладки
|
|
|
|
|
useEffect(() => { |
|
|
|
|
// попытаемся обновить токен используя refresh_token
|
|
|
|
|
const tryRenewToken = () => { |
|
|
|
|
const tokenLastUpdated = Number(localStorage.getItem('token_updated')) |
|
|
|
|
// предотвращаем одновременное обновление токена в разных окнах/вкладках
|
|
|
|
|
const needRenewToken = Date.now() - tokenLastUpdated >= 2 * 1e3 |
|
|
|
|
|
|
|
|
|
if (!needRenewToken) return |
|
|
|
|
|
|
|
|
|
localStorage.setItem('token_updated', String(Date.now())) |
|
|
|
|
|
|
|
|
|
userManager.signinSilent() |
|
|
|
|
.catch(logout) |
|
|
|
|
// библиотека oidc-client не поддерживает обновление токена только на 1 вкладке
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
if (window.isMaster()) { |
|
|
|
|
userManager.signinSilent().catch(logout) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// если запросы вернули 401 | 403
|
|
|
|
|
window.addEventListener('FORBIDDEN_REQUEST', tryRenewToken) |
|
|
|
|
|
|
|
|
|
// и если токен истек
|
|
|
|
|
userManager.events.addAccessTokenExpired(tryRenewToken) |
|
|
|
|
// и если токен истекает (по дефолту за 60 секунд)
|
|
|
|
|
userManager.events.addAccessTokenExpiring(tryRenewToken) |
|
|
|
|
return () => { |
|
|
|
|
window.removeEventListener('FORBIDDEN_REQUEST', tryRenewToken) |
|
|
|
|
userManager.events.removeAccessTokenExpired(tryRenewToken) |
|
|
|
|
userManager.events.removeAccessTokenExpiring(tryRenewToken) |
|
|
|
|
} |
|
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
|
|
}, [logout]) |
|
|
|
|
|
а мы можем обойтись без того, чтобы не тянуть еще одну библиотеку?