"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.jwtKeyManager = void 0; const crypto_1 = __importDefault(require("crypto")); const jsonwebtoken_1 = __importDefault(require("jsonwebtoken")); class JWTKeyManager { constructor() { this.previousSecret = null; this.rotationInterval = null; this.gracePeriodTimeout = null; console.log('๐Ÿ”‘ Initializing JWT Key Manager with automatic rotation'); this.currentSecret = this.generateSecret(); this.startRotation(); } generateSecret() { const secret = crypto_1.default.randomBytes(64).toString('hex'); console.log('๐Ÿ”„ Generated new JWT signing key (length:', secret.length, 'chars)'); return secret; } startRotation() { // Rotate every 24 hours (86400000 ms) this.rotationInterval = setInterval(() => { this.rotateKey(); }, 24 * 60 * 60 * 1000); console.log('โฐ JWT key rotation scheduled every 24 hours'); // Also rotate on startup after 1 hour to test the system setTimeout(() => { console.log('๐Ÿงช Performing initial key rotation test...'); this.rotateKey(); }, 60 * 60 * 1000); // 1 hour } rotateKey() { console.log('๐Ÿ”„ Rotating JWT signing key...'); // Store current secret as previous this.previousSecret = this.currentSecret; // Generate new current secret this.currentSecret = this.generateSecret(); console.log('โœ… JWT key rotation completed. Grace period: 24 hours'); // Clear any existing grace period timeout if (this.gracePeriodTimeout) { clearTimeout(this.gracePeriodTimeout); } // Clean up previous secret after 24 hours (grace period) this.gracePeriodTimeout = setTimeout(() => { this.previousSecret = null; console.log('๐Ÿงน Grace period ended. Previous JWT key cleaned up'); }, 24 * 60 * 60 * 1000); } generateToken(user) { const payload = { id: user.id, google_id: user.google_id, email: user.email, name: user.name, profile_picture_url: user.profile_picture_url, role: user.role, status: user.status, approval_status: user.approval_status, onboardingData: user.onboardingData, iat: Math.floor(Date.now() / 1000) // Issued at time }; return jsonwebtoken_1.default.sign(payload, this.currentSecret, { expiresIn: '24h', issuer: 'vip-coordinator', audience: 'vip-coordinator-users' }); } verifyToken(token) { try { // Try current secret first const decoded = jsonwebtoken_1.default.verify(token, this.currentSecret, { issuer: 'vip-coordinator', audience: 'vip-coordinator-users' }); return { id: decoded.id, google_id: decoded.google_id, email: decoded.email, name: decoded.name, profile_picture_url: decoded.profile_picture_url, role: decoded.role, status: decoded.status, approval_status: decoded.approval_status, onboardingData: decoded.onboardingData }; } catch (error) { // Try previous secret during grace period if (this.previousSecret) { try { const decoded = jsonwebtoken_1.default.verify(token, this.previousSecret, { issuer: 'vip-coordinator', audience: 'vip-coordinator-users' }); console.log('๐Ÿ”„ Token verified using previous key (grace period)'); return { id: decoded.id, google_id: decoded.google_id, email: decoded.email, name: decoded.name, profile_picture_url: decoded.profile_picture_url, role: decoded.role, status: decoded.status, approval_status: decoded.approval_status, onboardingData: decoded.onboardingData }; } catch (gracePeriodError) { console.log('โŒ Token verification failed with both current and previous keys'); return null; } } console.log('โŒ Token verification failed:', error instanceof Error ? error.message : 'Unknown error'); return null; } } // Get status for monitoring/debugging getStatus() { return { hasCurrentKey: !!this.currentSecret, hasPreviousKey: !!this.previousSecret, rotationActive: !!this.rotationInterval, gracePeriodActive: !!this.gracePeriodTimeout }; } // Cleanup on shutdown destroy() { console.log('๐Ÿ›‘ Shutting down JWT Key Manager...'); if (this.rotationInterval) { clearInterval(this.rotationInterval); this.rotationInterval = null; } if (this.gracePeriodTimeout) { clearTimeout(this.gracePeriodTimeout); this.gracePeriodTimeout = null; } console.log('โœ… JWT Key Manager shutdown complete'); } // Manual rotation for testing/emergency forceRotation() { console.log('๐Ÿšจ Manual key rotation triggered'); this.rotateKey(); } } // Singleton instance exports.jwtKeyManager = new JWTKeyManager(); // Graceful shutdown handling process.on('SIGTERM', () => { exports.jwtKeyManager.destroy(); }); process.on('SIGINT', () => { exports.jwtKeyManager.destroy(); }); exports.default = exports.jwtKeyManager; //# sourceMappingURL=jwtKeyManager.js.map