import { randomBytes } from 'crypto'; export interface IssuedToken { token: string; userId: string; username: string; displayName: string; signalingServerUrl: string; issuedAt: number; expiresAt: number; } const TOKEN_TTL_MS = 24 * 60 * 60 * 1000; const tokens = new Map(); export function issueToken(params: { userId: string; username: string; displayName: string; signalingServerUrl: string; }): IssuedToken { const token = randomBytes(32).toString('hex'); const issuedAt = Date.now(); const issued: IssuedToken = { token, issuedAt, expiresAt: issuedAt + TOKEN_TTL_MS, userId: params.userId, username: params.username, displayName: params.displayName, signalingServerUrl: params.signalingServerUrl }; tokens.set(token, issued); return issued; } export function consumeToken(token: string): IssuedToken | null { const issued = tokens.get(token); if (!issued) { return null; } if (issued.expiresAt < Date.now()) { tokens.delete(token); return null; } return issued; } export function revokeToken(token: string): void { tokens.delete(token); } export function clearAllTokens(): void { tokens.clear(); } export function pruneExpiredTokens(): void { const now = Date.now(); for (const [token, issued] of tokens) { if (issued.expiresAt < now) { tokens.delete(token); } } }