CSRF protection in enterprise applications needs to consider multiple aspects such as architecture, performance, scalability, and compliance to ensure effective security protection in complex environments.
Enterprise-Level CSRF Protection Architecture
1. Centralized Token Management
javascript// Centralized Token Service class CentralizedTokenService { constructor(redisClient) { this.redis = redisClient; this.tokenExpiry = 3600; // 1 hour } async generateToken(userId) { const token = crypto.randomBytes(32).toString('hex'); const key = `csrf:${userId}:${token}`; await this.redis.setex(key, this.tokenExpiry, '1'); return token; } async validateToken(userId, token) { const key = `csrf:${userId}:${token}`; const exists = await this.redis.exists(key); if (exists) { // Delete Token after successful validation (one-time use) await this.redis.del(key); return true; } return false; } async revokeUserTokens(userId) { const pattern = `csrf:${userId}:*`; const keys = await this.redis.keys(pattern); if (keys.length > 0) { await this.redis.del(...keys); } } }
2. CSRF Protection in Distributed Environments
javascript// Distributed CSRF Protection Middleware class DistributedCSRFProtection { constructor(tokenService, config) { this.tokenService = tokenService; this.config = config; } middleware() { return async (req, res, next) => { // Skip safe methods if (['GET', 'HEAD', 'OPTIONS'].includes(req.method)) { return next(); } // Get user ID const userId = this.getUserId(req); if (!userId) { return res.status(401).send('Unauthorized'); } // Validate Token const token = this.extractToken(req); if (!token) { return res.status(403).send('CSRF Token required'); } const isValid = await this.tokenService.validateToken(userId, token); if (!isValid) { return res.status(403).send('Invalid CSRF Token'); } next(); }; } getUserId(req) { // Get user ID from Session or JWT return req.user?.id || req.session?.userId; } extractToken(req) { // Extract Token from request header or body return req.headers['x-csrf-token'] || req.body._csrf; } }
Performance Optimization Strategies
1. Token Caching
javascript// Use Redis to cache Tokens class CachedTokenService { constructor(redisClient, localCache) { this.redis = redisClient; this.localCache = localCache; this.ttl = 3600; } async getToken(userId) { // First check local cache const cachedToken = this.localCache.get(`csrf:${userId}`); if (cachedToken) { return cachedToken; } // Get from Redis const token = await this.redis.get(`csrf:${userId}`); if (token) { this.localCache.set(`csrf:${userId}`, token, this.ttl); return token; } // Generate new Token const newToken = crypto.randomBytes(32).toString('hex'); await this.redis.setex(`csrf:${userId}`, this.ttl, newToken); this.localCache.set(`csrf:${userId}`, newToken, this.ttl); return newToken; } }
2. Batch Token Validation
javascript// Batch validate Tokens for multiple requests class BatchTokenValidator { constructor(tokenService) { this.tokenService = tokenService; this.batchSize = 100; } async validateBatch(requests) { const results = []; for (let i = 0; i < requests.length; i += this.batchSize) { const batch = requests.slice(i, i + this.batchSize); const batchResults = await Promise.all( batch.map(req => this.validateSingle(req)) ); results.push(...batchResults); } return results; } async validateSingle(request) { const { userId, token } = request; const isValid = await this.tokenService.validateToken(userId, token); return { userId, token, isValid, timestamp: Date.now() }; } }
High Availability Design
1. Token Service Redundancy
javascript// Load balancing for multiple Token services class RedundantTokenService { constructor(services) { this.services = services; this.currentService = 0; } async generateToken(userId) { const service = this.getNextService(); try { return await service.generateToken(userId); } catch (error) { // Try next service return await this.generateTokenWithRetry(userId, 3); } } async generateTokenWithRetry(userId, retries) { for (let i = 0; i < retries; i++) { const service = this.getNextService(); try { return await service.generateToken(userId); } catch (error) { if (i === retries - 1) { throw error; } } } } getNextService() { const service = this.services[this.currentService]; this.currentService = (this.currentService + 1) % this.services.length; return service; } }
2. Failover
javascript// Failure detection and failover class FailoverTokenService { constructor(primaryService, backupService) { this.primary = primaryService; this.backup = backupService; this.isPrimaryHealthy = true; this.healthCheckInterval = 30000; // 30 seconds } startHealthCheck() { setInterval(async () => { try { await this.primary.ping(); this.isPrimaryHealthy = true; } catch (error) { console.error('Primary service unhealthy:', error); this.isPrimaryHealthy = false; } }, this.healthCheckInterval); } async generateToken(userId) { if (this.isPrimaryHealthy) { try { return await this.primary.generateToken(userId); } catch (error) { console.error('Primary service failed, using backup:', error); return await this.backup.generateToken(userId); } } return await this.backup.generateToken(userId); } }
Compliance and Auditing
1. Audit Logging
javascript// CSRF Operation Audit Logging class CSRFAuditLogger { constructor(logService) { this.logService = logService; } async logTokenGeneration(userId, token, metadata) { const auditLog = { event: 'CSRF_TOKEN_GENERATED', userId, tokenHash: this.hashToken(token), timestamp: new Date().toISOString(), metadata: { ip: metadata.ip, userAgent: metadata.userAgent, sessionId: metadata.sessionId } }; await this.logService.log(auditLog); } async logTokenValidation(userId, token, isValid, metadata) { const auditLog = { event: 'CSRF_TOKEN_VALIDATED', userId, tokenHash: this.hashToken(token), isValid, timestamp: new Date().toISOString(), metadata: { ip: metadata.ip, userAgent: metadata.userAgent, sessionId: metadata.sessionId, requestPath: metadata.requestPath } }; await this.logService.log(auditLog); } hashToken(token) { return crypto.createHash('sha256').update(token).digest('hex'); } }
2. Compliance Reporting
javascript// Generate compliance reports class ComplianceReportGenerator { constructor(auditLogger) { this.auditLogger = auditLogger; } async generateReport(startDate, endDate) { const logs = await this.auditLogger.getLogs(startDate, endDate); return { summary: { totalTokensGenerated: logs.filter(l => l.event === 'CSRF_TOKEN_GENERATED').length, totalValidations: logs.filter(l => l.event === 'CSRF_TOKEN_VALIDATED').length, failedValidations: logs.filter(l => l.event === 'CSRF_TOKEN_VALIDATED' && !l.isValid).length, uniqueUsers: new Set(logs.map(l => l.userId)).size }, failedAttempts: this.analyzeFailedAttempts(logs), suspiciousActivity: this.detectSuspiciousActivity(logs), complianceStatus: this.checkCompliance(logs) }; } analyzeFailedAttempts(logs) { const failedLogs = logs.filter(l => l.event === 'CSRF_TOKEN_VALIDATED' && !l.isValid); return { byUser: this.groupBy(failedLogs, 'userId'), byIP: this.groupBy(failedLogs, l => l.metadata.ip), byTime: this.groupByTime(failedLogs) }; } detectSuspiciousActivity(logs) { const suspicious = []; // Detect abnormal validation failure rates const userFailureRates = this.calculateUserFailureRates(logs); Object.entries(userFailureRates).forEach(([userId, rate]) => { if (rate > 0.5) { // Failure rate over 50% suspicious.push({ type: 'HIGH_FAILURE_RATE', userId, rate }); } }); return suspicious; } checkCompliance(logs) { // Check if security standards are met const checks = { hasAuditLogs: logs.length > 0, hasTokenExpiry: true, // Need to check from configuration hasSecureTransmission: true, // Need to check from configuration hasProperValidation: true }; return { compliant: Object.values(checks).every(v => v), checks }; } }
Monitoring and Alerting
1. Real-time Monitoring
javascript// CSRF Attack Real-time Monitoring class CSRFMonitor { constructor(metricsService, alertService) { this.metrics = metricsService; this.alerts = alertService; this.thresholds = { failedValidationsPerMinute: 10, suspiciousIPRate: 5, unusualUserAgentRate: 3 }; } async monitorValidation(userId, token, isValid, metadata) { // Record metrics this.metrics.increment('csrf.validations.total'); if (!isValid) { this.metrics.increment('csrf.validations.failed'); await this.checkFailureThresholds(userId, metadata); } else { this.metrics.increment('csrf.validations.success'); } } async checkFailureThresholds(userId, metadata) { const recentFailures = await this.getRecentFailures(60); // Last 60 seconds if (recentFailures.length > this.thresholds.failedValidationsPerMinute) { await this.alerts.send({ severity: 'HIGH', message: 'High CSRF validation failure rate detected', details: { count: recentFailures.length, timeWindow: '60s' } }); } // Check failure rate for specific IP const ipFailures = recentFailures.filter(f => f.metadata.ip === metadata.ip); if (ipFailures.length > this.thresholds.suspiciousIPRate) { await this.alerts.send({ severity: 'MEDIUM', message: 'Suspicious IP detected', details: { ip: metadata.ip, failures: ipFailures.length } }); } } }
2. Dashboard
javascript// CSRF Security Dashboard class CSRFSecurityDashboard { constructor(monitor, reportGenerator) { this.monitor = monitor; this.reportGenerator = reportGenerator; } async getDashboardData(timeRange = '24h') { const report = await this.reportGenerator.generateReport( this.getStartDate(timeRange), new Date() ); const metrics = await this.monitor.getMetrics(timeRange); return { overview: { totalValidations: metrics.validations.total, successRate: this.calculateSuccessRate(metrics), activeUsers: report.summary.uniqueUsers }, security: { failedAttempts: report.summary.failedValidations, suspiciousActivity: report.suspiciousActivity.length, complianceStatus: report.complianceStatus.compliant }, trends: this.calculateTrends(metrics), alerts: this.getRecentAlerts() }; } }
Enterprise-level CSRF protection needs to comprehensively consider architecture, performance, availability, and compliance to build a comprehensive, reliable security protection system.