mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-21 10:31:13 -05:00
feat: Implement MFA Step-Up for OAuth
This commit is contained in:
@@ -5,6 +5,12 @@ import type { Profile } from '@/types/database';
|
||||
import { toast } from '@/hooks/use-toast';
|
||||
import { authLog, authWarn, authError } from '@/lib/authLogger';
|
||||
|
||||
export interface CheckAalResult {
|
||||
needsStepUp: boolean;
|
||||
hasMfaEnrolled: boolean;
|
||||
currentLevel: 'aal1' | 'aal2' | null;
|
||||
}
|
||||
|
||||
interface AuthContextType {
|
||||
user: User | null;
|
||||
session: Session | null;
|
||||
@@ -15,6 +21,7 @@ interface AuthContextType {
|
||||
signOut: () => Promise<void>;
|
||||
verifySession: () => Promise<boolean>;
|
||||
clearPendingEmail: () => void;
|
||||
checkAalStepUp: () => Promise<CheckAalResult>;
|
||||
}
|
||||
|
||||
const AuthContext = createContext<AuthContextType | undefined>(undefined);
|
||||
@@ -221,6 +228,29 @@ function AuthProviderComponent({ children }: { children: React.ReactNode }) {
|
||||
setPendingEmail(null);
|
||||
};
|
||||
|
||||
const checkAalStepUp = async (): Promise<CheckAalResult> => {
|
||||
if (!session?.user) {
|
||||
return { needsStepUp: false, hasMfaEnrolled: false, currentLevel: null };
|
||||
}
|
||||
|
||||
try {
|
||||
const { data: { currentLevel } } =
|
||||
await supabase.auth.mfa.getAuthenticatorAssuranceLevel();
|
||||
|
||||
const { data: factors } = await supabase.auth.mfa.listFactors();
|
||||
const hasMfaEnrolled = factors?.totp?.some(f => f.status === 'verified') || false;
|
||||
|
||||
return {
|
||||
needsStepUp: hasMfaEnrolled && currentLevel === 'aal1',
|
||||
hasMfaEnrolled,
|
||||
currentLevel: currentLevel as 'aal1' | 'aal2' | null,
|
||||
};
|
||||
} catch (error) {
|
||||
authError('[Auth] Failed to check AAL status:', error);
|
||||
return { needsStepUp: false, hasMfaEnrolled: false, currentLevel: null };
|
||||
}
|
||||
};
|
||||
|
||||
const value = {
|
||||
user,
|
||||
session,
|
||||
@@ -231,6 +261,7 @@ function AuthProviderComponent({ children }: { children: React.ReactNode }) {
|
||||
signOut,
|
||||
verifySession,
|
||||
clearPendingEmail,
|
||||
checkAalStepUp,
|
||||
};
|
||||
|
||||
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
|
||||
|
||||
Reference in New Issue
Block a user