Files
thrilltrack-explorer/supabase/functions/check-mfa-enrollment/index.ts
2025-10-31 17:12:59 +00:00

85 lines
2.7 KiB
TypeScript

import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.57.4';
const corsHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
};
const supabaseUrl = Deno.env.get('SUPABASE_URL')!;
const supabaseServiceKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!;
Deno.serve(async (req) => {
if (req.method === 'OPTIONS') {
return new Response(null, { headers: corsHeaders });
}
try {
const authHeader = req.headers.get('Authorization');
if (!authHeader) {
return new Response(
JSON.stringify({ error: 'Missing authorization header' }),
{ status: 401, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
);
}
// Create client with user's token to verify session
const supabase = createClient(supabaseUrl, supabaseServiceKey, {
global: {
headers: { Authorization: authHeader },
},
auth: {
autoRefreshToken: false,
persistSession: false,
},
});
const { data: { user }, error: userError } = await supabase.auth.getUser();
if (userError || !user) {
console.error('User verification error:', userError);
return new Response(
JSON.stringify({ error: 'Unauthorized' }),
{ status: 401, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
);
}
// Create admin client to check MFA factors
const supabaseAdmin = createClient(supabaseUrl, supabaseServiceKey, {
auth: {
autoRefreshToken: false,
persistSession: false,
},
});
const { data: factors, error: factorsError } = await supabaseAdmin.auth.admin.mfa.listFactors({
userId: user.id,
});
if (factorsError) {
console.error('MFA factors check error:', factorsError);
return new Response(
JSON.stringify({ error: 'Failed to check MFA enrollment' }),
{ status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
);
}
const verifiedFactors = factors?.totp?.filter((f) => f.status === 'verified') || [];
const hasEnrolled = verifiedFactors.length > 0;
const factorId = verifiedFactors.length > 0 ? verifiedFactors[0].id : undefined;
return new Response(
JSON.stringify({
hasEnrolled,
factorId,
}),
{ status: 200, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
);
} catch (error) {
console.error('Unexpected error:', error);
return new Response(
JSON.stringify({ error: 'Internal server error' }),
{ status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
);
}
});