codenuk_backend_mine/services/api-gateway/src/middleware/authentication.js
2025-09-03 10:47:50 +05:30

139 lines
4.4 KiB
JavaScript

const jwt = require('jsonwebtoken');
const axios = require('axios');
// JWT token verification middleware
const verifyToken = async (req, res, next) => {
try {
const authHeader = req.headers.authorization;
console.log('🔐 [API Gateway] Authorization header:', authHeader ? 'Present' : 'Missing');
const token = authHeader?.split(' ')[1];
console.log('🔐 [API Gateway] Token extracted:', token ? `${token.substring(0, 20)}...` : 'None');
if (!token) {
console.log('❌ [API Gateway] No token provided');
return res.status(401).json({
success: false,
message: 'Access token required',
error: 'No token provided'
});
}
// Verify JWT token using the same secret as the auth service
const jwtSecret = process.env.JWT_ACCESS_SECRET || process.env.JWT_SECRET || 'access-secret-key-2024-tech4biz';
console.log('🔐 [API Gateway] Verifying token with secret:', jwtSecret.substring(0, 20) + '...');
console.log('🔐 [API Gateway] Environment JWT_ACCESS_SECRET:', process.env.JWT_ACCESS_SECRET ? 'Set' : 'Not set');
console.log('🔐 [API Gateway] Environment JWT_SECRET:', process.env.JWT_SECRET ? 'Set' : 'Not set');
const decoded = jwt.verify(token, jwtSecret);
console.log('✅ [API Gateway] Token verified successfully for user:', decoded.id || decoded.userId);
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('❌ [API Gateway] Token verification failed:', error.message);
console.error('❌ [API Gateway] Error type:', error.name);
console.error('❌ [API Gateway] Error stack:', error.stack);
if (error.name === 'TokenExpiredError') {
console.log('❌ [API Gateway] Token expired');
return res.status(401).json({
success: false,
message: 'Token expired',
error: 'Please login again'
});
}
if (error.name === 'JsonWebTokenError') {
console.log('❌ [API Gateway] Invalid token format or signature');
return res.status(401).json({
success: false,
message: 'Invalid token',
error: 'Token verification failed'
});
}
console.log('❌ [API Gateway] General authentication error');
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
};