import { NextRequest, NextResponse } from 'next/server'; import { cookies } from 'next/headers'; import { createHmac } from 'node:crypto'; import { decryptSession } from '@/lib/auth/crypto'; import { sessionCookieName } from '@/lib/auth/session-cookie'; import { logger } from '@/lib/logger'; const JITSI_URL = (process.env.JITSI_URL || 'https://meet.src-advisory.com').replace(/\/+$/, ''); function base64url(input: Buffer): string { return input.toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''); } function b64u(input: string): string { return Buffer.from(input).toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''); } export async function POST(request: NextRequest) { try { const appId = process.env.JITSI_APP_ID; const appSecret = process.env.JITSI_APP_SECRET; if (!appId || !appSecret) { return NextResponse.json({ error: 'Jitsi is not configured' }, { status: 503 }); } const cookieStore = await cookies(); const sessionToken = cookieStore.get(sessionCookieName(0))?.value; if (!sessionToken) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } const session = decryptSession(sessionToken); if (!session) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } const email = session.username; const body = await request.json().catch(() => ({})); const room = typeof body.room === 'string' ? body.room.trim() : ''; if (!room || !/^[a-z0-9-]{1,100}$/i.test(room)) { return NextResponse.json({ error: 'Invalid room name' }, { status: 400 }); } const domain = new URL(JITSI_URL).hostname; const now = Math.floor(Date.now() / 1000); const header = { alg: 'HS256', typ: 'JWT' }; const payload = { iss: 'bulwark-webmail', sub: domain, aud: appId, room, iat: now, exp: now + 86400, context: { user: { email, name: email.split('@')[0], }, }, }; const signingInput = `${b64u(JSON.stringify(header))}.${b64u(JSON.stringify(payload))}`; const signature = createHmac('sha256', appSecret).update(signingInput).digest(); const token = `${signingInput}.${base64url(signature)}`; logger.info('Jitsi token issued', { room, email }); return NextResponse.json({ token, room, url: `${JITSI_URL}/${encodeURIComponent(room)}`, }); } catch (error) { const message = error instanceof Error ? error.message : 'Unknown error'; logger.error('Jitsi token issuance failed', { error: message }); return NextResponse.json({ error: message }, { status: 500 }); } }