Re_Backend/src/middlewares/auth.middleware.ts

109 lines
3.0 KiB
TypeScript

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<void> => {
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<void> => {
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();
}
};