123 lines
3.2 KiB
JavaScript
123 lines
3.2 KiB
JavaScript
const jwt = require('jsonwebtoken');
|
|
const axios = require('axios');
|
|
|
|
// JWT token verification middleware
|
|
const verifyToken = async (req, res, next) => {
|
|
try {
|
|
const token = req.headers.authorization?.split(' ')[1];
|
|
|
|
if (!token) {
|
|
return res.status(401).json({
|
|
success: false,
|
|
message: 'Access token required',
|
|
error: 'No token provided'
|
|
});
|
|
}
|
|
|
|
// Verify JWT token
|
|
const decoded = jwt.verify(token, process.env.JWT_SECRET);
|
|
req.user = decoded;
|
|
|
|
// Add user context to headers for downstream services
|
|
req.headers['x-user-id'] = decoded.id || decoded.userId;
|
|
req.headers['x-user-email'] = decoded.email;
|
|
req.headers['x-user-role'] = decoded.role || 'user';
|
|
|
|
next();
|
|
} catch (error) {
|
|
console.error('Token verification failed:', error.message);
|
|
|
|
if (error.name === 'TokenExpiredError') {
|
|
return res.status(401).json({
|
|
success: false,
|
|
message: 'Token expired',
|
|
error: 'Please login again'
|
|
});
|
|
}
|
|
|
|
if (error.name === 'JsonWebTokenError') {
|
|
return res.status(401).json({
|
|
success: false,
|
|
message: 'Invalid token',
|
|
error: 'Token verification failed'
|
|
});
|
|
}
|
|
|
|
return res.status(401).json({
|
|
success: false,
|
|
message: 'Authentication failed',
|
|
error: error.message
|
|
});
|
|
}
|
|
};
|
|
|
|
// Forward user context to downstream services
|
|
const forwardUserContext = (req, res, next) => {
|
|
if (req.user) {
|
|
// Add gateway headers for service identification
|
|
req.headers['x-gateway-request-id'] = req.requestId;
|
|
req.headers['x-gateway-timestamp'] = new Date().toISOString();
|
|
req.headers['x-forwarded-by'] = 'api-gateway';
|
|
req.headers['x-forwarded-for'] = req.ip;
|
|
req.headers['x-forwarded-proto'] = req.protocol;
|
|
req.headers['x-forwarded-host'] = req.get('host');
|
|
}
|
|
next();
|
|
};
|
|
|
|
// Optional token verification (doesn't fail if no token)
|
|
const verifyTokenOptional = async (req, res, next) => {
|
|
try {
|
|
const token = req.headers.authorization?.split(' ')[1];
|
|
|
|
if (token) {
|
|
const decoded = jwt.verify(token, process.env.JWT_SECRET);
|
|
req.user = decoded;
|
|
|
|
// Add user context to headers
|
|
req.headers['x-user-id'] = decoded.id || decoded.userId;
|
|
req.headers['x-user-email'] = decoded.email;
|
|
req.headers['x-user-role'] = decoded.role || 'user';
|
|
}
|
|
|
|
next();
|
|
} catch (error) {
|
|
// Continue without authentication for optional routes
|
|
console.log('Optional token verification failed:', error.message);
|
|
next();
|
|
}
|
|
};
|
|
|
|
// Role-based authorization middleware
|
|
const requireRole = (roles) => {
|
|
return (req, res, next) => {
|
|
if (!req.user) {
|
|
return res.status(401).json({
|
|
success: false,
|
|
message: 'Authentication required'
|
|
});
|
|
}
|
|
|
|
const userRole = req.user.role || 'user';
|
|
const allowedRoles = Array.isArray(roles) ? roles : [roles];
|
|
|
|
if (!allowedRoles.includes(userRole)) {
|
|
return res.status(403).json({
|
|
success: false,
|
|
message: 'Insufficient permissions',
|
|
required_roles: allowedRoles,
|
|
user_role: userRole
|
|
});
|
|
}
|
|
|
|
next();
|
|
};
|
|
};
|
|
|
|
module.exports = {
|
|
verifyToken,
|
|
forwardUserContext,
|
|
verifyTokenOptional,
|
|
requireRole
|
|
};
|