UNPKG

web-vuln-scanner

Version:

Advanced, lightweight web vulnerability scanner with smart detection and easy-to-use interface

219 lines (188 loc) 5.7 kB
/** * JWT Token Management System * Enterprise-grade JWT token creation, validation, and management */ const jwt = require('jsonwebtoken'); const crypto = require('crypto'); const { ConfigManager } = require('../config/config-manager'); const { Logger } = require('../monitoring/logger'); class JWTManager { constructor() { this.config = ConfigManager.getInstance(); this.logger = new Logger(this.config.get('logging')); // Generate secure JWT secrets if not configured this.accessTokenSecret = this.config.get('auth.jwt.accessSecret') || this.generateSecret(); this.refreshTokenSecret = this.config.get('auth.jwt.refreshSecret') || this.generateSecret(); // Token expiration settings this.accessTokenExpiry = this.config.get('auth.jwt.accessExpiry', '15m'); this.refreshTokenExpiry = this.config.get('auth.jwt.refreshExpiry', '7d'); // Algorithm and options this.algorithm = this.config.get('auth.jwt.algorithm', 'HS256'); this.issuer = this.config.get('auth.jwt.issuer', 'web-vuln-scanner'); this.audience = this.config.get('auth.jwt.audience', 'web-vuln-scanner-api'); } /** * Generate a cryptographically secure secret */ generateSecret() { return crypto.randomBytes(64).toString('hex'); } /** * Create access token with user payload */ createAccessToken(user) { try { const payload = { userId: user.id, email: user.email, roles: user.roles || [], permissions: user.permissions || [], type: 'access' }; const options = { expiresIn: this.accessTokenExpiry, issuer: this.issuer, audience: this.audience, algorithm: this.algorithm, jwtid: crypto.randomUUID(), subject: user.id.toString() }; return jwt.sign(payload, this.accessTokenSecret, options); } catch (error) { this.logger.error('Failed to create access token', { error: error.message, userId: user.id }); throw new Error('Token creation failed'); } } /** * Create refresh token */ createRefreshToken(user) { try { const payload = { userId: user.id, type: 'refresh', tokenFamily: crypto.randomUUID() // For token rotation }; const options = { expiresIn: this.refreshTokenExpiry, issuer: this.issuer, audience: this.audience, algorithm: this.algorithm, jwtid: crypto.randomUUID(), subject: user.id.toString() }; return jwt.sign(payload, this.refreshTokenSecret, options); } catch (error) { this.logger.error('Failed to create refresh token', { error: error.message, userId: user.id }); throw new Error('Refresh token creation failed'); } } /** * Verify access token */ verifyAccessToken(token) { try { const options = { issuer: this.issuer, audience: this.audience, algorithms: [this.algorithm] }; const decoded = jwt.verify(token, this.accessTokenSecret, options); if (decoded.type !== 'access') { throw new Error('Invalid token type'); } return decoded; } catch (error) { this.logger.warn('Access token verification failed', { error: error.message }); throw new Error('Invalid access token'); } } /** * Verify refresh token */ verifyRefreshToken(token) { try { const options = { issuer: this.issuer, audience: this.audience, algorithms: [this.algorithm] }; const decoded = jwt.verify(token, this.refreshTokenSecret, options); if (decoded.type !== 'refresh') { throw new Error('Invalid token type'); } return decoded; } catch (error) { this.logger.warn('Refresh token verification failed', { error: error.message }); throw new Error('Invalid refresh token'); } } /** * Create token pair (access + refresh) */ createTokenPair(user) { return { accessToken: this.createAccessToken(user), refreshToken: this.createRefreshToken(user), tokenType: 'Bearer', expiresIn: this.accessTokenExpiry }; } /** * Decode token without verification (for debugging) */ decodeToken(token) { try { return jwt.decode(token, { complete: true }); } catch (error) { this.logger.error('Failed to decode token', { error: error.message }); return null; } } /** * Check if token is expired */ isTokenExpired(token) { try { const decoded = this.decodeToken(token); if (!decoded || !decoded.payload.exp) { return true; } return Date.now() >= decoded.payload.exp * 1000; } catch (error) { return true; } } /** * Extract user ID from token */ extractUserId(token) { try { const decoded = this.decodeToken(token); return decoded?.payload?.userId || null; } catch (error) { return null; } } /** * Blacklist token (requires external storage implementation) */ async blacklistToken(token, reason = 'manual_revocation') { const decoded = this.decodeToken(token); if (!decoded) { throw new Error('Invalid token format'); } const blacklistEntry = { jti: decoded.payload.jti, userId: decoded.payload.userId, exp: decoded.payload.exp, reason, timestamp: new Date() }; this.logger.info('Token blacklisted', blacklistEntry); // TODO: Store in database/cache // await this.tokenBlacklistStore.add(blacklistEntry); return blacklistEntry; } } module.exports = { JWTManager };