import { Request, Response, NextFunction } from 'express'; import jwt from 'jsonwebtoken'; export interface JwtPayload { userId: string; email: string; } export interface AuthenticatedRequest extends Request { user?: JwtPayload; } // JWT configuration with environment validation const JWT_SECRET_ENV = process.env.JWT_SECRET; if (!JWT_SECRET_ENV) { throw new Error('FATAL: JWT_SECRET environment variable is required. Set it in .env file.'); } export const JWT_SECRET = JWT_SECRET_ENV; export const JWT_EXPIRES_IN = process.env.JWT_EXPIRES_IN || '7d'; export const JWT_REFRESH_EXPIRES_IN = process.env.JWT_REFRESH_EXPIRES_IN || '30d'; // Verify JWT token middleware export const authenticateToken = ( req: AuthenticatedRequest, res: Response, next: NextFunction ) => { const authHeader = req.headers['authorization']; const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN if (!token) { return res.status(401).json({ error: 'Authentication required' }); } try { const decoded = jwt.verify(token, JWT_SECRET) as JwtPayload; req.user = decoded; next(); } catch (error) { return res.status(403).json({ error: 'Invalid or expired token' }); } }; // Generate access token export const generateAccessToken = (payload: JwtPayload): string => { return jwt.sign(payload, JWT_SECRET, { expiresIn: JWT_EXPIRES_IN, }); }; // Generate refresh token export const generateRefreshToken = (payload: JwtPayload): string => { return jwt.sign(payload, JWT_SECRET, { expiresIn: JWT_REFRESH_EXPIRES_IN, }); }; // Verify refresh token export const verifyRefreshToken = (token: string): JwtPayload | null => { try { return jwt.verify(token, JWT_SECRET) as JwtPayload; } catch { return null; } };