import { NextRequest } from 'next/server'; import { db } from '@/lib/db'; import { createHmac, randomBytes } from 'crypto'; // ============================================================ // JWT-like Token Management (Simple HMAC-based) // ============================================================ const JWT_SECRET = process.env.JWT_SECRET || 'socialconnect-secret-key-2024'; const TOKEN_EXPIRY = 24 * 60 * 60 * 1000; // 24 hours const REFRESH_TOKEN_EXPIRY = 7 * 24 * 60 * 60 * 1000; // 7 days interface TokenPayload { userId: string; email: string; role: string; exp: number; type: 'access' | 'refresh'; } function base64UrlEncode(data: string): string { return Buffer.from(data).toString('base64url'); } function base64UrlDecode(data: string): string { return Buffer.from(data, 'base64url').toString(); } export function generateToken(payload: Omit, type: 'access' | 'refresh' = 'access'): string { const exp = Date.now() + (type === 'refresh' ? REFRESH_TOKEN_EXPIRY : TOKEN_EXPIRY); const fullPayload: TokenPayload = { ...payload, exp, type }; const header = base64UrlEncode(JSON.stringify({ alg: 'HS256', typ: 'JWT' })); const payloadStr = base64UrlEncode(JSON.stringify(fullPayload)); const signature = createHmac('sha256', JWT_SECRET).update(`${header}.${payloadStr}`).digest('base64url'); return `${header}.${payloadStr}.${signature}`; } export function verifyToken(token: string): TokenPayload | null { try { const parts = token.split('.'); if (parts.length !== 3) return null; const [header, payload, signature] = parts; const expectedSignature = createHmac('sha256', JWT_SECRET).update(`${header}.${payload}`).digest('base64url'); if (signature !== expectedSignature) return null; const decoded = JSON.parse(base64UrlDecode(payload)) as TokenPayload; if (decoded.exp < Date.now()) return null; return decoded; } catch { return null; } } // ============================================================ // Password Hashing // ============================================================ export function hashPassword(password: string): string { const salt = randomBytes(16).toString('hex'); const hash = createHmac('sha256', salt).update(password).digest('hex'); return `${salt}:${hash}`; } export function verifyPassword(password: string, stored: string): boolean { const [salt, hash] = stored.split(':'); const verifyHash = createHmac('sha256', salt).update(password).digest('hex'); return hash === verifyHash; } // ============================================================ // Auth Middleware Helper // ============================================================ export interface AuthUser { userId: string; email: string; role: string; } export async function getAuthUser(request: NextRequest): Promise { const authHeader = request.headers.get('authorization'); if (!authHeader?.startsWith('Bearer ')) return null; const token = authHeader.substring(7); const payload = verifyToken(token); if (!payload) return null; // Verify user still exists and is active const user = await db.user.findUnique({ where: { id: payload.userId } }); if (!user || !user.isActive) return null; return { userId: user.id, email: user.email, role: user.role }; } export function requireRole(user: AuthUser | null, roles: string[]): AuthUser { if (!user) throw new Error('Authentication required'); if (!roles.includes(user.role)) throw new Error('Insufficient permissions'); return user; }