72 lines
2.5 KiB
TypeScript

// backend/middleware/auth.ts
import logger from '../utils/logger';
import { Request, Response, NextFunction } from 'express';
import jwt, { JwtPayload } from 'jsonwebtoken';
import { Pool } from 'mysql2/promise';
// Extend Request to include a user property
declare module 'express-serve-static-core' {
interface Request {
user?: { id: number; username: string; role: string } | null;
}
}
export const authMiddleware = (pool: Pool) => async (req: Request, res: Response, next: NextFunction) => {
try {
logger.info("Auth middleware triggered");
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Bearer ')) {
logger.warn("Authorization header missing or invalid:", { authHeader });
return res.status(401).json({ message: 'Authorization header missing or invalid' });
}
const token = authHeader.split(' ')[1];
const jwtSecret = process.env.JWT_SECRET;
if (!jwtSecret) {
throw new Error("JWT_SECRET is not set in environment variables");
}
let decoded: JwtPayload;
try {
decoded = jwt.verify(token, jwtSecret) as JwtPayload;
} catch (error: unknown) {
logger.error("JWT verification failed:", error);
if (error instanceof jwt.TokenExpiredError) {
return res.status(401).json({
message: 'Access token expired',
code: 'TOKEN_EXPIRED',
});
}
return res.status(401).json({ message: 'Invalid token', code: 'INVALID_TOKEN' });
}
const userId = decoded.userId;
if (!userId || typeof userId !== 'number') {
logger.warn("Invalid or missing userId in token payload:", { decoded });
return res.status(401).json({ message: 'Invalid token payload' });
}
try {
const [rows] = await pool.execute(
'SELECT id, username, role FROM users WHERE id = ? AND status = "active"',
[userId]
);
const users = Array.isArray(rows) ? rows : [];
if (users.length === 0) {
logger.warn("User not found or inactive:", { userId });
return res.status(401).json({ message: 'User not found or inactive' });
}
req.user = users[0] as { id: number; username: string; role: string };
next();
} catch (dbError) {
logger.error("Database query failed:", dbError);
return res.status(500).json({ message: 'Database query error' });
}
} catch (error: unknown) {
logger.error('Error in authMiddleware:', error);
res.status(500).json({ message: 'Internal server error' });
}
};