UNPKG

@tidecloak/react

Version:
146 lines (145 loc) 5.75 kB
import { jsx as _jsx } from "react/jsx-runtime"; import React from "react"; import { IAMService } from '@tidecloak/js'; const TideCloakContext = React.createContext(undefined); export function TideCloakContextProvider({ config, children }) { const [isInitializing, setIsInitializing] = React.useState(true); const [initError, setInitError] = React.useState(null); const [authenticated, setAuthenticated] = React.useState(false); const [sessionExpired, setSessionExpired] = React.useState(false); const [isRefreshing, setIsRefreshing] = React.useState(false); const [token, setToken] = React.useState(null); const [idToken, setIdToken] = React.useState(null); const [tokenExp, setTokenExp] = React.useState(null); const [baseURL, setBaseURL] = React.useState(""); const [reloadKey, setReloadKey] = React.useState(0); React.useEffect(() => { let mounted = true; const updateAuthState = async (eventName) => { console.debug(`[TideCloak Provider] Updating auth state. Triggered by the ${eventName} event`); if (!mounted) return; const logged = IAMService.isLoggedIn(); setAuthenticated(logged); if (logged) { setSessionExpired(false); try { const t = await IAMService.getToken(); const idt = IAMService.getIDToken(); setToken(t); setIdToken(idt); setTokenExp(IAMService.getTokenExp()); } catch (e) { console.error("[TideCloak Provider] Failed to update auth state", e); } } else { setSessionExpired(true); setToken(null); setIdToken(null); } }; const onInitError = (err) => { if (mounted) { setInitError(err); setIsInitializing(false); } }; const onTokenExpired = async () => { if (!mounted) return; console.debug("[TideCloak Provider] Token expired, attempting refresh..."); setSessionExpired(true); try { await IAMService.updateIAMToken(); } catch (refreshError) { console.error("[TideCloak Provider] Failed to refresh token:", refreshError); } }; IAMService .on('authSuccess', updateAuthState) .on('authError', updateAuthState) .on('authRefreshSuccess', updateAuthState) .on('authRefreshError', updateAuthState) .on('logout', updateAuthState) .on('tokenExpired', onTokenExpired) .on('initError', onInitError); setIsInitializing(true); (async () => { try { const loaded = await IAMService.loadConfig(config); ; if (!loaded) throw new Error("Invalid config"); setBaseURL(loaded['auth-server-url'].replace(/\/+$/, '')); await IAMService.initIAM(config, updateAuthState); if (!mounted) return; setIsInitializing(false); } catch (err) { onInitError(err); } })(); return () => { mounted = false; IAMService.off('ready', updateAuthState) .off('authSuccess', updateAuthState) .off('authError', updateAuthState) .off('authRefreshSuccess', updateAuthState) .off('authRefreshError', updateAuthState) .off('logout', updateAuthState) .off('tokenExpired', onTokenExpired) .off('initError', onInitError); }; }, [config, reloadKey]); if (isInitializing) return null; return (_jsx(TideCloakContext.Provider, { value: { isInitializing, initError, authenticated, sessionExpired, isRefreshing, token, idToken, tokenExp, baseURL, getConfig: () => IAMService.getConfig(), reload: () => setReloadKey(k => k + 1), login: () => IAMService.doLogin(), logout: () => IAMService.doLogout(), refreshToken: async () => { setIsRefreshing(true); try { return await IAMService.updateIAMToken(); } finally { setIsRefreshing(false); } }, forceRefreshToken: async () => { setIsRefreshing(true); try { return await IAMService.forceUpdateToken(); } finally { setIsRefreshing(false); } }, hasRealmRole: (role) => IAMService.hasRealmRole(role), hasClientRole: (role, resource) => IAMService.hasClientRole(role, resource), getValueFromToken: (key) => IAMService.getValueFromToken(key), getValueFromIdToken: (key) => IAMService.getValueFromIDToken(key), doEncrypt: async (data) => await IAMService.doEncrypt(data), doDecrypt: async (data) => await IAMService.doDecrypt(data) }, children: children })); } export function useTideCloakContext() { const ctx = React.useContext(TideCloakContext); if (!ctx) throw new Error("useTideCloakContext must be used within <TideCloakContextProvider>"); return ctx; }