From 152a90ae9d8c4d0980e3a65755f4ddaf5cb096a4 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Fri, 17 Oct 2025 19:06:35 +0000 Subject: [PATCH] feat: Improve MFA check reliability --- .../moderation/useModerationQueueManager.ts | 36 +++++++++++++++++++ src/hooks/useAuth.tsx | 1 + src/lib/authService.ts | 16 +++++++-- 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/hooks/moderation/useModerationQueueManager.ts b/src/hooks/moderation/useModerationQueueManager.ts index 2904c8dd..8b9db81e 100644 --- a/src/hooks/moderation/useModerationQueueManager.ts +++ b/src/hooks/moderation/useModerationQueueManager.ts @@ -93,6 +93,17 @@ export function useModerationQueueManager(config: ModerationQueueManagerConfig): const queryClient = useQueryClient(); const { aal } = useAuth(); + // Debug AAL status + useEffect(() => { + logger.log('🔐 [QUEUE MANAGER] AAL Status:', { + aal, + isNull: aal === null, + isAal1: aal === 'aal1', + isAal2: aal === 'aal2', + timestamp: new Date().toISOString() + }); + }, [aal]); + // Initialize sub-hooks const filters = useModerationFilters({ initialEntityFilter: "all", @@ -273,7 +284,30 @@ export function useModerationQueueManager(config: ModerationQueueManagerConfig): setActionLoading(item.id); // Check MFA (AAL2) requirement before moderation action + if (aal === null) { + logger.log('⏳ [QUEUE MANAGER] AAL is null, waiting for authentication status...'); + toast({ + title: "Loading Authentication Status", + description: "Please wait while we verify your authentication level...", + }); + setActionLoading(null); + + // Retry after 1 second + setTimeout(() => { + logger.log('🔄 [QUEUE MANAGER] Retrying action after AAL load'); + performAction(item, action, moderatorNotes); + }, 1000); + + return; + } + if (aal !== 'aal2') { + logger.warn('🚫 [QUEUE MANAGER] MFA check failed', { + aal, + expected: 'aal2', + userId: user?.id + }); + toast({ title: "MFA Verification Required", description: "You must complete multi-factor authentication to perform moderation actions.", @@ -283,6 +317,8 @@ export function useModerationQueueManager(config: ModerationQueueManagerConfig): return; } + logger.log('✅ [QUEUE MANAGER] MFA check passed', { aal }); + // Calculate stat delta for optimistic update const statDelta: Partial = {}; diff --git a/src/hooks/useAuth.tsx b/src/hooks/useAuth.tsx index 8365bbc9..69a92443 100644 --- a/src/hooks/useAuth.tsx +++ b/src/hooks/useAuth.tsx @@ -110,6 +110,7 @@ function AuthProviderComponent({ children }: { children: React.ReactNode }) { const currentAal = await getSessionAal(session); setAal(currentAal); authLog('[Auth] Current AAL:', currentAal); + console.log('🔐 [Auth] AAL SET:', currentAal); // Explicit console log for debugging } else { setAal(null); } diff --git a/src/lib/authService.ts b/src/lib/authService.ts index 673a67e6..8f6e20d5 100644 --- a/src/lib/authService.ts +++ b/src/lib/authService.ts @@ -19,17 +19,29 @@ import { setStepUpRequired, setAuthMethod, clearAllAuthFlags } from './sessionFl * Always returns ground truth from server, not cached session data */ export async function getSessionAal(session: Session | null): Promise { - if (!session) return 'aal1'; + if (!session) { + console.log('🔍 [AuthService] No session, returning aal1'); + return 'aal1'; + } try { const { data, error } = await supabase.auth.mfa.getAuthenticatorAssuranceLevel(); + console.log('🔍 [AuthService] getSessionAal result:', { + hasData: !!data, + currentLevel: data?.currentLevel, + nextLevel: data?.nextLevel, + error: error?.message + }); + if (error) { console.error('[AuthService] Error getting AAL:', error); return 'aal1'; } - return (data.currentLevel as AALLevel) || 'aal1'; + const level = (data.currentLevel as AALLevel) || 'aal1'; + console.log('🔐 [AuthService] Returning AAL:', level); + return level; } catch (error) { console.error('[AuthService] Exception getting AAL:', error); return 'aal1';