import { Request, Response, NextFunction } from 'express'; import { supabase } from '../../db/client'; import { logger } from '../../utils/logger'; /** Augmented Express Request with authenticated user fields */ export interface AuthenticatedRequest extends Request { userId: string; userEmail: string; } /** * Express middleware that verifies a Supabase JWT from the Authorization header. * On success, sets req.userId and req.userEmail for downstream handlers. * Returns 401 if the token is missing or invalid. */ export async function authenticateUser( req: Request, res: Response, next: NextFunction, ): Promise { const authHeader = req.headers.authorization; if (!authHeader || !authHeader.startsWith('Bearer ')) { res.status(401).json({ error: 'Missing or malformed Authorization header' }); return; } const token = authHeader.slice(7); // Strip "Bearer " try { const { data, error } = await supabase.auth.getUser(token); if (error || !data.user) { logger.warn('Auth verification failed', { error: error?.message }); res.status(401).json({ error: 'Invalid or expired token' }); return; } // Attach user info to the request (req as AuthenticatedRequest).userId = data.user.id; (req as AuthenticatedRequest).userEmail = data.user.email || ''; next(); } catch (err) { logger.error('Auth middleware unexpected error', { error: err instanceof Error ? err.message : String(err), }); res.status(401).json({ error: 'Authentication failed' }); } }