Spaces:
Sleeping
Sleeping
File size: 1,559 Bytes
d5c9d40 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | 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<void> {
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' });
}
}
|