import { useEffect, useRef, useState } from 'react' import { useNavigate } from 'react-router-dom' import { getPKCE, clearPKCE, storeToken, getState, clearState } from '../auth/oidc' import { api } from '../api/client' import { useAuthStore } from '../stores/auth' const CLIENT_ID = import.meta.env.VITE_OIDC_CLIENT_ID const REDIRECT_URI = import.meta.env.VITE_OIDC_REDIRECT_URI export default function CallbackPage() { const navigate = useNavigate() const { setUser, setError } = useAuthStore() const [status, setStatus] = useState('Processing authentication...') const isMounted = useRef(true) useEffect(() => { return () => { isMounted.current = false } }, []) useEffect(() => { const handleCallback = async () => { try { const urlParams = new URLSearchParams(window.location.search) const code = urlParams.get('code') const error = urlParams.get('error') const state = urlParams.get('state') const storedState = getState() if (error) { throw new Error(`Authentication error: ${error}`) } if (!code) { throw new Error('No authorization code received') } if (!state || state !== storedState) { throw new Error('Invalid or missing state parameter') } const verifier = getPKCE() if (!verifier) { throw new Error('PKCE verifier not found') } if (isMounted.current) { setStatus('Exchanging code for token...') } const tokenEndpoint = 'https://auth.commumedia.org/application/o/token/' const tokenResponse = await fetch(tokenEndpoint, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: new URLSearchParams({ grant_type: 'authorization_code', client_id: CLIENT_ID, code, redirect_uri: REDIRECT_URI, code_verifier: verifier, }), }) if (!tokenResponse.ok) { const errorData = await tokenResponse.json().catch(() => ({})) throw new Error(errorData.error_description || errorData.error || 'Token exchange failed') } const tokenData = await tokenResponse.json() storeToken(tokenData.access_token) clearPKCE() clearState() if (isMounted.current) { setStatus('Fetching user information...') } const user = await api.getCurrentUser() if (isMounted.current) { setUser(user) navigate('/') } } catch (error) { console.error('Callback error:', error) clearPKCE() clearState() if (isMounted.current) { setError(error instanceof Error ? error : new Error('Authentication failed')) setStatus('Authentication failed') setTimeout(() => navigate('/login'), 3000) } } } handleCallback() }, [navigate, setUser, setError]) return (

{status}

) }