Files
thrilltrack-explorer/supabase/functions/auth0-get-management-token/index.ts
gpt-engineer-app[bot] b2bf9a6e20 Implement Auth0 migration
2025-11-01 01:08:11 +00:00

115 lines
3.2 KiB
TypeScript

/**
* 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,
}
);
}
});