mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-21 11:51:14 -05:00
75 lines
2.3 KiB
TypeScript
75 lines
2.3 KiB
TypeScript
import { useState, useEffect } from 'react';
|
|
import { useAuth } from './useAuth';
|
|
import { useRequireMFA } from './useRequireMFA';
|
|
import { getSessionAal } from '@/lib/authService';
|
|
import { logger } from '@/lib/logger';
|
|
import { handleNonCriticalError } from '@/lib/errorHandler';
|
|
|
|
/**
|
|
* Phase 3: Session Monitoring Hook
|
|
* Monitors AAL degradation and forces re-verification when needed
|
|
*
|
|
* This hook continuously checks the session's AAL level and detects
|
|
* if it degrades from AAL2 to AAL1, which can happen after token refresh
|
|
* or session expiry.
|
|
*/
|
|
export function useSessionMonitor() {
|
|
const { aal, session, user } = useAuth();
|
|
const { requiresMFA, isEnrolled } = useRequireMFA();
|
|
const [aalWarning, setAalWarning] = useState(false);
|
|
const [aalDegraded, setAalDegraded] = useState(false);
|
|
|
|
useEffect(() => {
|
|
if (!session || !user || !requiresMFA || !isEnrolled) {
|
|
setAalWarning(false);
|
|
setAalDegraded(false);
|
|
return;
|
|
}
|
|
|
|
// Check AAL every 60 seconds
|
|
const interval = setInterval(async () => {
|
|
try {
|
|
const currentAal = await getSessionAal(session);
|
|
|
|
// If AAL degraded from AAL2 to AAL1
|
|
if (currentAal === 'aal1' && aal === 'aal2') {
|
|
logger.warn('AAL degradation detected', {
|
|
userId: user.id,
|
|
previousAal: aal,
|
|
currentAal,
|
|
action: 'session_monitor'
|
|
});
|
|
|
|
// Show warning for 30 seconds
|
|
setAalWarning(true);
|
|
setAalDegraded(true);
|
|
|
|
// After 30 seconds, redirect to MFA step-up
|
|
setTimeout(() => {
|
|
logger.info('Forcing MFA step-up due to AAL degradation', {
|
|
userId: user.id,
|
|
action: 'session_monitor_redirect'
|
|
});
|
|
|
|
sessionStorage.setItem('mfa_step_up_required', 'true');
|
|
sessionStorage.setItem('mfa_intended_path', window.location.pathname);
|
|
window.location.href = '/auth';
|
|
}, 30000);
|
|
}
|
|
} catch (error: unknown) {
|
|
handleNonCriticalError(error, {
|
|
action: 'Session monitor check',
|
|
userId: user.id,
|
|
});
|
|
}
|
|
}, 60000);
|
|
|
|
return () => clearInterval(interval);
|
|
}, [session, aal, requiresMFA, isEnrolled, user]);
|
|
|
|
return {
|
|
aalWarning,
|
|
aalDegraded
|
|
};
|
|
}
|