import { Request, Response, NextFunction } from 'express'; import jwt from 'jsonwebtoken'; import { User } from '../models/User'; import { ssoConfig } from '../config/sso'; import { ResponseHandler } from '../utils/responseHandler'; interface JwtPayload { userId: string; employeeId: string; email: string; role: string; iat: number; exp: number; } export const authenticateToken = async ( req: Request, res: Response, next: NextFunction ): Promise => { try { // Try to get token from Authorization header first const authHeader = req.headers.authorization; let token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN // Fallback to cookie if available (requires cookie-parser middleware) if (!token && req.cookies?.accessToken) { token = req.cookies.accessToken; } if (!token) { ResponseHandler.unauthorized(res, 'Access token is required'); return; } // Verify JWT token const decoded = jwt.verify(token, ssoConfig.jwtSecret) as JwtPayload; // Fetch user from database to ensure they still exist and are active const user = await User.findByPk(decoded.userId); if (!user || !user.isActive) { ResponseHandler.unauthorized(res, 'User not found or inactive'); return; } // Attach user info to request object req.user = { userId: user.userId, email: user.email, employeeId: user.employeeId || null, // Optional - schema not finalized role: user.role // Keep uppercase: USER, MANAGEMENT, ADMIN }; next(); } catch (error: any) { if (error?.name === 'TokenExpiredError') { ResponseHandler.unauthorized(res, 'Token has expired'); } else if (error?.name === 'JsonWebTokenError') { ResponseHandler.unauthorized(res, 'Invalid token'); } else { const errorMessage = error instanceof Error ? error.message : 'Unknown error'; ResponseHandler.error(res, 'Authentication error', 500, errorMessage); } } }; export const requireAdmin = ( req: Request, res: Response, next: NextFunction ): void => { if (req.user?.role !== 'ADMIN') { ResponseHandler.forbidden(res, 'Admin access required'); return; } next(); }; export const optionalAuth = async ( req: Request, res: Response, next: NextFunction ): Promise => { try { const authHeader = req.headers.authorization; const token = authHeader && authHeader.split(' ')[1]; if (token) { const decoded = jwt.verify(token, ssoConfig.jwtSecret) as JwtPayload; const user = await User.findByPk(decoded.userId); if (user && user.isActive) { req.user = { userId: user.userId, email: user.email, employeeId: user.employeeId || null, // Optional - schema not finalized role: user.role // Keep uppercase: USER, MANAGEMENT, ADMIN }; } } next(); } catch (error) { // For optional auth, we don't throw errors, just continue without user next(); } };