/** * Server-side auth utilities — proxies to platform-service for token verification. * Used by Next.js API routes only (never imported in client components). * * All JWT signing/verification is handled by platform-service (single auth source). * This module provides helper functions that verify tokens via platform-service * and return a lightweight UserDoc for use in API route guards. */ import { hashPassword, verifyPassword } from '@bytelyst/auth'; import { getMeViaService } from '@/lib/platform-client'; export { hashPassword, verifyPassword }; export interface UserDoc { id: string; email: string; name: string; role: string; plan: string; status?: string; } /** * Get the current user from an Authorization header value. * Verifies the token via platform-service /auth/me. */ export async function getCurrentUser(authHeader: string | null): Promise { if (!authHeader?.startsWith('Bearer ')) return null; const token = authHeader.slice(7); try { const user = await getMeViaService(token); return { id: user.id, email: user.email, name: user.displayName, role: user.role, plan: user.plan, }; } catch { return null; } } /** * Get the current user from a Request object. * Checks cookies first (Next.js httpOnly cookie), then Authorization header. * Returns null if not authenticated. */ export async function getCurrentUserFromRequest(request: Request): Promise { const cookieHeader = request.headers.get('cookie') || ''; const tokenMatch = cookieHeader.match(/(?:^|;\s*)token=([^;]+)/); const authHeader = request.headers.get('authorization'); if (tokenMatch) { return getCurrentUser(`Bearer ${tokenMatch[1]}`); } if (authHeader) { return getCurrentUser(authHeader); } return null; } /** * Require an admin user from the request. Checks cookies first, then Authorization header. * Throws Error("Unauthorized") if not authenticated or not admin/super_admin role. */ export async function requireAdmin(request: Request): Promise { // Try cookie first (Next.js httpOnly cookie), then Authorization header const cookieHeader = request.headers.get('cookie') || ''; const tokenMatch = cookieHeader.match(/(?:^|;\s*)token=([^;]+)/); const authHeader = request.headers.get('authorization'); let user: UserDoc | null = null; if (tokenMatch) { user = await getCurrentUser(`Bearer ${tokenMatch[1]}`); } else if (authHeader) { user = await getCurrentUser(authHeader); } if (!user) throw new Error('Unauthorized'); if (!['admin', 'super_admin'].includes(user.role)) throw new Error('Unauthorized'); return user; }