/* eslint-disable no-console */ import { useState, useCallback, useEffect } from 'react'; import { AuthenticationConfiguration } from '../types'; import { getCookieValue, refreshAccessToken as refreshTokenUtil, logout } from '../utils/authUtils'; export const useAuth = (authConfig: AuthenticationConfiguration | undefined) => { const [authToken, setAuthToken] = useState(getCookieValue('authToken')); const [isAuthenticated, setIsAuthenticated] = useState(!!authToken); const refreshAccessToken = useCallback(async (): Promise => { try { const newToken = await refreshTokenUtil(authConfig); setAuthToken(newToken); setIsAuthenticated(!!newToken); return newToken; } catch { setAuthToken(null); setIsAuthenticated(false); // Clear cookies associated with invalidated tokens logout(); throw new Error('Session expired. Please log in again.'); } }, [authConfig]); const handleLogin = useCallback((): void => { if (!authConfig?.redirectUrl || !authConfig?.authUrl) { console.error('Auth config is misconfigured'); return; } const encodedRedirectUrl = encodeURIComponent(authConfig.redirectUrl); const scope = authConfig?.scope?.split(';').join(' '); // Saved in scope1;scope2;scope3 format, sent in scope1 scope2 scope3 format const loginUrl = `${authConfig?.authUrl}?client_id=${authConfig?.clientId}&scope=${scope}&redirect_uri=${encodedRedirectUrl}&response_type=code&state=state`; const popup = window.open(loginUrl, 'Login', 'width=600,height=600'); if (!popup) { console.error('Popup failed to open'); return; } const checkPopup = setInterval(() => { try { const token = getCookieValue('authToken'); const refreshToken = getCookieValue('refreshToken'); if (token && refreshToken) { clearInterval(checkPopup); popup.close(); setAuthToken(token); setIsAuthenticated(true); } } catch (error) { // Ignore cross-origin access errors } if (popup.closed) { clearInterval(checkPopup); console.error('Popup closed before authentication'); } }, 1000); // Check every second }, [authConfig]); const syncAuthState = () => { const token = getCookieValue('authToken'); setAuthToken(token); setIsAuthenticated(!!token); }; useEffect(() => { // Don't run internal processes if we are always using the resource request proxy if (authConfig?.alwaysUseResourceRequestProxy) { // Consistent return value for cleanup function return () => {}; } const handleTabChange = () => { if (!document.hidden) { syncAuthState(); } }; syncAuthState(); document.addEventListener('visibilitychange', handleTabChange); window.addEventListener('focus', syncAuthState); return () => { document.removeEventListener('visibilitychange', handleTabChange); window.removeEventListener('focus', syncAuthState); }; }, []); useEffect(() => { // Don't run internal processes if we are always using the resource request proxy if (authConfig?.alwaysUseResourceRequestProxy) { return; } refreshAccessToken().catch(() => { setIsAuthenticated(false); }); }, [authConfig, refreshAccessToken]); // Return some dummy data if we are always using the resource request proxy if (authConfig?.alwaysUseResourceRequestProxy) { return { authToken: null, isAuthenticated: true, login: () => {}, refreshAccessToken: () => Promise.resolve(''), alwaysUseResourceRequestProxy: true, }; } return { authToken, isAuthenticated, login: handleLogin, refreshAccessToken, alwaysUseResourceRequestProxy: false, }; };