elearning/Backend/src/middleware/authentication.ts
2026-01-09 06:28:15 +00:00

92 lines
2.5 KiB
TypeScript

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