import jwt from 'jsonwebtoken'; import { config } from './config'; export interface JitsiJWTPayload { context: { user: { id: string; name: string; email?: string; avatar?: string; }; features?: { livestreaming?: boolean | string; recording?: boolean | string; transcription?: boolean | string; 'outbound-call'?: boolean | string; 'sip-outbound-call'?: boolean | string; }; }; moderator?: boolean; aud: string; iss: string; sub: string; room: string; exp?: number; nbf?: number; } /** * Genera un JWT token para autenticación en Jitsi Meet * * @param userId - ID del usuario * @param userName - Nombre completo del usuario * @param email - Email del usuario (opcional) * @param roomName - Nombre de la sala de Jitsi * @param isModerator - Si el usuario tiene permisos de moderador * @param avatarUrl - URL del avatar del usuario (opcional) * @param expiresInSeconds - Tiempo de expiración en segundos (por defecto 2 horas) * @returns JWT token firmado */ export function generateJitsiToken( userId: string, userName: string, email: string | undefined, roomName: string, isModerator: boolean = false, avatarUrl?: string, expiresInSeconds: number = 7200 // 2 horas por defecto ): string { if (!config.jitsi.appId || !config.jitsi.appSecret) { throw new Error('Jitsi JWT credentials not configured'); } const now = Math.floor(Date.now() / 1000); const payload: JitsiJWTPayload = { context: { user: { id: userId, name: userName, email: email, avatar: avatarUrl, }, features: { livestreaming: isModerator ? 'true' : false, recording: isModerator ? 'true' : false, transcription: isModerator ? 'true' : false, }, }, moderator: isModerator, aud: config.jitsi.appId, // Debe coincidir con JWT_APP_ID en Jitsi iss: config.jitsi.appId, // Debe coincidir con JWT_APP_ID en Jitsi sub: config.jitsi.domain, // Tu dominio de Jitsi room: roomName, exp: now + expiresInSeconds, nbf: now - 10, // Not before: 10 segundos antes para compensar desincronización de relojes }; const token = jwt.sign(payload, config.jitsi.appSecret, { algorithm: 'HS256', header: { typ: 'JWT', alg: 'HS256', }, }); return token; } /** * Verifica si la configuración de Jitsi JWT está completa */ export function isJitsiJWTConfigured(): boolean { return !!( config.jitsi.useJWT && config.jitsi.appId && config.jitsi.appSecret && config.jitsi.domain ); }