EverydayTech Platform - Developer Reference
Complete Source Code Documentation - All Applications
Loading...
Searching...
No Matches
auth.js
Go to the documentation of this file.
1/**
2 * @file JWT Authentication Middleware
3 * @module middleware/auth
4 * @description
5 * Express middleware for JWT token authentication. Validates Bearer tokens using
6 * JWT_SECRET (dashboard users) or AGENT_SIGN_KEY (agent enrollment). Extracts user
7 * information from token payload and attaches to req.user.
8 *
9 * Token verification precedence:
10 * 1. JWT_SECRET - Standard dashboard user authentication
11 * 2. AGENT_SIGN_KEY - Fallback for agent enrollment tokens
12 *
13 * Special cases:
14 * - /api/agent/enroll - Bypasses JWT_SECRET verification, only validates AGENT_SIGN_KEY
15 * - All other routes - Requires valid JWT from either key
16 *
17 * Token payload expects:
18 * - tenant_id: Tenant ID for multi-tenancy
19 * - Standard JWT claims (sub, iat, exp, etc.)
20 * @requires jsonwebtoken
21 * @see {@link https://jwt.io/} JWT specification
22 */
23
24const jwt = require('jsonwebtoken');
25
26/**
27 * Authenticates JWT token from Authorization header.
28 *
29 * Validates Bearer token using JWT_SECRET or AGENT_SIGN_KEY. Extracts user information
30 * and attaches to req.user. Bypasses JWT_SECRET verification for agent enrollment endpoint.
31 * @function authenticateToken
32 * @param {object} req - Express request object
33 * @param {object} req.headers - HTTP headers
34 * @param {string} req.headers.authorization - Bearer token (format: "Bearer <token>")
35 * @param {string} req.originalUrl - Original request URL (for enrollment bypass check)
36 * @param {object} res - Express response object
37 * @param {Function} next - Express next middleware function
38 * @returns {void} Calls next() on success, sends 401/403 on failure
39 * @throws {401} Access denied - Missing authorization header or token
40 * @throws {403} Invalid token - JWT verification failed for both keys
41 * @example
42 * // Apply to protected routes
43 * const authenticateToken = require('./middleware/auth');
44 * router.get('/protected', authenticateToken, (req, res) => {
45 * const userId = req.user.sub;
46 * const tenantId = req.user.tenantId;
47 * // Handle request...
48 * });
49 * @example
50 * // Request with valid token
51 * curl https://api.example.com/api/users \
52 * -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
53 */
54function authenticateToken(req, res, next) {
55 // Allow agent enrollment route to bypass JWT_SECRET verification
56 if (req.originalUrl === '/api/agent/enroll') {
57 return next();
58 }
59
60
61 // Default: JWT authentication for all other routes
62 const authHeader = req.headers['authorization'];
63 const token = authHeader && authHeader.split(' ')[1]; // Bearer <token>
64
65 if (!token) return res.status(401).send('Access denied');
66
67 // Try JWT_SECRET first, then AGENT_SIGN_KEY if verification fails
68 jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
69 if (!err) {
70 req.user = user;
71 req.user.tenantId = user.tenant_id || null;
72 return next();
73 }
74 // Try AGENT_SIGN_KEY
75 jwt.verify(token, process.env.AGENT_SIGN_KEY, (err2, user2) => {
76 if (!err2) {
77 req.user = user2;
78 req.user.tenantId = user2.tenant_id || null;
79 return next();
80 }
81 return res.status(403).send('Invalid token');
82 });
83 });
84}
85
86module.exports = authenticateToken;