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 };