import { Request, Response, NextFunction } from 'express'; import jwt from 'jsonwebtoken'; import { config } from '../config'; import { JWTPayload } from '../types'; import { logger } from '../config/logger'; export interface AuthRequest extends Request { user?: JWTPayload; } export async function expressAuthentication( request: Request, securityName: string, scopes?: string[] ): Promise { if (securityName === 'jwt') { const token = request.headers.authorization?.replace('Bearer ', ''); if (!token) { throw new Error('No token provided'); } try { const decoded = jwt.verify(token, config.jwt.secret) as JWTPayload; // Check if user has required role if (scopes && scopes.length > 0) { if (!scopes.includes(decoded.roleCode)) { throw new Error('Insufficient permissions'); } } return decoded; } catch (error) { logger.error('JWT verification failed', { error }); throw new Error('Invalid token'); } } throw new Error('Unknown security name'); } export function authenticate(req: AuthRequest, res: Response, next: NextFunction) { const token = req.headers.authorization?.replace('Bearer ', ''); if (!token) { return res.status(401).json({ error: { code: 'UNAUTHORIZED', message: 'No token provided' } }); } try { const decoded = jwt.verify(token, config.jwt.secret) as JWTPayload; req.user = decoded; next(); } catch (error) { logger.error('Authentication failed', { error }); return res.status(401).json({ error: { code: 'UNAUTHORIZED', message: 'Invalid token' } }); } } export function authorize(...roles: string[]) { return (req: AuthRequest, res: Response, next: NextFunction) => { if (!req.user) { return res.status(401).json({ error: { code: 'UNAUTHORIZED', message: 'Not authenticated' } }); } if (roles.length > 0 && !roles.includes(req.user.roleCode)) { return res.status(403).json({ error: { code: 'FORBIDDEN', message: 'Insufficient permissions' } }); } next(); }; }