import { useCallback, useEffect, useRef } from 'react'; import { AuthSessionResult } from 'expo-auth-session'; import { config } from 'config'; import * as Linking from 'expo-linking'; import * as AuthSession from 'expo-auth-session'; import { setAccessToken, setRefreshToken } from 'utils/auth'; import { ScreensPath } from 'navigation/enum'; import { useResponsiveLayout } from 'hooks/responsive-layout'; import { isLoggedInVar } from 'state-management/session'; import { decodeBase64 } from 'utils/decoding'; import decode from 'jwt-decode'; import { Sentry } from 'utils/sentry'; import { useRouting } from '../routing'; const { auth } = config; export const useAuth = (): Auth => { const { platform } = useResponsiveLayout(); const isMounted = useRef(false); const { toLanding, navigateTo } = useRouting(); const returnUrl = encodeURIComponent(Linking.createURL(`${ScreensPath.Landing}`)); const authUrl = `${auth.url}?returnUrl=${returnUrl}`; const webAuthUrl = `${auth.webURL}?returnUrl=${returnUrl}`; const webNullAuthUrl = `/auth?returnUrl=${returnUrl}`; useEffect(() => { isMounted.current = true; return () => { isMounted.current = false; }; }, []); const authenticate = useCallback(async () => { const authResponse = await AuthSession.startAsync({ authUrl, projectNameForProxy: 'pivot', }); return authResponse; }, [authUrl]); const setAuthKeys = useCallback(async (accessToken: string, refreshToken: string) => { const accessTokenDecoded = decodeBase64(accessToken); const refreshTokenDecoded = decodeBase64(refreshToken); await setAccessToken(accessTokenDecoded); await setRefreshToken(refreshTokenDecoded); const { email } = decode(accessTokenDecoded); Sentry.setUser({ email }); isLoggedInVar(true); }, []); const initAuth = useCallback(async () => { const authResponse: AuthSessionResult = await authenticate(); if (authResponse.type === 'success') { const { accessToken, refreshToken, verificationCode, email } = authResponse.params || {}; if (accessToken && refreshToken) { setAuthKeys(accessToken, refreshToken); } else if (verificationCode && email) { toLanding({ email: decodeBase64(email), verificationCode: decodeBase64(verificationCode), }); } // TODO: handle errors // } else if (authResponse.type === 'cancel') { // } else if (authResponse.type === 'dismiss') { // } else if (authResponse.type === 'error') { // } else if (authResponse.type === 'locked') { // } } }, [authenticate, setAuthKeys, toLanding]); const login = useCallback(() => { if (platform === 'web') { if (auth.webURL) { window.location.href = webAuthUrl; } else { navigateTo(webNullAuthUrl); } } else { initAuth(); } }, [initAuth, navigateTo, platform, webAuthUrl, webNullAuthUrl]); return { login, setAuthKeys, }; }; interface Auth { login: () => void; setAuthKeys: (accessToken: string, refreshToken: string) => void; } interface User { email: string; }