@pawells/nestjs-shared 1.0.0-dev.3052c75
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +802 -0
- package/build/LICENSE +21 -0
- package/build/README.md +802 -0
- package/build/common/common.module.d.ts +49 -0
- package/build/common/common.module.d.ts.map +1 -0
- package/build/common/common.module.js +178 -0
- package/build/common/common.module.js.map +1 -0
- package/build/common/constants/histogram-buckets.constants.d.ts +12 -0
- package/build/common/constants/histogram-buckets.constants.d.ts.map +1 -0
- package/build/common/constants/histogram-buckets.constants.js +51 -0
- package/build/common/constants/histogram-buckets.constants.js.map +1 -0
- package/build/common/constants/http-status.constants.d.ts +27 -0
- package/build/common/constants/http-status.constants.d.ts.map +1 -0
- package/build/common/constants/http-status.constants.js +27 -0
- package/build/common/constants/http-status.constants.js.map +1 -0
- package/build/common/constants/timeout.constants.d.ts +29 -0
- package/build/common/constants/timeout.constants.d.ts.map +1 -0
- package/build/common/constants/timeout.constants.js +45 -0
- package/build/common/constants/timeout.constants.js.map +1 -0
- package/build/common/controllers/metrics.controller.d.ts +23 -0
- package/build/common/controllers/metrics.controller.d.ts.map +1 -0
- package/build/common/controllers/metrics.controller.js +66 -0
- package/build/common/controllers/metrics.controller.js.map +1 -0
- package/build/common/decorators/common-decorators.d.ts +90 -0
- package/build/common/decorators/common-decorators.d.ts.map +1 -0
- package/build/common/decorators/common-decorators.js +101 -0
- package/build/common/decorators/common-decorators.js.map +1 -0
- package/build/common/decorators/decorator-factory.d.ts +108 -0
- package/build/common/decorators/decorator-factory.d.ts.map +1 -0
- package/build/common/decorators/decorator-factory.js +104 -0
- package/build/common/decorators/decorator-factory.js.map +1 -0
- package/build/common/decorators/guard.decorators.d.ts +48 -0
- package/build/common/decorators/guard.decorators.d.ts.map +1 -0
- package/build/common/decorators/guard.decorators.js +49 -0
- package/build/common/decorators/guard.decorators.js.map +1 -0
- package/build/common/decorators/index.d.ts +10 -0
- package/build/common/decorators/index.d.ts.map +1 -0
- package/build/common/decorators/index.js +11 -0
- package/build/common/decorators/index.js.map +1 -0
- package/build/common/decorators/instrument.decorator.d.ts +128 -0
- package/build/common/decorators/instrument.decorator.d.ts.map +1 -0
- package/build/common/decorators/instrument.decorator.js +165 -0
- package/build/common/decorators/instrument.decorator.js.map +1 -0
- package/build/common/decorators/metric.decorators.d.ts +42 -0
- package/build/common/decorators/metric.decorators.d.ts.map +1 -0
- package/build/common/decorators/metric.decorators.js +85 -0
- package/build/common/decorators/metric.decorators.js.map +1 -0
- package/build/common/decorators/request-property.decorator.d.ts +65 -0
- package/build/common/decorators/request-property.decorator.d.ts.map +1 -0
- package/build/common/decorators/request-property.decorator.js +102 -0
- package/build/common/decorators/request-property.decorator.js.map +1 -0
- package/build/common/errors/base-application-error.d.ts +98 -0
- package/build/common/errors/base-application-error.d.ts.map +1 -0
- package/build/common/errors/base-application-error.js +133 -0
- package/build/common/errors/base-application-error.js.map +1 -0
- package/build/common/errors/error-factory.d.ts +93 -0
- package/build/common/errors/error-factory.d.ts.map +1 -0
- package/build/common/errors/error-factory.js +105 -0
- package/build/common/errors/error-factory.js.map +1 -0
- package/build/common/errors/index.d.ts +13 -0
- package/build/common/errors/index.d.ts.map +1 -0
- package/build/common/errors/index.js +15 -0
- package/build/common/errors/index.js.map +1 -0
- package/build/common/factories/index.d.ts +5 -0
- package/build/common/factories/index.d.ts.map +1 -0
- package/build/common/factories/index.js +3 -0
- package/build/common/factories/index.js.map +1 -0
- package/build/common/factories/module-factory.d.ts +178 -0
- package/build/common/factories/module-factory.d.ts.map +1 -0
- package/build/common/factories/module-factory.js +253 -0
- package/build/common/factories/module-factory.js.map +1 -0
- package/build/common/factories/rate-limit-config.factory.d.ts +79 -0
- package/build/common/factories/rate-limit-config.factory.d.ts.map +1 -0
- package/build/common/factories/rate-limit-config.factory.js +115 -0
- package/build/common/factories/rate-limit-config.factory.js.map +1 -0
- package/build/common/factories/security-bootstrap.factory.d.ts +77 -0
- package/build/common/factories/security-bootstrap.factory.d.ts.map +1 -0
- package/build/common/factories/security-bootstrap.factory.js +222 -0
- package/build/common/factories/security-bootstrap.factory.js.map +1 -0
- package/build/common/filters/global-exception.filter.d.ts +78 -0
- package/build/common/filters/global-exception.filter.d.ts.map +1 -0
- package/build/common/filters/global-exception.filter.js +192 -0
- package/build/common/filters/global-exception.filter.js.map +1 -0
- package/build/common/filters/http-exception.filter.d.ts +37 -0
- package/build/common/filters/http-exception.filter.d.ts.map +1 -0
- package/build/common/filters/http-exception.filter.js +91 -0
- package/build/common/filters/http-exception.filter.js.map +1 -0
- package/build/common/guards/csrf.guard.d.ts +53 -0
- package/build/common/guards/csrf.guard.d.ts.map +1 -0
- package/build/common/guards/csrf.guard.js +109 -0
- package/build/common/guards/csrf.guard.js.map +1 -0
- package/build/common/guards/metrics.guard.d.ts +42 -0
- package/build/common/guards/metrics.guard.d.ts.map +1 -0
- package/build/common/guards/metrics.guard.js +124 -0
- package/build/common/guards/metrics.guard.js.map +1 -0
- package/build/common/index.d.ts +43 -0
- package/build/common/index.d.ts.map +1 -0
- package/build/common/index.js +50 -0
- package/build/common/index.js.map +1 -0
- package/build/common/interceptors/http-client.interceptor.d.ts +11 -0
- package/build/common/interceptors/http-client.interceptor.d.ts.map +1 -0
- package/build/common/interceptors/http-client.interceptor.js +69 -0
- package/build/common/interceptors/http-client.interceptor.js.map +1 -0
- package/build/common/interceptors/http-instrumentation.interceptor.d.ts +64 -0
- package/build/common/interceptors/http-instrumentation.interceptor.d.ts.map +1 -0
- package/build/common/interceptors/http-instrumentation.interceptor.js +148 -0
- package/build/common/interceptors/http-instrumentation.interceptor.js.map +1 -0
- package/build/common/interceptors/http-metrics.interceptor.d.ts +46 -0
- package/build/common/interceptors/http-metrics.interceptor.d.ts.map +1 -0
- package/build/common/interceptors/http-metrics.interceptor.js +120 -0
- package/build/common/interceptors/http-metrics.interceptor.js.map +1 -0
- package/build/common/interceptors/logging.interceptor.d.ts +22 -0
- package/build/common/interceptors/logging.interceptor.d.ts.map +1 -0
- package/build/common/interceptors/logging.interceptor.js +67 -0
- package/build/common/interceptors/logging.interceptor.js.map +1 -0
- package/build/common/interfaces/cache-provider.interface.d.ts +54 -0
- package/build/common/interfaces/cache-provider.interface.d.ts.map +1 -0
- package/build/common/interfaces/cache-provider.interface.js +6 -0
- package/build/common/interfaces/cache-provider.interface.js.map +1 -0
- package/build/common/interfaces/index.d.ts +7 -0
- package/build/common/interfaces/index.d.ts.map +1 -0
- package/build/common/interfaces/index.js +3 -0
- package/build/common/interfaces/index.js.map +1 -0
- package/build/common/interfaces/log-context.interface.d.ts +77 -0
- package/build/common/interfaces/log-context.interface.d.ts.map +1 -0
- package/build/common/interfaces/log-context.interface.js +2 -0
- package/build/common/interfaces/log-context.interface.js.map +1 -0
- package/build/common/interfaces/log-entry.interface.d.ts +26 -0
- package/build/common/interfaces/log-entry.interface.d.ts.map +1 -0
- package/build/common/interfaces/log-entry.interface.js +33 -0
- package/build/common/interfaces/log-entry.interface.js.map +1 -0
- package/build/common/interfaces/logger.interface.d.ts +62 -0
- package/build/common/interfaces/logger.interface.d.ts.map +1 -0
- package/build/common/interfaces/logger.interface.js +2 -0
- package/build/common/interfaces/logger.interface.js.map +1 -0
- package/build/common/interfaces/metrics-exporter.interface.d.ts +275 -0
- package/build/common/interfaces/metrics-exporter.interface.d.ts.map +1 -0
- package/build/common/interfaces/metrics-exporter.interface.js +8 -0
- package/build/common/interfaces/metrics-exporter.interface.js.map +1 -0
- package/build/common/metrics/base-metrics-collector.d.ts +81 -0
- package/build/common/metrics/base-metrics-collector.d.ts.map +1 -0
- package/build/common/metrics/base-metrics-collector.js +88 -0
- package/build/common/metrics/base-metrics-collector.js.map +1 -0
- package/build/common/metrics/index.d.ts +2 -0
- package/build/common/metrics/index.d.ts.map +1 -0
- package/build/common/metrics/index.js +2 -0
- package/build/common/metrics/index.js.map +1 -0
- package/build/common/metrics.module.d.ts +50 -0
- package/build/common/metrics.module.d.ts.map +1 -0
- package/build/common/metrics.module.js +77 -0
- package/build/common/metrics.module.js.map +1 -0
- package/build/common/modules/throttler.module.d.ts +69 -0
- package/build/common/modules/throttler.module.d.ts.map +1 -0
- package/build/common/modules/throttler.module.js +117 -0
- package/build/common/modules/throttler.module.js.map +1 -0
- package/build/common/pipes/base-validation.pipe.d.ts +67 -0
- package/build/common/pipes/base-validation.pipe.d.ts.map +1 -0
- package/build/common/pipes/base-validation.pipe.js +95 -0
- package/build/common/pipes/base-validation.pipe.js.map +1 -0
- package/build/common/pipes/validation.pipe.d.ts +32 -0
- package/build/common/pipes/validation.pipe.d.ts.map +1 -0
- package/build/common/pipes/validation.pipe.js +60 -0
- package/build/common/pipes/validation.pipe.js.map +1 -0
- package/build/common/registry/instrumentation-registry.d.ts +227 -0
- package/build/common/registry/instrumentation-registry.d.ts.map +1 -0
- package/build/common/registry/instrumentation-registry.js +414 -0
- package/build/common/registry/instrumentation-registry.js.map +1 -0
- package/build/common/services/audit-logger.service.d.ts +91 -0
- package/build/common/services/audit-logger.service.d.ts.map +1 -0
- package/build/common/services/audit-logger.service.js +180 -0
- package/build/common/services/audit-logger.service.js.map +1 -0
- package/build/common/services/csrf.service.d.ts +202 -0
- package/build/common/services/csrf.service.d.ts.map +1 -0
- package/build/common/services/csrf.service.js +478 -0
- package/build/common/services/csrf.service.js.map +1 -0
- package/build/common/services/error-categorizer.service.d.ts +82 -0
- package/build/common/services/error-categorizer.service.d.ts.map +1 -0
- package/build/common/services/error-categorizer.service.js +339 -0
- package/build/common/services/error-categorizer.service.js.map +1 -0
- package/build/common/services/error-sanitizer.service.d.ts +146 -0
- package/build/common/services/error-sanitizer.service.d.ts.map +1 -0
- package/build/common/services/error-sanitizer.service.js +287 -0
- package/build/common/services/error-sanitizer.service.js.map +1 -0
- package/build/common/services/health-check.service.d.ts +86 -0
- package/build/common/services/health-check.service.d.ts.map +1 -0
- package/build/common/services/health-check.service.js +132 -0
- package/build/common/services/health-check.service.js.map +1 -0
- package/build/common/services/http-client.service.d.ts +113 -0
- package/build/common/services/http-client.service.d.ts.map +1 -0
- package/build/common/services/http-client.service.js +294 -0
- package/build/common/services/http-client.service.js.map +1 -0
- package/build/common/services/logger.service.d.ts +189 -0
- package/build/common/services/logger.service.d.ts.map +1 -0
- package/build/common/services/logger.service.js +423 -0
- package/build/common/services/logger.service.js.map +1 -0
- package/build/common/services/metrics-registry.service.d.ts +98 -0
- package/build/common/services/metrics-registry.service.d.ts.map +1 -0
- package/build/common/services/metrics-registry.service.js +262 -0
- package/build/common/services/metrics-registry.service.js.map +1 -0
- package/build/common/services/nest-logger-adapter.service.d.ts +62 -0
- package/build/common/services/nest-logger-adapter.service.d.ts.map +1 -0
- package/build/common/services/nest-logger-adapter.service.js +120 -0
- package/build/common/services/nest-logger-adapter.service.js.map +1 -0
- package/build/common/utils/error.utils.d.ts +16 -0
- package/build/common/utils/error.utils.d.ts.map +1 -0
- package/build/common/utils/error.utils.js +26 -0
- package/build/common/utils/error.utils.js.map +1 -0
- package/build/common/utils/lazy-getter.types.d.ts +190 -0
- package/build/common/utils/lazy-getter.types.d.ts.map +1 -0
- package/build/common/utils/lazy-getter.types.js +114 -0
- package/build/common/utils/lazy-getter.types.js.map +1 -0
- package/build/common/utils/module.utils.d.ts +33 -0
- package/build/common/utils/module.utils.d.ts.map +1 -0
- package/build/common/utils/module.utils.js +48 -0
- package/build/common/utils/module.utils.js.map +1 -0
- package/build/common/utils/sanitization.utils.d.ts +69 -0
- package/build/common/utils/sanitization.utils.d.ts.map +1 -0
- package/build/common/utils/sanitization.utils.js +141 -0
- package/build/common/utils/sanitization.utils.js.map +1 -0
- package/build/config/config.module.d.ts +30 -0
- package/build/config/config.module.d.ts.map +1 -0
- package/build/config/config.module.js +49 -0
- package/build/config/config.module.js.map +1 -0
- package/build/config/config.service.d.ts +74 -0
- package/build/config/config.service.d.ts.map +1 -0
- package/build/config/config.service.js +145 -0
- package/build/config/config.service.js.map +1 -0
- package/build/config/config.types.d.ts +143 -0
- package/build/config/config.types.d.ts.map +1 -0
- package/build/config/config.types.js +2 -0
- package/build/config/config.types.js.map +1 -0
- package/build/config/decorators/config.decorators.d.ts +43 -0
- package/build/config/decorators/config.decorators.d.ts.map +1 -0
- package/build/config/decorators/config.decorators.js +68 -0
- package/build/config/decorators/config.decorators.js.map +1 -0
- package/build/config/decorators/index.d.ts +2 -0
- package/build/config/decorators/index.d.ts.map +1 -0
- package/build/config/decorators/index.js +2 -0
- package/build/config/decorators/index.js.map +1 -0
- package/build/config/index.d.ts +7 -0
- package/build/config/index.d.ts.map +1 -0
- package/build/config/index.js +9 -0
- package/build/config/index.js.map +1 -0
- package/build/config/validation.utils.d.ts +136 -0
- package/build/config/validation.utils.d.ts.map +1 -0
- package/build/config/validation.utils.js +263 -0
- package/build/config/validation.utils.js.map +1 -0
- package/build/errors/index.d.ts +9 -0
- package/build/errors/index.d.ts.map +1 -0
- package/build/errors/index.js +12 -0
- package/build/errors/index.js.map +1 -0
- package/build/guards/custom-throttle.guard.d.ts +28 -0
- package/build/guards/custom-throttle.guard.d.ts.map +1 -0
- package/build/guards/custom-throttle.guard.js +52 -0
- package/build/guards/custom-throttle.guard.js.map +1 -0
- package/build/guards/index.d.ts +2 -0
- package/build/guards/index.d.ts.map +1 -0
- package/build/guards/index.js +2 -0
- package/build/guards/index.js.map +1 -0
- package/build/index.d.ts +53 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +61 -0
- package/build/index.js.map +1 -0
- package/build/logging/index.d.ts +7 -0
- package/build/logging/index.d.ts.map +1 -0
- package/build/logging/index.js +7 -0
- package/build/logging/index.js.map +1 -0
- package/build/metrics/index.d.ts +6 -0
- package/build/metrics/index.d.ts.map +1 -0
- package/build/metrics/index.js +11 -0
- package/build/metrics/index.js.map +1 -0
- package/build/package.json +72 -0
- package/build/security/index.d.ts +8 -0
- package/build/security/index.d.ts.map +1 -0
- package/build/security/index.js +11 -0
- package/build/security/index.js.map +1 -0
- package/build/test-setup.d.ts +2 -0
- package/build/test-setup.d.ts.map +1 -0
- package/build/test-setup.js +40 -0
- package/build/test-setup.js.map +1 -0
- package/build/validation/index.d.ts +6 -0
- package/build/validation/index.d.ts.map +1 -0
- package/build/validation/index.js +8 -0
- package/build/validation/index.js.map +1 -0
- package/package.json +71 -0
|
@@ -0,0 +1,478 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
|
+
};
|
|
13
|
+
var CSRFService_1;
|
|
14
|
+
import { Injectable, Logger, HttpException, HttpStatus, Inject, Optional } from '@nestjs/common';
|
|
15
|
+
import { ConfigService } from '@nestjs/config';
|
|
16
|
+
import { doubleCsrf } from 'csrf-csrf';
|
|
17
|
+
import { escapeNewlines } from '../utils/sanitization.utils.js';
|
|
18
|
+
/**
|
|
19
|
+
* CSRF Service.
|
|
20
|
+
* Provides CSRF token generation and validation using the Double Submit Cookie pattern.
|
|
21
|
+
* Uses cryptographic signing and per-session/IP binding for secure token verification.
|
|
22
|
+
*
|
|
23
|
+
* Features:
|
|
24
|
+
* - Double-CSRF token pattern (cookie + request header/body)
|
|
25
|
+
* - Per-IP rate limiting: 10 tokens per 60 seconds
|
|
26
|
+
* - Session binding (when available) or IP-based fallback
|
|
27
|
+
* - Automatic pruning of stale timestamps
|
|
28
|
+
* - Capacity monitoring with safety margin (80% threshold)
|
|
29
|
+
* - SSL-only, HTTPOnly cookies in production
|
|
30
|
+
*
|
|
31
|
+
* Configuration requirements:
|
|
32
|
+
* - CSRF_SECRET: Min 32 characters, cryptographically random, high entropy
|
|
33
|
+
* - Express app with cookie parser middleware
|
|
34
|
+
* - Optional: trustProxy for reverse proxy environments
|
|
35
|
+
*
|
|
36
|
+
* @remarks
|
|
37
|
+
* - In-memory rate limiting supports ~10,000 concurrent IPs per instance
|
|
38
|
+
* - For distributed deployments, use Redis-backed SharedThrottlerModule instead
|
|
39
|
+
* - Token generation timeout: 30 seconds (queue timeout)
|
|
40
|
+
* - Token timestamp pruning interval: 10 seconds
|
|
41
|
+
* - IP map capacity threshold: 80% (8,000 IPs) before pruning
|
|
42
|
+
* - Returns 503 Service Unavailable if at capacity after pruning
|
|
43
|
+
* - Returns 429 Too Many Requests if rate limit exceeded
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```typescript
|
|
47
|
+
* // Generate token for form
|
|
48
|
+
* const token = await csrfService.generateToken(req, res);
|
|
49
|
+
* res.render('form', { csrfToken: token });
|
|
50
|
+
*
|
|
51
|
+
* // Validate incoming request (done automatically by CSRFGuard)
|
|
52
|
+
* const isValid = csrfService.validateToken(req);
|
|
53
|
+
*
|
|
54
|
+
* // Refresh token after sensitive operation (login, password change)
|
|
55
|
+
* const newToken = await csrfService.refreshToken(req, res);
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
let CSRFService = class CSRFService {
|
|
59
|
+
static { CSRFService_1 = this; }
|
|
60
|
+
configService;
|
|
61
|
+
// Configuration constants
|
|
62
|
+
// eslint-disable-next-line no-magic-numbers
|
|
63
|
+
static MIN_SECRET_LENGTH = 32;
|
|
64
|
+
// eslint-disable-next-line no-magic-numbers
|
|
65
|
+
static MIN_CHARACTER_SET_DIVERSITY = 3;
|
|
66
|
+
// eslint-disable-next-line no-magic-numbers
|
|
67
|
+
static ANONYMOUS_TOKEN_RANDOMNESS_BYTES = 4;
|
|
68
|
+
// eslint-disable-next-line no-magic-numbers
|
|
69
|
+
static RATE_LIMIT_WINDOW_MS = 60_000; // 60 seconds
|
|
70
|
+
// eslint-disable-next-line no-magic-numbers
|
|
71
|
+
static RATE_LIMIT_COUNT = 10;
|
|
72
|
+
/**
|
|
73
|
+
* Maximum number of unique IP addresses tracked for rate limiting.
|
|
74
|
+
* This in-memory strategy supports ~10,000 concurrent IPs per instance.
|
|
75
|
+
*
|
|
76
|
+
* **Scaling guidance**: For deployments exceeding 10,000 concurrent unique IPs,
|
|
77
|
+
* migrate to a Redis-backed rate limiting solution via SharedThrottlerModule:
|
|
78
|
+
* - Configure SharedThrottlerModule with Redis backend
|
|
79
|
+
* - Adjust limits and TTL for your traffic pattern
|
|
80
|
+
*
|
|
81
|
+
* **Memory management**: When the tracked IPs map reaches 80% capacity
|
|
82
|
+
* (8,000 IPs), the pruning logic removes stale entries (>60s old).
|
|
83
|
+
* If after pruning the map remains >= 10,000 IPs, token generation is
|
|
84
|
+
* rejected with HTTP 503 to prevent unbounded memory growth.
|
|
85
|
+
* The 80% threshold provides a safety margin before hard limits are hit.
|
|
86
|
+
*
|
|
87
|
+
* @see SharedThrottlerModule for Redis-backed distributed rate limiting
|
|
88
|
+
*/
|
|
89
|
+
// eslint-disable-next-line no-magic-numbers
|
|
90
|
+
static MAX_TRACKED_IPS = 10000;
|
|
91
|
+
// eslint-disable-next-line no-magic-numbers
|
|
92
|
+
static TIMESTAMP_PRUNING_INTERVAL_MS = 10 * 1000; // Prune every 10 seconds
|
|
93
|
+
// eslint-disable-next-line no-magic-numbers
|
|
94
|
+
static IP_LOCK_TIMEOUT_MS = 30_000; // 30 second timeout for queued requests
|
|
95
|
+
// eslint-disable-next-line no-magic-numbers
|
|
96
|
+
static CAPACITY_THRESHOLD_PERCENT = 0.8;
|
|
97
|
+
csrfProtection;
|
|
98
|
+
logger = new Logger('CSRFService');
|
|
99
|
+
tokenGenTimestamps = new Map();
|
|
100
|
+
ipLocks = new Map();
|
|
101
|
+
trustProxy;
|
|
102
|
+
capacityThresholdCrossedCount = 0;
|
|
103
|
+
pruneIntervalHandle;
|
|
104
|
+
_isPruning = false;
|
|
105
|
+
constructor(configService, options) {
|
|
106
|
+
this.configService = configService;
|
|
107
|
+
// Note: CSRF_SECRET validation is deferred to onModuleInit() to ensure
|
|
108
|
+
// NestJS surfaces the error at bootstrap time rather than during DI resolution
|
|
109
|
+
this.trustProxy = options?.trustProxy ?? false;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* NestJS lifecycle hook: validate required CSRF_SECRET environment variable
|
|
113
|
+
* at application bootstrap time
|
|
114
|
+
*/
|
|
115
|
+
onModuleInit() {
|
|
116
|
+
const csrfSecret = this.configService?.get('CSRF_SECRET') ?? process.env['CSRF_SECRET'];
|
|
117
|
+
if (!csrfSecret) {
|
|
118
|
+
throw new Error('CSRF_SECRET environment variable is required but not set. ' +
|
|
119
|
+
'Set it in your .env file or as an environment variable before starting the application.');
|
|
120
|
+
}
|
|
121
|
+
// Validate CSRF_SECRET entropy
|
|
122
|
+
if (csrfSecret.length < CSRFService_1.MIN_SECRET_LENGTH) {
|
|
123
|
+
throw new Error(`CSRF_SECRET must be at least ${CSRFService_1.MIN_SECRET_LENGTH} characters long for adequate entropy. ` +
|
|
124
|
+
`Current length: ${csrfSecret.length}. ` +
|
|
125
|
+
'Generate a cryptographically secure value with: openssl rand -base64 32');
|
|
126
|
+
}
|
|
127
|
+
// Check for obviously weak patterns as secondary check
|
|
128
|
+
if (this.isWeakSecret(csrfSecret)) {
|
|
129
|
+
throw new Error('CSRF_SECRET contains obviously weak pattern. ' +
|
|
130
|
+
'Must have a mix of different characters, not repeated or common strings. ' +
|
|
131
|
+
'Generate a cryptographically secure value with: openssl rand -base64 32');
|
|
132
|
+
}
|
|
133
|
+
// Validate entropy (primary check)
|
|
134
|
+
const entropy = this.calculateEntropy(csrfSecret);
|
|
135
|
+
const MIN_ENTROPY = 4.0;
|
|
136
|
+
if (entropy < MIN_ENTROPY) {
|
|
137
|
+
throw new Error(`CSRF_SECRET entropy is insufficient (${entropy.toFixed(2)} bits/char). ` +
|
|
138
|
+
`Minimum required: ${MIN_ENTROPY} bits/char. ` +
|
|
139
|
+
'Generate a cryptographically secure value with: openssl rand -base64 32');
|
|
140
|
+
}
|
|
141
|
+
// Initialize CSRF protection now that we know the secret is available and valid
|
|
142
|
+
this.csrfProtection = doubleCsrf({
|
|
143
|
+
getSecret: () => csrfSecret,
|
|
144
|
+
getSessionIdentifier: (req) => this.getSessionIdentifier(req),
|
|
145
|
+
cookieName: '__Host-psifi.x-csrf-token',
|
|
146
|
+
cookieOptions: {
|
|
147
|
+
httpOnly: true,
|
|
148
|
+
secure: process.env['NODE_ENV'] === 'production',
|
|
149
|
+
sameSite: 'strict',
|
|
150
|
+
path: '/',
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
// Check for trust proxy misconfiguration at boot time
|
|
154
|
+
this.validateTrustProxyConfiguration();
|
|
155
|
+
// Prune old token generation timestamps more frequently to prevent unbounded growth
|
|
156
|
+
// More aggressive pruning than 5 minutes to handle high-traffic scenarios
|
|
157
|
+
this.pruneIntervalHandle = setInterval(() => this.pruneTokenTimestamps(), CSRFService_1.TIMESTAMP_PRUNING_INTERVAL_MS);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* NestJS lifecycle hook: clear the pruning interval on module destroy
|
|
161
|
+
*/
|
|
162
|
+
onModuleDestroy() {
|
|
163
|
+
if (this.pruneIntervalHandle !== undefined) {
|
|
164
|
+
clearInterval(this.pruneIntervalHandle);
|
|
165
|
+
this.pruneIntervalHandle = undefined;
|
|
166
|
+
}
|
|
167
|
+
// Clear maps to release memory on shutdown
|
|
168
|
+
this.tokenGenTimestamps.clear();
|
|
169
|
+
this.ipLocks.clear();
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Validate trust proxy configuration to detect mismatches early
|
|
173
|
+
* Checks if X-Forwarded-For header support is configured correctly in both directions:
|
|
174
|
+
* - If trustProxy=false but X-Forwarded-For is present: may miss real client IP
|
|
175
|
+
* - If trustProxy=true but X-Forwarded-For is absent: proxy may not be configured correctly
|
|
176
|
+
*/
|
|
177
|
+
validateTrustProxyConfiguration() {
|
|
178
|
+
// Check direction 1: trustProxy=false but service is likely behind a proxy
|
|
179
|
+
// We detect this by checking if the NODE_ENV and common proxy environments are misconfigured.
|
|
180
|
+
// Note: We do NOT call extractClientIp here to avoid spurious "X-Forwarded-For detected" warnings
|
|
181
|
+
// during module initialization with synthetic sample requests.
|
|
182
|
+
if (!this.trustProxy) {
|
|
183
|
+
// Nothing to warn about at init time — the runtime warning in extractClientIp
|
|
184
|
+
// will fire if real requests arrive with X-Forwarded-For headers.
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
// Check direction 2: trustProxy=true but X-Forwarded-For absent (reverse proxy may not be configured)
|
|
188
|
+
// Use a sample request without X-Forwarded-For to detect this early
|
|
189
|
+
const sampleRequestWithoutHeader = { headers: {}, socket: { remoteAddress: '127.0.0.1' } };
|
|
190
|
+
const extractedIpWithoutHeader = this.extractClientIp(sampleRequestWithoutHeader);
|
|
191
|
+
if (extractedIpWithoutHeader === undefined || extractedIpWithoutHeader === null) {
|
|
192
|
+
this.logger.warn('Trust proxy is enabled but X-Forwarded-For header is not present in sample request. ' +
|
|
193
|
+
'Your reverse proxy may not be configured to set X-Forwarded-For correctly. ' +
|
|
194
|
+
'Verify your proxy (nginx, Apache, load balancer, etc.) is setting this header.');
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Calculate Shannon entropy of a string to measure randomness.
|
|
199
|
+
* Higher entropy indicates better randomness quality.
|
|
200
|
+
*
|
|
201
|
+
* The minimum threshold of 4.0 bits/char is chosen because:
|
|
202
|
+
* - A uniformly random string from a 16-character alphabet (hex: 0-9a-f) has log2(16) = 4.0 bits/char
|
|
203
|
+
* - This ensures the CSRF_SECRET has sufficient entropy for cryptographic purposes
|
|
204
|
+
* - Values below 4.0 bits/char indicate the secret uses a limited character set or has patterns
|
|
205
|
+
*
|
|
206
|
+
* @param str - Input string to analyze
|
|
207
|
+
* @returns Entropy in bits per character
|
|
208
|
+
*/
|
|
209
|
+
calculateEntropy(str) {
|
|
210
|
+
const freq = new Map();
|
|
211
|
+
for (const char of str) {
|
|
212
|
+
freq.set(char, (freq.get(char) ?? 0) + 1);
|
|
213
|
+
}
|
|
214
|
+
let entropy = 0;
|
|
215
|
+
for (const count of freq.values()) {
|
|
216
|
+
const p = count / str.length;
|
|
217
|
+
entropy -= p * Math.log2(p);
|
|
218
|
+
}
|
|
219
|
+
return entropy;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Check if the secret contains obviously weak patterns
|
|
223
|
+
*/
|
|
224
|
+
isWeakSecret(secret) {
|
|
225
|
+
// Check if all characters are the same (e.g., 'aaaaa...')
|
|
226
|
+
if (/^(.)\1+$/.test(secret)) {
|
|
227
|
+
return true;
|
|
228
|
+
}
|
|
229
|
+
// Check for repeated character sequences (e.g., 'aaaa' or 'bbbb')
|
|
230
|
+
// Indicates low entropy and predictable patterns
|
|
231
|
+
if (/(.)\1{4,}/.test(secret)) {
|
|
232
|
+
return true;
|
|
233
|
+
}
|
|
234
|
+
// Check for common weak strings (case-insensitive)
|
|
235
|
+
const lowerSecret = secret.toLowerCase();
|
|
236
|
+
const weakPatterns = ['password', 'secret', '12345678', 'qwerty', '00000000', '11111111', '88888888', '99999999'];
|
|
237
|
+
if (weakPatterns.some(pattern => lowerSecret.includes(pattern))) {
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Get session identifier for CSRF token binding
|
|
244
|
+
* Prefers session ID if available, falls back to IP address
|
|
245
|
+
* @param req - Express request object
|
|
246
|
+
* @returns Session identifier
|
|
247
|
+
*/
|
|
248
|
+
getSessionIdentifier(req) {
|
|
249
|
+
const sessionId = req.session?.id;
|
|
250
|
+
if (sessionId)
|
|
251
|
+
return sessionId;
|
|
252
|
+
const ip = this.extractClientIp(req);
|
|
253
|
+
if (!ip) {
|
|
254
|
+
// Log warning — do not silently fall through to 'unknown'
|
|
255
|
+
this.logger.warn('CSRF session identifier unavailable: no session and no IP. ' +
|
|
256
|
+
'Using fixed fallback bucket to enforce rate limiting on anonymous requests.');
|
|
257
|
+
// Use fixed fallback bucket so all anonymous requests share the same rate limit
|
|
258
|
+
return 'anon';
|
|
259
|
+
}
|
|
260
|
+
return ip;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Extract client IP address from request, respecting trustProxy setting
|
|
264
|
+
*
|
|
265
|
+
* **Note on Express vs Fastify**: This implementation uses `req.ip` (Express-specific).
|
|
266
|
+
* For Fastify deployments, ensure the `trustProxy` option is properly configured:
|
|
267
|
+
* - In Fastify, use `app.register(require('@fastify/proxy'), { ...config })`
|
|
268
|
+
* - Or set the Fastify instance option: `fastify({ trustProxy: true })`
|
|
269
|
+
* - Without correct Fastify configuration, IP detection will fail
|
|
270
|
+
*
|
|
271
|
+
* @param req - Express request object
|
|
272
|
+
* @returns Client IP address or null if unavailable
|
|
273
|
+
*/
|
|
274
|
+
extractClientIp(req) {
|
|
275
|
+
// If trustProxy is enabled, use X-Forwarded-For header (first IP only)
|
|
276
|
+
if (this.trustProxy) {
|
|
277
|
+
const forwardedFor = req.headers['x-forwarded-for'];
|
|
278
|
+
if (forwardedFor) {
|
|
279
|
+
// X-Forwarded-For can contain multiple IPs: client, proxy1, proxy2...
|
|
280
|
+
// We only trust the first one (the original client)
|
|
281
|
+
const firstIp = Array.isArray(forwardedFor) ? forwardedFor[0] : forwardedFor.split(',')[0];
|
|
282
|
+
return firstIp?.trim() ?? null;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
// Warn if X-Forwarded-For is present but trustProxy is false
|
|
287
|
+
// This may indicate a misconfiguration where the service is behind a reverse proxy
|
|
288
|
+
const forwardedFor = req.headers['x-forwarded-for'];
|
|
289
|
+
if (forwardedFor) {
|
|
290
|
+
this.logger.warn('X-Forwarded-For header detected but trustProxy is false. ' +
|
|
291
|
+
'If this service is behind a reverse proxy (nginx, Apache, load balancer, etc.), ' +
|
|
292
|
+
'enable trustProxy in CSRFService options to correctly identify client IPs. ' +
|
|
293
|
+
'Otherwise, client IP detection will use direct socket IP.');
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
// Fall back to direct socket IP
|
|
297
|
+
return req.ip ?? (req.socket?.remoteAddress) ?? null;
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Prune old token generation timestamps to prevent unbounded map growth
|
|
301
|
+
* Removes entries older than 60 seconds and cleans up idle IPs from both
|
|
302
|
+
* tokenGenTimestamps and ipLocks to prevent memory accumulation.
|
|
303
|
+
*/
|
|
304
|
+
pruneTokenTimestamps() {
|
|
305
|
+
const now = Date.now();
|
|
306
|
+
const TIMESTAMP_TTL = 60_000; // 60 seconds
|
|
307
|
+
for (const [ip, timestamps] of this.tokenGenTimestamps.entries()) {
|
|
308
|
+
const recentTimestamps = timestamps.filter(ts => now - ts < TIMESTAMP_TTL);
|
|
309
|
+
if (recentTimestamps.length === 0) {
|
|
310
|
+
this.tokenGenTimestamps.delete(ip);
|
|
311
|
+
// Clean up corresponding ipLocks entry when IP has no timestamps
|
|
312
|
+
this.ipLocks.delete(ip);
|
|
313
|
+
}
|
|
314
|
+
else {
|
|
315
|
+
this.tokenGenTimestamps.set(ip, recentTimestamps);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Generate CSRF token with per-IP rate limiting
|
|
321
|
+
* Limits to 10 token generations per IP per 60 seconds
|
|
322
|
+
* Uses per-IP locking to serialize concurrent requests from the same IP,
|
|
323
|
+
* preventing race conditions in rate limit checks.
|
|
324
|
+
* @param req - Express request object
|
|
325
|
+
* @param res - Express response object
|
|
326
|
+
* @returns CSRF token
|
|
327
|
+
* @throws Error if CSRF_SECRET was not initialized in onModuleInit
|
|
328
|
+
* @throws {HttpException} 429 - When rate limit exceeded for this IP
|
|
329
|
+
* @throws {HttpException} 503 - When service is at capacity
|
|
330
|
+
*/
|
|
331
|
+
async generateToken(req, res) {
|
|
332
|
+
if (!this.csrfProtection) {
|
|
333
|
+
throw new Error('CSRFService not initialized — call onModuleInit() first');
|
|
334
|
+
}
|
|
335
|
+
const ip = this.extractClientIp(req) ?? 'unknown';
|
|
336
|
+
// Serialize rate-limit check + token generation per IP to prevent race conditions
|
|
337
|
+
// Chain this request's work after any pending work for the same IP
|
|
338
|
+
const pendingWork = this.ipLocks.get(ip) ?? Promise.resolve();
|
|
339
|
+
// Wrap with a timeout to prevent indefinite waits in the queue
|
|
340
|
+
const currentWork = pendingWork.then(() => {
|
|
341
|
+
return new Promise((resolve, reject) => {
|
|
342
|
+
const timer = setTimeout(() => {
|
|
343
|
+
reject(new HttpException('CSRF token generation timed out waiting in queue', HttpStatus.SERVICE_UNAVAILABLE));
|
|
344
|
+
}, CSRFService_1.IP_LOCK_TIMEOUT_MS);
|
|
345
|
+
try {
|
|
346
|
+
const token = this.performRateLimitedTokenGeneration(req, res);
|
|
347
|
+
clearTimeout(timer);
|
|
348
|
+
resolve(token);
|
|
349
|
+
}
|
|
350
|
+
catch (err) {
|
|
351
|
+
clearTimeout(timer);
|
|
352
|
+
reject(err);
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
});
|
|
356
|
+
this.ipLocks.set(ip, currentWork);
|
|
357
|
+
// Clean up the lock after this work completes (only if no new work queued)
|
|
358
|
+
currentWork.finally(() => {
|
|
359
|
+
if (this.ipLocks.get(ip) === currentWork) {
|
|
360
|
+
this.ipLocks.delete(ip);
|
|
361
|
+
}
|
|
362
|
+
});
|
|
363
|
+
// eslint-disable-next-line @typescript-eslint/return-await
|
|
364
|
+
return await currentWork;
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Perform rate-limited token generation for a single IP.
|
|
368
|
+
* This method is called within an IP-serialized lock to ensure atomicity.
|
|
369
|
+
* @param req - Express request object
|
|
370
|
+
* @param res - Express response object
|
|
371
|
+
* @returns CSRF token
|
|
372
|
+
* @throws HttpException with 429 status if rate limit exceeded
|
|
373
|
+
*/
|
|
374
|
+
performRateLimitedTokenGeneration(req, res) {
|
|
375
|
+
// Check per-IP rate limit
|
|
376
|
+
const ip = this.extractClientIp(req) ?? 'unknown';
|
|
377
|
+
const now = Date.now();
|
|
378
|
+
// Check if map is approaching capacity (at 80% threshold with 20% safety margin)
|
|
379
|
+
// This safety margin prevents race conditions where concurrent requests might insert
|
|
380
|
+
// new IPs between the pruning step and the final capacity check.
|
|
381
|
+
const capacityThreshold = CSRFService_1.MAX_TRACKED_IPS * CSRFService_1.CAPACITY_THRESHOLD_PERCENT;
|
|
382
|
+
if (this.tokenGenTimestamps.size >= capacityThreshold) {
|
|
383
|
+
this.capacityThresholdCrossedCount++;
|
|
384
|
+
// eslint-disable-next-line no-magic-numbers
|
|
385
|
+
const capacityPercent = (this.tokenGenTimestamps.size / CSRFService_1.MAX_TRACKED_IPS * 100).toFixed(1);
|
|
386
|
+
this.logger.warn(`CSRF token generation approaching capacity (${capacityPercent}% of ${CSRFService_1.MAX_TRACKED_IPS} max IPs). ` +
|
|
387
|
+
`Threshold crossed ${this.capacityThresholdCrossedCount} times.`);
|
|
388
|
+
if (!this._isPruning) {
|
|
389
|
+
this._isPruning = true;
|
|
390
|
+
this.pruneTokenTimestamps();
|
|
391
|
+
this._isPruning = false;
|
|
392
|
+
}
|
|
393
|
+
// Check again after pruning
|
|
394
|
+
if (this.tokenGenTimestamps.size >= CSRFService_1.MAX_TRACKED_IPS) {
|
|
395
|
+
// eslint-disable-next-line no-magic-numbers
|
|
396
|
+
const finalCapacityPercent = (this.tokenGenTimestamps.size / CSRFService_1.MAX_TRACKED_IPS * 100).toFixed(1);
|
|
397
|
+
this.logger.error(`CSRF service at maximum capacity (${finalCapacityPercent}% of ${CSRFService_1.MAX_TRACKED_IPS} max IPs). ` +
|
|
398
|
+
'Token generation rejected.');
|
|
399
|
+
throw new HttpException('CSRF token generation service is temporarily unavailable', HttpStatus.SERVICE_UNAVAILABLE);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
let timestamps = this.tokenGenTimestamps.get(ip) ?? [];
|
|
403
|
+
// Filter to only timestamps within the last 60 seconds
|
|
404
|
+
timestamps = timestamps.filter(ts => now - ts < CSRFService_1.RATE_LIMIT_WINDOW_MS);
|
|
405
|
+
if (timestamps.length >= CSRFService_1.RATE_LIMIT_COUNT) {
|
|
406
|
+
this.logger.warn(`CSRF token rate limit exceeded for IP: ${escapeNewlines(ip)}`);
|
|
407
|
+
throw new HttpException('Rate limit exceeded for CSRF token generation', HttpStatus.TOO_MANY_REQUESTS);
|
|
408
|
+
}
|
|
409
|
+
// Record this generation
|
|
410
|
+
timestamps.push(now);
|
|
411
|
+
this.tokenGenTimestamps.set(ip, timestamps);
|
|
412
|
+
// Generate and return the token
|
|
413
|
+
// csrfProtection is guaranteed non-null: generateToken (our caller) checks it,
|
|
414
|
+
// and performRateLimitedTokenGeneration is only called from generateToken's chain.
|
|
415
|
+
const protection = this.csrfProtection;
|
|
416
|
+
if (!protection) {
|
|
417
|
+
throw new Error('CSRFService not initialized — call onModuleInit() first');
|
|
418
|
+
}
|
|
419
|
+
return protection.generateToken(req, res);
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Validate CSRF token
|
|
423
|
+
* @param req - Express request object
|
|
424
|
+
* @returns true if token is valid, false otherwise
|
|
425
|
+
* @throws Error if CSRF_SECRET was not initialized in onModuleInit
|
|
426
|
+
*/
|
|
427
|
+
validateToken(req) {
|
|
428
|
+
if (!this.csrfProtection) {
|
|
429
|
+
throw new Error('CSRFService not initialized — call onModuleInit() first');
|
|
430
|
+
}
|
|
431
|
+
try {
|
|
432
|
+
this.csrfProtection.validateRequest(req);
|
|
433
|
+
return true;
|
|
434
|
+
}
|
|
435
|
+
catch {
|
|
436
|
+
return false;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* Refresh CSRF token by invalidating the current one and generating a new one
|
|
441
|
+
* Use this after sensitive operations like login, password change, or privilege escalation
|
|
442
|
+
* to ensure the user has a fresh token that cannot be replayed from before the operation
|
|
443
|
+
* @param req - Express request object
|
|
444
|
+
* @param res - Express response object
|
|
445
|
+
* @returns New CSRF token
|
|
446
|
+
* @throws Error if CSRF_SECRET was not initialized in onModuleInit
|
|
447
|
+
*/
|
|
448
|
+
// eslint-disable-next-line @typescript-eslint/promise-function-async
|
|
449
|
+
refreshToken(req, res) {
|
|
450
|
+
if (!this.csrfProtection) {
|
|
451
|
+
throw new Error('CSRFService not initialized — call onModuleInit() first');
|
|
452
|
+
}
|
|
453
|
+
// Route through rate limiting to enforce per-IP token generation limits
|
|
454
|
+
// Clear any session-bound CSRF state by generating a fresh token
|
|
455
|
+
// The doubleCsrf library handles invalidation through cookie/session updates
|
|
456
|
+
return this.generateToken(req, res);
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Get CSRF middleware
|
|
460
|
+
* @returns CSRF protection middleware
|
|
461
|
+
* @throws Error if CSRF_SECRET was not initialized in onModuleInit
|
|
462
|
+
*/
|
|
463
|
+
getMiddleware() {
|
|
464
|
+
if (!this.csrfProtection) {
|
|
465
|
+
throw new Error('CSRFService not initialized — call onModuleInit() first');
|
|
466
|
+
}
|
|
467
|
+
return this.csrfProtection.doubleCsrfProtection;
|
|
468
|
+
}
|
|
469
|
+
};
|
|
470
|
+
CSRFService = CSRFService_1 = __decorate([
|
|
471
|
+
Injectable(),
|
|
472
|
+
__param(0, Inject(ConfigService)),
|
|
473
|
+
__param(0, Optional()),
|
|
474
|
+
__param(1, Optional()),
|
|
475
|
+
__metadata("design:paramtypes", [ConfigService, Object])
|
|
476
|
+
], CSRFService);
|
|
477
|
+
export { CSRFService };
|
|
478
|
+
//# sourceMappingURL=csrf.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"csrf.service.js","sourceRoot":"","sources":["../../../src/common/services/csrf.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { ModuleRef } from '@nestjs/core';
|
|
2
|
+
import { LazyModuleRefService } from '../utils/lazy-getter.types.js';
|
|
3
|
+
import { AppLogger } from './logger.service.js';
|
|
4
|
+
/**
|
|
5
|
+
* Error category classification for recovery strategy determination.
|
|
6
|
+
*/
|
|
7
|
+
export interface ErrorCategory {
|
|
8
|
+
type: 'transient' | 'permanent';
|
|
9
|
+
retryable: boolean;
|
|
10
|
+
strategy: 'retry' | 'fail' | 'backoff';
|
|
11
|
+
backoffMs?: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Error Categorizer Service.
|
|
15
|
+
* Classifies errors as transient or permanent and recommends recovery strategies.
|
|
16
|
+
*
|
|
17
|
+
* Categories:
|
|
18
|
+
* - **Transient** (retryable): Network errors, timeouts, database connection errors, rate limits, server errors (5xx)
|
|
19
|
+
* - **Permanent** (not retryable): Validation errors, bad requests (4xx), authentication/authorization, not found
|
|
20
|
+
*
|
|
21
|
+
* Recovery strategies:
|
|
22
|
+
* - **retry**: Immediate retry (for network errors)
|
|
23
|
+
* - **backoff**: Exponential backoff retry (for timeouts, database, rate limits)
|
|
24
|
+
* - **fail**: Fast failure without retry (for validation, authentication, not found)
|
|
25
|
+
*
|
|
26
|
+
* @remarks
|
|
27
|
+
* - Node.js error codes (ECONNRESET, ECONNREFUSED, ETIMEDOUT, ENOTFOUND, EAI_AGAIN) are always transient
|
|
28
|
+
* - Database connection errors are always transient with long backoff (5s)
|
|
29
|
+
* - Timeout errors get medium backoff (2s)
|
|
30
|
+
* - Rate limit errors get maximum backoff (10s)
|
|
31
|
+
* - Unknown errors default to permanent/fail strategy
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```typescript
|
|
35
|
+
* const category = errorCategorizer.categorizeError(error);
|
|
36
|
+
* if (category.retryable) {
|
|
37
|
+
* // Retry with backoff: category.backoffMs
|
|
38
|
+
* } else {
|
|
39
|
+
* // Fail fast
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export declare class ErrorCategorizerService implements LazyModuleRefService {
|
|
44
|
+
private _contextualLogger;
|
|
45
|
+
readonly Module: ModuleRef;
|
|
46
|
+
constructor(module: ModuleRef);
|
|
47
|
+
/**
|
|
48
|
+
* Get contextual logger for error categorizer
|
|
49
|
+
*/
|
|
50
|
+
get Logger(): AppLogger;
|
|
51
|
+
/**
|
|
52
|
+
* Check if an error is retryable
|
|
53
|
+
*/
|
|
54
|
+
isRetryable(error: unknown): boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Categorize an error and determine recovery strategy
|
|
57
|
+
*/
|
|
58
|
+
categorizeError(error: unknown): ErrorCategory;
|
|
59
|
+
/**
|
|
60
|
+
* Log error recovery attempt
|
|
61
|
+
*/
|
|
62
|
+
logRecoveryAttempt(error: unknown, attempt: number, maxAttempts: number): void;
|
|
63
|
+
/**
|
|
64
|
+
* Log successful recovery
|
|
65
|
+
*/
|
|
66
|
+
logRecoverySuccess(error: unknown, attempts: number): void;
|
|
67
|
+
/**
|
|
68
|
+
* Log failed recovery
|
|
69
|
+
*/
|
|
70
|
+
logRecoveryFailed(error: unknown, attempts: number): void;
|
|
71
|
+
private isNetworkError;
|
|
72
|
+
private isTimeoutError;
|
|
73
|
+
private isDatabaseError;
|
|
74
|
+
private isBadRequestError;
|
|
75
|
+
private isValidationError;
|
|
76
|
+
private isAuthError;
|
|
77
|
+
private isAuthzError;
|
|
78
|
+
private isNotFoundError;
|
|
79
|
+
private isServerError;
|
|
80
|
+
private isRateLimitError;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=error-categorizer.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-categorizer.service.d.ts","sourceRoot":"","sources":["../../../src/common/services/error-categorizer.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAYzC,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAQhD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,WAAW,GAAG,WAAW,CAAC;IAChC,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBACa,uBAAwB,YAAW,oBAAoB;IACnE,OAAO,CAAC,iBAAiB,CAAwB;IAEjD,SAAgB,MAAM,EAAE,SAAS,CAAC;gBAEtB,MAAM,EAAE,SAAS;IAI7B;;OAEG;IACH,IAAW,MAAM,IAAI,SAAS,CAM7B;IAED;;OAEG;IACI,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO;IAK3C;;OAEG;IACI,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa;IAuLrD;;OAEG;IACI,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI;IAYrF;;OAEG;IACI,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAOjE;;OAEG;IACI,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAWhE,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,eAAe;IAKvB,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,gBAAgB;CAKxB"}
|