import { createContext, useContext, useEffect, useMemo, useState } from 'react' import type { PropsWithChildren } from 'react' import { userManager } from './oidc' import type { User } from 'oidc-client-ts' interface AuthCtx { user: User | null isAuthenticated: boolean signIn: (returnTo?: string) => Promise signOut: () => Promise getAccessToken: () => string | null } const Ctx = createContext(null) export function AuthProvider({ children }: PropsWithChildren) { const [user, setUser] = useState(null) useEffect(() => { userManager.getUser().then(u => setUser(u)) const onLoaded = (u: User) => setUser(u) const onUnloaded = () => setUser(null) const onExpired = async () => { try { await userManager.signinSilent() } catch {/* ignore */} } userManager.events.addUserLoaded(onLoaded) userManager.events.addUserUnloaded(onUnloaded) userManager.events.addAccessTokenExpired(onExpired) return () => { userManager.events.removeUserLoaded(onLoaded) userManager.events.removeUserUnloaded(onUnloaded) userManager.events.removeAccessTokenExpired(onExpired) } }, []) // Spegla token till sessionStorage så ky kan läsa den // i useEffect som speglar token: useEffect(() => { const token = user?.access_token ?? null if (token) { sessionStorage.setItem('access_token', token) console.debug('access_token set') } else { sessionStorage.removeItem('access_token') } }, [user]) const api: AuthCtx = useMemo(() => ({ user, isAuthenticated: !!user && !user.expired, signIn: async (returnTo) => { await userManager.signinRedirect({ state: { returnTo } }) }, signOut: async () => { await userManager.signoutRedirect() }, getAccessToken: () => user?.access_token ?? null, }), [user]) return {children} } export function useAuth() { const ctx = useContext(Ctx) if (!ctx) throw new Error('useAuth must be used within ') return ctx }