All files / features / auth CallbackPage.tsx

95.65% Statements 22/23
66.66% Branches 10/15
90% Functions 9/10
100% Lines 19/19

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60          7x 24x 7x   7x 5x   5x 3x     3x                   3x 3x 3x     2x       7x 2x     5x               2x 2x 2x     2x              
import { useEffect, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { useAuthStore } from './authStore'
 
export function CallbackPage() {
  const navigate = useNavigate()
  const setAuth = useAuthStore((s) => s.setAuth)
  const [error, setError] = useState<string | null>(null)
 
  useEffect(() => {
    fetch('/api/auth/session')
      .then((res) => {
        if (!res.ok) throw new Error('Session fetch failed')
        return res.json()
      })
      .then((data) => {
        setAuth(
          {
            sub: data.sub ?? '',
            preferred_username: data.preferred_username ?? data.sub ?? '',
            email: data.email ?? '',
            groups: data.groups ?? [],
          },
          data.expiresAt,
          data.idleExpiresAt,
        )
        const returnUrl = sessionStorage.getItem('returnUrl')
        sessionStorage.removeItem('returnUrl')
        navigate(returnUrl ?? '/', { replace: true })
      })
      .catch(() => {
        setError('Failed to complete authentication. Please try again.')
      })
  }, [navigate, setAuth])
 
  if (error) {
    return <CallbackError error={error} navigate={navigate} />
  }
 
  return (
    <div className="flex min-h-screen items-center justify-center">
      <p className="text-muted-foreground">Signing in...</p>
    </div>
  )
}
 
function CallbackError({ error, navigate }: { error: string; navigate: (path: string, opts?: { replace?: boolean }) => void }) {
  useEffect(() => {
    const timer = setTimeout(() => navigate('/login', { replace: true }), 3000)
    return () => clearTimeout(timer)
  }, [navigate])
 
  return (
    <div className="flex min-h-screen flex-col items-center justify-center gap-4">
      <p className="text-destructive">{error}</p>
      <p className="text-sm text-muted-foreground">Redirecting to login...</p>
    </div>
  )
}