/** * Auth0 Get Management Token Edge Function * * Obtains Auth0 Management API access tokens for admin operations */ import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'; import { verifyAuth0Token, extractRoles } from '../_shared/auth0Jwt.ts'; const corsHeaders = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type', }; // In-memory cache for management token let cachedToken: string | null = null; let tokenExpiry: number = 0; serve(async (req) => { // Handle CORS preflight if (req.method === 'OPTIONS') { return new Response('ok', { headers: corsHeaders }); } try { // Verify user is authenticated const authHeader = req.headers.get('authorization'); if (!authHeader) { throw new Error('Missing authorization header'); } const token = authHeader.replace('Bearer ', ''); const payload = await verifyAuth0Token(token); // Check if user has admin/moderator role const roles = extractRoles(payload); const isAuthorized = roles.some(role => ['admin', 'moderator', 'superuser'].includes(role) ); if (!isAuthorized) { return new Response( JSON.stringify({ error: 'Unauthorized - admin role required' }), { headers: { ...corsHeaders, 'Content-Type': 'application/json' }, status: 403, } ); } // Check if cached token is still valid (5 min buffer) const now = Date.now() / 1000; if (cachedToken && tokenExpiry > now + 300) { return new Response( JSON.stringify({ access_token: cachedToken, token_type: 'Bearer', }), { headers: { ...corsHeaders, 'Content-Type': 'application/json' }, status: 200, } ); } // Get new management token const AUTH0_DOMAIN = Deno.env.get('AUTH0_DOMAIN')!; const M2M_CLIENT_ID = Deno.env.get('AUTH0_M2M_CLIENT_ID')!; const M2M_CLIENT_SECRET = Deno.env.get('AUTH0_M2M_CLIENT_SECRET')!; const response = await fetch(`https://${AUTH0_DOMAIN}/oauth/token`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ client_id: M2M_CLIENT_ID, client_secret: M2M_CLIENT_SECRET, audience: `https://${AUTH0_DOMAIN}/api/v2/`, grant_type: 'client_credentials', }), }); if (!response.ok) { throw new Error('Failed to get management token'); } const data = await response.json(); // Cache the token cachedToken = data.access_token; tokenExpiry = now + data.expires_in; return new Response( JSON.stringify({ access_token: data.access_token, token_type: data.token_type, expires_in: data.expires_in, }), { headers: { ...corsHeaders, 'Content-Type': 'application/json' }, status: 200, } ); } catch (error) { console.error('[Auth0ManagementToken] Error:', error); return new Response( JSON.stringify({ error: error.message }), { headers: { ...corsHeaders, 'Content-Type': 'application/json' }, status: 400, } ); } });