|
|
|
@ -7,7 +7,6 @@ import { |
|
|
|
import { useHistory } from 'react-router' |
|
|
|
import { useHistory } from 'react-router' |
|
|
|
|
|
|
|
|
|
|
|
import type { User } from 'oidc-client' |
|
|
|
import type { User } from 'oidc-client' |
|
|
|
import { UserManager } from 'oidc-client' |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import isString from 'lodash/isString' |
|
|
|
import isString from 'lodash/isString' |
|
|
|
import isBoolean from 'lodash/isBoolean' |
|
|
|
import isBoolean from 'lodash/isBoolean' |
|
|
|
@ -16,34 +15,33 @@ import { PAGES } from 'config' |
|
|
|
|
|
|
|
|
|
|
|
import { |
|
|
|
import { |
|
|
|
addLanguageUrlParam, |
|
|
|
addLanguageUrlParam, |
|
|
|
} from 'helpers/languageUrlParam' |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import { |
|
|
|
|
|
|
|
writeToken, |
|
|
|
writeToken, |
|
|
|
removeToken, |
|
|
|
removeToken, |
|
|
|
readToken, |
|
|
|
readToken, |
|
|
|
} from 'helpers/token' |
|
|
|
|
|
|
|
import { |
|
|
|
|
|
|
|
setCookie, |
|
|
|
setCookie, |
|
|
|
removeCookie, |
|
|
|
removeCookie, |
|
|
|
} from 'helpers/cookie' |
|
|
|
isMatchPage, |
|
|
|
import { isMatchPage } from 'helpers/isMatchPage' |
|
|
|
} from 'helpers' |
|
|
|
|
|
|
|
|
|
|
|
import { |
|
|
|
import { |
|
|
|
useLocalStore, |
|
|
|
useLocalStore, |
|
|
|
useSessionStore, |
|
|
|
useSessionStore, |
|
|
|
useToggle, |
|
|
|
useToggle, |
|
|
|
|
|
|
|
useEventListener, |
|
|
|
} from 'hooks' |
|
|
|
} from 'hooks' |
|
|
|
|
|
|
|
|
|
|
|
import { useLexicsStore } from 'features/LexicsStore' |
|
|
|
import { useLexicsStore } from 'features/LexicsStore' |
|
|
|
import { queryParamStorage } from 'features/QueryParamsStorage' |
|
|
|
import { queryParamStorage } from 'features/QueryParamsStorage' |
|
|
|
|
|
|
|
|
|
|
|
import { getUserInfo, UserInfo } from 'requests/getUserInfo' |
|
|
|
import type { UserInfo, FailedResponse } from 'requests' |
|
|
|
import { checkDevice, FailedResponse } from 'requests/checkDevice' |
|
|
|
import { |
|
|
|
import { getTokenVirtualUser } from 'requests/getTokenVirtualUser' |
|
|
|
getUserInfo, |
|
|
|
|
|
|
|
checkDevice, |
|
|
|
|
|
|
|
getTokenVirtualUser, |
|
|
|
|
|
|
|
} from 'requests' |
|
|
|
|
|
|
|
|
|
|
|
// eslint-disable-next-line
|
|
|
|
import { userManager, channel } from '../config' |
|
|
|
import { getClientSettings, needCheckNewDeviсe } from '../helpers' |
|
|
|
import { needCheckNewDeviсe } from '../helpers' |
|
|
|
|
|
|
|
|
|
|
|
export const useAuth = () => { |
|
|
|
export const useAuth = () => { |
|
|
|
const { changeLang, lang } = useLexicsStore() |
|
|
|
const { changeLang, lang } = useLexicsStore() |
|
|
|
@ -55,11 +53,10 @@ export const useAuth = () => { |
|
|
|
const [user, setUser] = useState<User>() |
|
|
|
const [user, setUser] = useState<User>() |
|
|
|
const [isNewDeviceLogin, setIsNewDeviceLogin] = useState(false) |
|
|
|
const [isNewDeviceLogin, setIsNewDeviceLogin] = useState(false) |
|
|
|
const [userInfo, setUserInfo] = useState<UserInfo>() |
|
|
|
const [userInfo, setUserInfo] = useState<UserInfo>() |
|
|
|
const userManager = useMemo(() => new UserManager(getClientSettings()), []) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const login = useCallback(async () => { |
|
|
|
const login = useCallback(async () => { |
|
|
|
userManager.signinRedirect({ extraQueryParams: { lang } }) |
|
|
|
userManager.signinRedirect({ extraQueryParams: { lang } }) |
|
|
|
}, [userManager, lang]) |
|
|
|
}, [lang]) |
|
|
|
|
|
|
|
|
|
|
|
const logout = useCallback((key?: string) => { |
|
|
|
const logout = useCallback((key?: string) => { |
|
|
|
setPage(history.location.pathname) |
|
|
|
setPage(history.location.pathname) |
|
|
|
@ -73,7 +70,7 @@ export const useAuth = () => { |
|
|
|
removeCookie('access_token') |
|
|
|
removeCookie('access_token') |
|
|
|
} |
|
|
|
} |
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
|
}, [userManager, lang]) |
|
|
|
}, [lang]) |
|
|
|
|
|
|
|
|
|
|
|
const storeUser = useCallback((loadedUser: User) => { |
|
|
|
const storeUser = useCallback((loadedUser: User) => { |
|
|
|
setUser(loadedUser) |
|
|
|
setUser(loadedUser) |
|
|
|
@ -83,6 +80,8 @@ export const useAuth = () => { |
|
|
|
name: 'access_token', |
|
|
|
name: 'access_token', |
|
|
|
value: loadedUser.access_token, |
|
|
|
value: loadedUser.access_token, |
|
|
|
}) |
|
|
|
}) |
|
|
|
|
|
|
|
// обновляем токен в других окнах/вкладках
|
|
|
|
|
|
|
|
channel.postMessage({ token: loadedUser.access_token }) |
|
|
|
}, []) |
|
|
|
}, []) |
|
|
|
|
|
|
|
|
|
|
|
const checkUser = useCallback(async () => { |
|
|
|
const checkUser = useCallback(async () => { |
|
|
|
@ -102,7 +101,6 @@ export const useAuth = () => { |
|
|
|
return loadedUser |
|
|
|
return loadedUser |
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
|
}, [ |
|
|
|
}, [ |
|
|
|
userManager, |
|
|
|
|
|
|
|
storeUser, |
|
|
|
storeUser, |
|
|
|
markUserLoaded, |
|
|
|
markUserLoaded, |
|
|
|
]) |
|
|
|
]) |
|
|
|
@ -173,12 +171,31 @@ export const useAuth = () => { |
|
|
|
}).catch(login) |
|
|
|
}).catch(login) |
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
|
}, [ |
|
|
|
}, [ |
|
|
|
userManager, |
|
|
|
|
|
|
|
login, |
|
|
|
login, |
|
|
|
storeUser, |
|
|
|
storeUser, |
|
|
|
markUserLoaded, |
|
|
|
markUserLoaded, |
|
|
|
]) |
|
|
|
]) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
useEventListener({ |
|
|
|
|
|
|
|
callback: useCallback(async (e: MessageEvent<{ token: string }>) => { |
|
|
|
|
|
|
|
const loadedUser = await userManager.getUser() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( |
|
|
|
|
|
|
|
!e.data.token |
|
|
|
|
|
|
|
|| !loadedUser |
|
|
|
|
|
|
|
|| loadedUser.access_token === e.data.token |
|
|
|
|
|
|
|
) return |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
userManager.storeUser({ |
|
|
|
|
|
|
|
...loadedUser, |
|
|
|
|
|
|
|
access_token: e.data.token, |
|
|
|
|
|
|
|
toStorageString: loadedUser.toStorageString, |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
}, []), |
|
|
|
|
|
|
|
event: 'message', |
|
|
|
|
|
|
|
target: channel, |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
useEffect(() => { |
|
|
|
const isRedirectedBackFromAuthProvider = history.location.pathname === '/redirect' |
|
|
|
const isRedirectedBackFromAuthProvider = history.location.pathname === '/redirect' |
|
|
|
isRedirectedBackFromAuthProvider ? signinRedirectCallback() : checkUser() |
|
|
|
isRedirectedBackFromAuthProvider ? signinRedirectCallback() : checkUser() |
|
|
|
@ -200,34 +217,41 @@ export const useAuth = () => { |
|
|
|
setTimeout(logout, 10000) |
|
|
|
setTimeout(logout, 10000) |
|
|
|
} |
|
|
|
} |
|
|
|
}) |
|
|
|
}) |
|
|
|
}, [logout, userManager]) |
|
|
|
}, [logout]) |
|
|
|
|
|
|
|
|
|
|
|
// eslint-disable-next-line
|
|
|
|
|
|
|
|
const checkNewDevice = useCallback(async () => { |
|
|
|
const checkNewDevice = useCallback(async () => { |
|
|
|
const loadedUser = await userManager.getUser() |
|
|
|
const loadedUser = await userManager.getUser() |
|
|
|
if (!loadedUser) return |
|
|
|
if (!loadedUser) return |
|
|
|
|
|
|
|
|
|
|
|
checkDevice(loadedUser.access_token).catch(() => { |
|
|
|
checkDevice(loadedUser.access_token).catch(() => { |
|
|
|
setTimeout(reChekNewDevice, 2000) |
|
|
|
setTimeout(reChekNewDevice, 5000) |
|
|
|
}) |
|
|
|
}) |
|
|
|
}, [reChekNewDevice, userManager]) |
|
|
|
}, [reChekNewDevice]) |
|
|
|
|
|
|
|
|
|
|
|
// useEffect(() => {
|
|
|
|
useEffect(() => { |
|
|
|
// if (!needCheckNewDeviсe && !user) return undefined
|
|
|
|
if (!needCheckNewDeviсe && !user) return undefined |
|
|
|
// const startCheckDevice = setInterval(checkNewDevice, 20000)
|
|
|
|
const startCheckDevice = setInterval(checkNewDevice, 20000) |
|
|
|
// isNewDeviceLogin && clearInterval(startCheckDevice)
|
|
|
|
isNewDeviceLogin && clearInterval(startCheckDevice) |
|
|
|
// return () => clearInterval(startCheckDevice)
|
|
|
|
return () => clearInterval(startCheckDevice) |
|
|
|
//
|
|
|
|
|
|
|
|
// // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
|
// }, [
|
|
|
|
}, [ |
|
|
|
// checkNewDevice,
|
|
|
|
checkNewDevice, |
|
|
|
// isNewDeviceLogin,
|
|
|
|
isNewDeviceLogin, |
|
|
|
// setIsNewDeviceLogin,
|
|
|
|
setIsNewDeviceLogin, |
|
|
|
// ])
|
|
|
|
]) |
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
useEffect(() => { |
|
|
|
// попытаемся обновить токен используя refresh_token
|
|
|
|
// попытаемся обновить токен используя refresh_token
|
|
|
|
const tryRenewToken = () => { |
|
|
|
const tryRenewToken = () => { |
|
|
|
|
|
|
|
const tokenLastUpdated = Number(localStorage.getItem('token_updated')) |
|
|
|
|
|
|
|
// предотвращаем одновременное обновление токена в разных окнах/вкладках
|
|
|
|
|
|
|
|
const needRenewToken = Date.now() - tokenLastUpdated >= userManager.settings.clockSkew! * 1e3 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!needRenewToken) return |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
localStorage.setItem('token_updated', String(Date.now())) |
|
|
|
|
|
|
|
|
|
|
|
userManager.signinSilent() |
|
|
|
userManager.signinSilent() |
|
|
|
.catch(() => user && logout()) |
|
|
|
.catch(() => user && logout()) |
|
|
|
} |
|
|
|
} |
|
|
|
@ -241,14 +265,7 @@ export const useAuth = () => { |
|
|
|
userManager.events.removeAccessTokenExpired(tryRenewToken) |
|
|
|
userManager.events.removeAccessTokenExpired(tryRenewToken) |
|
|
|
} |
|
|
|
} |
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
|
}, [userManager, logout]) |
|
|
|
}, [logout]) |
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
|
|
|
|
// событие срабатывает после получения токена(первый
|
|
|
|
|
|
|
|
// логин и обновление токена)
|
|
|
|
|
|
|
|
userManager.events.addUserLoaded(storeUser) |
|
|
|
|
|
|
|
return () => userManager.events.removeUserLoaded(storeUser) |
|
|
|
|
|
|
|
}, [userManager, storeUser]) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const fetchUserInfo = useCallback(async () => { |
|
|
|
const fetchUserInfo = useCallback(async () => { |
|
|
|
try { |
|
|
|
try { |
|
|
|
|