Files
Nexus_Mat/lib/middleware/authMiddleware.ts

90 lines
2.3 KiB
TypeScript

import { NextApiRequest, NextApiResponse } from 'next';
import { verifyToken } from '../auth';
import { UserService } from '../../backend/services/userService';
import { UserDTO } from '../../types';
// Extend NextApiRequest to include user property
export interface AuthenticatedRequest extends NextApiRequest {
user?: UserDTO;
}
/**
* Middleware to require authentication
* Returns 401 if no valid token is found
*/
export async function requireAuth(
req: AuthenticatedRequest,
res: NextApiResponse
): Promise<boolean> {
const token = getTokenFromRequest(req);
if (!token) {
res.status(401).json({ success: false, error: 'Authentication required' });
return false;
}
const decoded = verifyToken(token);
if (!decoded) {
res.status(401).json({ success: false, error: 'Invalid or expired token' });
return false;
}
// Load user from database
const user = await UserService.getUserById(decoded.userId);
if (!user) {
res.status(401).json({ success: false, error: 'User not found' });
return false;
}
// Check if user is banned
if (user.status === 'BANNED') {
res.status(403).json({ success: false, error: 'Account has been banned' });
return false;
}
// Attach user to request
req.user = user;
return true;
}
/**
* Middleware for optional authentication
* Attaches user to request if valid token exists, but doesn't fail if not
*/
export async function optionalAuth(req: AuthenticatedRequest): Promise<void> {
const token = getTokenFromRequest(req);
if (!token) {
return;
}
const decoded = verifyToken(token);
if (!decoded) {
return;
}
const user = await UserService.getUserById(decoded.userId);
if (user && user.status !== 'BANNED') {
req.user = user;
}
}
/**
* Extract JWT token from request
* Checks both cookies and Authorization header
*/
function getTokenFromRequest(req: NextApiRequest): string | null {
// Check cookie first
if (req.cookies.token) {
return req.cookies.token;
}
// Check Authorization header
const authHeader = req.headers.authorization;
if (authHeader && authHeader.startsWith('Bearer ')) {
return authHeader.substring(7);
}
return null;
}