Files
thrilltrack-explorer/src-old/hooks/useSuperuserGuard.ts

73 lines
2.1 KiB
TypeScript

import { useAuth } from './useAuth';
import { useUserRole } from './useUserRole';
import { useRequireMFA } from './useRequireMFA';
/**
* Centralized AAL2 enforcement for all superuser actions
*
* This hook ensures that ALL superuser actions require AAL2 authentication
* if the user has MFA enrolled. It fails closed - blocking actions if
* AAL verification is uncertain.
*
* SECURITY PRINCIPLE: Superusers MUST verify MFA before performing
* privileged operations that could affect other users or system settings.
*/
export interface SuperuserGuardState {
// Core permissions
isSuperuser: boolean;
canPerformAction: boolean; // Only true if superuser AND has AAL2 (if MFA enrolled)
// AAL2 state
hasAAL2: boolean;
needsAAL2Verification: boolean; // True if has MFA but not at AAL2
isEnrolled: boolean;
// Loading states
loading: boolean;
// Current AAL level
aal: 'aal1' | 'aal2' | null;
}
/**
* Hook to check if current user can perform superuser actions
* Enforces AAL2 requirement when MFA is enrolled
*/
export function useSuperuserGuard(): SuperuserGuardState {
const { aal, loading: authLoading } = useAuth();
const { isSuperuser, loading: roleLoading } = useUserRole();
const {
hasMFA,
isEnrolled,
needsVerification,
loading: mfaLoading
} = useRequireMFA();
const loading = authLoading || roleLoading || mfaLoading;
const isSuperuserRole = isSuperuser();
const hasAAL2 = hasMFA; // hasMFA means AAL2 + enrolled
// CRITICAL: Superuser can only perform actions if:
// 1. They have superuser role, AND
// 2. Either (no MFA enrolled) OR (has AAL2)
// This fails closed - if uncertain about MFA state, block action
const canPerformAction = isSuperuserRole && (!isEnrolled || hasAAL2);
// User needs AAL2 verification if:
// - Is superuser
// - Has MFA enrolled
// - Currently at AAL1 (not AAL2)
const needsAAL2Verification = isSuperuserRole && isEnrolled && !hasAAL2;
return {
isSuperuser: isSuperuserRole,
canPerformAction,
hasAAL2,
needsAAL2Verification,
isEnrolled,
loading,
aal,
};
}