/** * OAuth Callback Page * Handles OAuth provider redirects and completes authentication */ import React, { useEffect, useState } from 'react'; import { useNavigate, useParams, useLocation } from 'react-router-dom'; import { Loader2, AlertCircle, CheckCircle } from 'lucide-react'; import { handleOAuthCallback } from '../api/oauth'; import { setCookie } from '../utils/cookies'; import { getCookieDomain, buildSubdomainUrl } from '../utils/domain'; import SmoothScheduleLogo from '../components/SmoothScheduleLogo'; const OAuthCallback: React.FC = () => { const [status, setStatus] = useState<'processing' | 'success' | 'error'>('processing'); const [errorMessage, setErrorMessage] = useState(''); const navigate = useNavigate(); const { provider } = useParams<{ provider: string }>(); const location = useLocation(); useEffect(() => { const processCallback = async () => { try { // Check if we're in a popup window const isPopup = window.opener && window.opener !== window; // Extract OAuth callback parameters // Try both query params and hash params (some providers use hash) const searchParams = new URLSearchParams(location.search); const hashParams = new URLSearchParams(location.hash.substring(1)); const code = searchParams.get('code') || hashParams.get('code'); const state = searchParams.get('state') || hashParams.get('state'); const error = searchParams.get('error') || hashParams.get('error'); const errorDescription = searchParams.get('error_description') || hashParams.get('error_description'); // Check for OAuth errors if (error) { const message = errorDescription || error || 'Authentication failed'; throw new Error(message); } // Validate required parameters if (!code || !state) { throw new Error('Missing required OAuth parameters'); } if (!provider) { throw new Error('Missing OAuth provider'); } // Exchange code for tokens const response = await handleOAuthCallback(provider, code, state); // Store tokens in cookies (accessible across subdomains) setCookie('access_token', response.access, 7); setCookie('refresh_token', response.refresh, 7); // Clear session cookie to prevent interference with JWT const cookieDomain = getCookieDomain(); document.cookie = `sessionid=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; domain=${cookieDomain}`; document.cookie = 'sessionid=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; setStatus('success'); // Determine redirect URL based on user role const user = response.user; const currentHostname = window.location.hostname; let targetUrl = '/'; let needsRedirect = false; let targetSubdomain: string | null = null; // Platform users (superuser, platform_manager, platform_support) if (['superuser', 'platform_manager', 'platform_support'].includes(user.role)) { targetSubdomain = 'platform'; } // Business users - redirect to their business subdomain else if (user.business_subdomain) { targetSubdomain = user.business_subdomain; } // Check if redirect is needed if (targetSubdomain) { const baseDomain = window.location.hostname.split('.').slice(-2).join('.'); const targetHostname = `${targetSubdomain}.${baseDomain}`; needsRedirect = currentHostname !== targetHostname; if (needsRedirect) { targetUrl = buildSubdomainUrl(targetSubdomain, '/'); } } // Handle popup vs redirect flows if (isPopup) { // Post message to parent window window.opener.postMessage( { type: 'oauth-success', provider, user: response.user, needsRedirect, targetUrl, }, window.location.origin ); // Close popup after short delay setTimeout(() => { window.close(); }, 1000); } else { // Standard redirect flow setTimeout(() => { if (needsRedirect) { // Redirect to different subdomain window.location.href = targetUrl; } else { // Navigate to dashboard on same subdomain navigate(targetUrl); } }, 1500); } } catch (err: any) { console.error('OAuth callback error:', err); setStatus('error'); setErrorMessage(err.message || 'Authentication failed. Please try again.'); // If in popup, post error to parent if (window.opener && window.opener !== window) { window.opener.postMessage( { type: 'oauth-error', provider, error: err.message || 'Authentication failed', }, window.location.origin ); // Close popup after delay setTimeout(() => { window.close(); }, 3000); } } }; processCallback(); }, [provider, location, navigate]); const handleTryAgain = () => { // Simply navigate to login on current subdomain navigate('/login'); }; return (
{/* Logo */}
Smooth Schedule
{/* Processing State */} {status === 'processing' && (

Completing Sign In...

Please wait while we authenticate your account

)} {/* Success State */} {status === 'success' && (

Authentication Successful!

Redirecting to your dashboard...

)} {/* Error State */} {status === 'error' && (

Authentication Failed

{errorMessage}

)} {/* Provider Info */} {provider && status === 'processing' && (

Authenticating with{' '} {provider}

)}
{/* Additional Help Text */} {status === 'error' && (

If the problem persists, please contact support

)}
); }; export default OAuthCallback;