Files
thrilltrack-explorer/supabase/functions/_shared/auth0Jwt.ts
gpt-engineer-app[bot] b2bf9a6e20 Implement Auth0 migration
2025-11-01 01:08:11 +00:00

72 lines
1.8 KiB
TypeScript

/**
* Auth0 JWT Verification Utility
*
* Provides JWT verification using Auth0 JWKS
*/
import { jwtVerify, createRemoteJWKSet, JWTPayload } from 'jose';
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<Auth0JWTPayload> {
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;
}