/** * Auth0 JWT Verification Utility * * Provides JWT verification using Auth0 JWKS */ import { jwtVerify, createRemoteJWKSet, type JWTPayload } from 'https://esm.sh/jose@5.2.0'; const AUTH0_DOMAIN = Deno.env.get('AUTH0_DOMAIN') || ''; const AUTH0_CLIENT_ID = Deno.env.get('AUTH0_CLIENT_ID') || ''; /** * Extended JWT payload with Auth0-specific claims */ export interface Auth0JWTPayload extends JWTPayload { sub: string; email?: string; email_verified?: boolean; name?: string; picture?: string; 'https://thrillwiki.com/roles'?: string[]; amr?: string[]; // Authentication Methods Reference (includes 'mfa' if MFA verified) } /** * Verify Auth0 JWT token using JWKS */ export async function verifyAuth0Token(token: string): Promise { try { if (!AUTH0_DOMAIN || !AUTH0_CLIENT_ID) { throw new Error('Auth0 configuration missing'); } // Create JWKS fetcher const JWKS = createRemoteJWKSet( new URL(`https://${AUTH0_DOMAIN}/.well-known/jwks.json`) ); // Verify token const { payload } = await jwtVerify(token, JWKS, { issuer: `https://${AUTH0_DOMAIN}/`, audience: AUTH0_CLIENT_ID, }); return payload as Auth0JWTPayload; } catch (error) { console.error('[Auth0JWT] Verification failed:', error); throw new Error('Invalid Auth0 token'); } } /** * Extract roles from Auth0 JWT payload */ export function extractRoles(payload: Auth0JWTPayload): string[] { return payload['https://thrillwiki.com/roles'] || []; } /** * Check if user has verified MFA */ export function hasMFA(payload: Auth0JWTPayload): boolean { return payload.amr?.includes('mfa') || false; } /** * Extract user ID (sub) from payload */ export function getUserId(payload: Auth0JWTPayload): string { return payload.sub; }