@nauth-toolkit/nestjs 0.1.14 → 0.1.17
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/dist/auth.module.d.ts +48 -0
- package/dist/auth.module.d.ts.map +1 -1
- package/dist/auth.module.js +161 -19
- package/dist/auth.module.js.map +1 -1
- package/dist/decorators/client-info.decorator.d.ts +39 -0
- package/dist/decorators/client-info.decorator.d.ts.map +1 -1
- package/dist/decorators/client-info.decorator.js +41 -0
- package/dist/decorators/client-info.decorator.js.map +1 -1
- package/dist/decorators/current-user.decorator.d.ts +6 -0
- package/dist/decorators/current-user.decorator.d.ts.map +1 -1
- package/dist/decorators/current-user.decorator.js +6 -0
- package/dist/decorators/current-user.decorator.js.map +1 -1
- package/dist/decorators/public.decorator.d.ts +7 -0
- package/dist/decorators/public.decorator.d.ts.map +1 -1
- package/dist/decorators/public.decorator.js +7 -0
- package/dist/decorators/public.decorator.js.map +1 -1
- package/dist/decorators/token-delivery.decorator.d.ts +20 -0
- package/dist/decorators/token-delivery.decorator.d.ts.map +1 -1
- package/dist/dto/index.d.ts +9 -0
- package/dist/dto/index.d.ts.map +1 -1
- package/dist/dto/index.js +10 -0
- package/dist/dto/index.js.map +1 -1
- package/dist/factories/storage-adapter.factory.d.ts +107 -0
- package/dist/factories/storage-adapter.factory.d.ts.map +1 -1
- package/dist/factories/storage-adapter.factory.js +129 -0
- package/dist/factories/storage-adapter.factory.js.map +1 -1
- package/dist/filters/nauth-http-exception.filter.d.ts +80 -0
- package/dist/filters/nauth-http-exception.filter.d.ts.map +1 -1
- package/dist/filters/nauth-http-exception.filter.js +96 -0
- package/dist/filters/nauth-http-exception.filter.js.map +1 -1
- package/dist/guards/auth.guard.d.ts +26 -0
- package/dist/guards/auth.guard.d.ts.map +1 -1
- package/dist/guards/auth.guard.js +44 -0
- package/dist/guards/auth.guard.js.map +1 -1
- package/dist/guards/csrf.guard.d.ts +21 -0
- package/dist/guards/csrf.guard.d.ts.map +1 -1
- package/dist/guards/csrf.guard.js +30 -1
- package/dist/guards/csrf.guard.js.map +1 -1
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +46 -0
- package/dist/index.js.map +1 -1
- package/dist/interceptors/client-info.interceptor.d.ts +37 -0
- package/dist/interceptors/client-info.interceptor.d.ts.map +1 -1
- package/dist/interceptors/client-info.interceptor.js +89 -1
- package/dist/interceptors/client-info.interceptor.js.map +1 -1
- package/dist/interceptors/cookie-token.interceptor.d.ts +16 -0
- package/dist/interceptors/cookie-token.interceptor.d.ts.map +1 -1
- package/dist/interceptors/cookie-token.interceptor.js +61 -2
- package/dist/interceptors/cookie-token.interceptor.js.map +1 -1
- package/dist/providers/nestjs-logger.adapter.d.ts +96 -0
- package/dist/providers/nestjs-logger.adapter.d.ts.map +1 -1
- package/dist/providers/nestjs-logger.adapter.js +105 -1
- package/dist/providers/nestjs-logger.adapter.js.map +1 -1
- package/dist/services/csrf.service.d.ts +61 -0
- package/dist/services/csrf.service.d.ts.map +1 -1
- package/dist/services/csrf.service.js +62 -1
- package/dist/services/csrf.service.js.map +1 -1
- package/dist/services/migrations-bootstrap.service.d.ts +6 -0
- package/dist/services/migrations-bootstrap.service.d.ts.map +1 -1
- package/dist/services/migrations-bootstrap.service.js +6 -0
- package/dist/services/migrations-bootstrap.service.js.map +1 -1
- package/package.json +7 -2
|
@@ -20,6 +20,22 @@ const core_2 = require("@nauth-toolkit/core");
|
|
|
20
20
|
const internal_1 = require("@nauth-toolkit/core/internal");
|
|
21
21
|
const token_delivery_decorator_1 = require("../decorators/token-delivery.decorator");
|
|
22
22
|
const csrf_service_1 = require("../services/csrf.service");
|
|
23
|
+
/**
|
|
24
|
+
* Cookie Token Interceptor
|
|
25
|
+
*
|
|
26
|
+
* Automatically sets JWT tokens as httpOnly cookies for HTTP responses when
|
|
27
|
+
* token delivery mode is configured as 'cookies' or 'hybrid'.
|
|
28
|
+
*
|
|
29
|
+
* Security defaults:
|
|
30
|
+
* - Cookie names prefixed with 'nauth_' to avoid conflicts: 'nauth_access_token', 'nauth_refresh_token'
|
|
31
|
+
* - httpOnly: true (always)
|
|
32
|
+
* - secure: true (configurable via cookieOptions.secure)
|
|
33
|
+
* - sameSite: 'strict' (configurable via cookieOptions.sameSite)
|
|
34
|
+
* - path: '/' (configurable via cookieOptions.path)
|
|
35
|
+
*
|
|
36
|
+
* This interceptor is transport-aware and only applies to HTTP requests.
|
|
37
|
+
* It does nothing in other contexts (e.g., WebSocket, GraphQL).
|
|
38
|
+
*/
|
|
23
39
|
let CookieTokenInterceptor = class CookieTokenInterceptor {
|
|
24
40
|
config;
|
|
25
41
|
jwtService;
|
|
@@ -32,6 +48,7 @@ let CookieTokenInterceptor = class CookieTokenInterceptor {
|
|
|
32
48
|
this.csrfService = csrfService;
|
|
33
49
|
}
|
|
34
50
|
intercept(context, next) {
|
|
51
|
+
// Only operate in HTTP context
|
|
35
52
|
if (context.getType() !== 'http') {
|
|
36
53
|
return next.handle();
|
|
37
54
|
}
|
|
@@ -39,17 +56,23 @@ let CookieTokenInterceptor = class CookieTokenInterceptor {
|
|
|
39
56
|
const http = context.switchToHttp();
|
|
40
57
|
const req = http.getRequest();
|
|
41
58
|
const res = http.getResponse();
|
|
59
|
+
// Determine effective delivery for this request
|
|
42
60
|
const routeMode = this.reflector.get(token_delivery_decorator_1.TOKEN_DELIVERY_KEY, context.getHandler());
|
|
43
61
|
const method = deliveryConfig?.method || 'json';
|
|
62
|
+
// Validate route-level delivery mode against global configuration
|
|
44
63
|
if (routeMode === 'cookies') {
|
|
64
|
+
// Route requests cookies - config must allow cookies (cookies or hybrid)
|
|
45
65
|
if (method === 'json') {
|
|
46
66
|
throw new core_2.NAuthException(core_2.AuthErrorCode.COOKIES_NOT_ALLOWED, "Route-level cookie delivery requested, but tokenDelivery.method is 'json' (cookies disabled)");
|
|
47
67
|
}
|
|
68
|
+
// method === 'cookies' or 'hybrid' - both allow cookies, so OK
|
|
48
69
|
}
|
|
49
70
|
else if (routeMode === 'json') {
|
|
71
|
+
// Route requests JSON - config must allow JSON (json or hybrid)
|
|
50
72
|
if (method === 'cookies') {
|
|
51
73
|
throw new core_2.NAuthException(core_2.AuthErrorCode.BEARER_NOT_ALLOWED, "Route-level JSON delivery requested, but tokenDelivery.method is 'cookies' (JSON/Bearer tokens disabled)");
|
|
52
74
|
}
|
|
75
|
+
// method === 'json' or 'hybrid' - both allow JSON, so OK
|
|
53
76
|
}
|
|
54
77
|
let effective = 'json';
|
|
55
78
|
if (routeMode) {
|
|
@@ -65,26 +88,51 @@ let CookieTokenInterceptor = class CookieTokenInterceptor {
|
|
|
65
88
|
effective = 'json';
|
|
66
89
|
}
|
|
67
90
|
return next.handle().pipe((0, operators_1.map)((data) => {
|
|
91
|
+
// ============================================================================
|
|
92
|
+
// Safety: Only process object responses
|
|
93
|
+
// ============================================================================
|
|
94
|
+
// Some consumer endpoints (e.g. health checks) legitimately return primitives
|
|
95
|
+
// like strings. The `in` operator throws on non-objects, so we must no-op.
|
|
68
96
|
if (!data || typeof data !== 'object' || Array.isArray(data)) {
|
|
69
97
|
return data;
|
|
70
98
|
}
|
|
71
99
|
const responseData = data;
|
|
72
100
|
const record = data;
|
|
101
|
+
// Handle trust-device endpoint which returns only deviceToken
|
|
73
102
|
const hasDeviceTokenOnly = 'deviceToken' in record && !('accessToken' in record) && typeof responseData.deviceToken === 'string';
|
|
74
103
|
const hasAccessToken = 'accessToken' in record && typeof responseData.accessToken === 'string' && !!responseData.accessToken;
|
|
104
|
+
// Only process responses that include tokens OR deviceToken
|
|
75
105
|
if (!hasAccessToken && !hasDeviceTokenOnly) {
|
|
76
106
|
return responseData;
|
|
77
107
|
}
|
|
108
|
+
// Smart default cookie options
|
|
78
109
|
const opt = deliveryConfig?.cookieOptions;
|
|
110
|
+
// Cookie domain handling:
|
|
111
|
+
// - undefined: Cookie set for exact host:port (e.g., localhost:3000)
|
|
112
|
+
// For cross-port requests (localhost:4200 → localhost:3000), cookies work IF:
|
|
113
|
+
// - Frontend sends withCredentials: true
|
|
114
|
+
// - Backend CORS allows credentials
|
|
115
|
+
// - SameSite allows cross-site requests (e.g., 'lax' or 'none')
|
|
116
|
+
//
|
|
117
|
+
// - 'localhost' or '.localhost': Some browsers accept this, others reject it
|
|
118
|
+
// Modern browsers generally allow 'localhost' without domain attribute
|
|
119
|
+
//
|
|
120
|
+
// - '.example.com': For production cross-subdomain sharing
|
|
121
|
+
// Allows cookies set by api.example.com to be sent from app.example.com
|
|
79
122
|
const cookieOptions = {
|
|
80
123
|
httpOnly: true,
|
|
81
|
-
secure: opt?.secure !== false,
|
|
124
|
+
secure: opt?.secure !== false, // default true
|
|
82
125
|
sameSite: (opt?.sameSite || 'strict'),
|
|
83
126
|
path: opt?.path || '/',
|
|
84
127
|
};
|
|
128
|
+
// Include domain if provided (browsers handle localhost differently - some accept, some reject)
|
|
129
|
+
// For cross-port testing (like Cognito), omitting domain works with sameSite: 'lax' or 'none'
|
|
85
130
|
if (opt?.domain) {
|
|
86
131
|
cookieOptions.domain = opt.domain;
|
|
87
132
|
}
|
|
133
|
+
// Derive expiry strictly from JWT claims (no fallback)
|
|
134
|
+
// We decode here (signature already trusted as tokens are freshly issued);
|
|
135
|
+
// full validation and blacklist checks happen in the AuthGuard on subsequent requests.
|
|
88
136
|
let accessTokenMaxAgeMs = 0;
|
|
89
137
|
if (hasAccessToken && responseData.accessToken) {
|
|
90
138
|
const accessPayload = this.jwtService.decodeToken(responseData.accessToken);
|
|
@@ -105,6 +153,7 @@ let CookieTokenInterceptor = class CookieTokenInterceptor {
|
|
|
105
153
|
res.setCookie(name, value, options);
|
|
106
154
|
}
|
|
107
155
|
};
|
|
156
|
+
// Set cookies only when effective is 'cookies'
|
|
108
157
|
if (effective === 'cookies' && hasAccessToken && responseData.accessToken) {
|
|
109
158
|
const accessTokenCookieName = (0, core_2.getAccessTokenCookieName)(this.config);
|
|
110
159
|
setCookie(accessTokenCookieName, responseData.accessToken, {
|
|
@@ -128,26 +177,36 @@ let CookieTokenInterceptor = class CookieTokenInterceptor {
|
|
|
128
177
|
maxAge: refreshTokenMaxAgeMs,
|
|
129
178
|
});
|
|
130
179
|
}
|
|
180
|
+
// Set device token cookie for trusted device feature (web)
|
|
181
|
+
// Only set cookie when deviceToken is present and effective is cookies
|
|
182
|
+
// (hybrid mode may resolve to cookies for web origins)
|
|
131
183
|
if (typeof responseData.deviceToken === 'string' && responseData.deviceToken && effective === 'cookies') {
|
|
132
184
|
const rememberDeviceDays = this.config.mfa?.rememberDeviceDays || 30;
|
|
133
|
-
const deviceTokenMaxAgeMs = rememberDeviceDays * 24 * 60 * 60 * 1000;
|
|
185
|
+
const deviceTokenMaxAgeMs = rememberDeviceDays * 24 * 60 * 60 * 1000; // Convert days to milliseconds
|
|
134
186
|
const deviceTokenCookieName = (0, core_2.getDeviceTokenCookieName)(this.config);
|
|
135
187
|
setCookie(deviceTokenCookieName, responseData.deviceToken, {
|
|
136
188
|
...cookieOptions,
|
|
137
189
|
maxAge: deviceTokenMaxAgeMs,
|
|
138
190
|
});
|
|
139
191
|
}
|
|
192
|
+
// Set CSRF token cookie when using cookie-based token delivery
|
|
193
|
+
// CSRF token is required for state-changing requests to prevent CSRF attacks
|
|
140
194
|
if (effective === 'cookies' && this.csrfService && this.config.security?.csrf) {
|
|
141
195
|
const csrfToken = this.csrfService.generateToken();
|
|
142
196
|
const csrfCookieName = this.csrfService.getCookieName();
|
|
143
197
|
const csrfCookieOptions = this.csrfService.getCookieOptions();
|
|
198
|
+
// Use same max age as access token for CSRF cookie
|
|
199
|
+
// This ensures CSRF token expires when access token expires
|
|
144
200
|
setCookie(csrfCookieName, csrfToken, {
|
|
145
201
|
...csrfCookieOptions,
|
|
146
202
|
maxAge: accessTokenMaxAgeMs > 0 ? accessTokenMaxAgeMs : undefined,
|
|
147
203
|
});
|
|
148
204
|
}
|
|
205
|
+
// Strip tokens, deviceToken, and expiration fields only when effective is cookies (strict web path)
|
|
206
|
+
// Expiration is managed by cookie maxAge, so these fields are not needed
|
|
149
207
|
if (effective === 'cookies') {
|
|
150
208
|
if (hasDeviceTokenOnly) {
|
|
209
|
+
// For trust-device endpoint, return empty object (deviceToken set as cookie)
|
|
151
210
|
return {};
|
|
152
211
|
}
|
|
153
212
|
const authData = responseData;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cookie-token.interceptor.js","sourceRoot":"","sources":["../../src/interceptors/cookie-token.interceptor.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAoG;AACpG,uCAAyC;AAEzC,8CAAqC;AACrC,8CAU6B;AAC7B,2DAA0D;AAC1D,qFAA2F;AAC3F,2DAAuD;
|
|
1
|
+
{"version":3,"file":"cookie-token.interceptor.js","sourceRoot":"","sources":["../../src/interceptors/cookie-token.interceptor.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,18 +1,114 @@
|
|
|
1
1
|
import { LoggerProvider, LogMetadata, LogLevel } from '@nauth-toolkit/core';
|
|
2
|
+
/**
|
|
3
|
+
* NestJS Logger Adapter
|
|
4
|
+
*
|
|
5
|
+
* Default logger adapter that uses NestJS's built-in Logger.
|
|
6
|
+
* Automatically redacts PII from all log messages and metadata.
|
|
7
|
+
*
|
|
8
|
+
* **Features:**
|
|
9
|
+
* - Uses NestJS Logger (familiar to NestJS developers)
|
|
10
|
+
* - Automatic PII redaction (emails, IPs, tokens, passwords)
|
|
11
|
+
* - Structured logging with metadata
|
|
12
|
+
* - Color-coded output in development
|
|
13
|
+
* - JSON output in production (via NestJS config)
|
|
14
|
+
*
|
|
15
|
+
* **Usage:**
|
|
16
|
+
* ```typescript
|
|
17
|
+
* // Default (automatically used if no logger provided)
|
|
18
|
+
* AuthModule.forRoot({
|
|
19
|
+
* logger: {
|
|
20
|
+
* provider: new NestJsLoggerAdapter(),
|
|
21
|
+
* },
|
|
22
|
+
* })
|
|
23
|
+
*
|
|
24
|
+
* // With custom configuration
|
|
25
|
+
* AuthModule.forRoot({
|
|
26
|
+
* logger: {
|
|
27
|
+
* provider: new NestJsLoggerAdapter({
|
|
28
|
+
* context: 'CustomAuth',
|
|
29
|
+
* enablePiiRedaction: true,
|
|
30
|
+
* }),
|
|
31
|
+
* },
|
|
32
|
+
* })
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* const logger = new NestJsLoggerAdapter();
|
|
38
|
+
*
|
|
39
|
+
* logger.log('User logged in', {
|
|
40
|
+
* userId: '123',
|
|
41
|
+
* email: 'user@example.com', // Redacted to u***@***.com
|
|
42
|
+
* ipAddress: '192.168.1.100' // Redacted to 192.168.1.***
|
|
43
|
+
* });
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
2
46
|
export declare class NestJsLoggerAdapter implements LoggerProvider {
|
|
3
47
|
private readonly logger;
|
|
4
48
|
private readonly piiRedactor;
|
|
5
49
|
private readonly enablePiiRedaction;
|
|
50
|
+
/**
|
|
51
|
+
* Constructor
|
|
52
|
+
*
|
|
53
|
+
* @param options - Logger configuration options
|
|
54
|
+
*/
|
|
6
55
|
constructor(options?: {
|
|
7
56
|
context?: string;
|
|
8
57
|
enablePiiRedaction?: boolean;
|
|
9
58
|
piiRedactionOptions?: Record<string, unknown>;
|
|
10
59
|
});
|
|
60
|
+
/**
|
|
61
|
+
* Log debug message (lowest priority)
|
|
62
|
+
*
|
|
63
|
+
* Used for detailed debugging information.
|
|
64
|
+
* Only logged if log level is set to 'debug'.
|
|
65
|
+
*
|
|
66
|
+
* @param message - Log message
|
|
67
|
+
* @param metadata - Additional context (PII will be redacted)
|
|
68
|
+
*/
|
|
11
69
|
debug(message: string, metadata?: LogMetadata): void;
|
|
70
|
+
/**
|
|
71
|
+
* Log informational message
|
|
72
|
+
*
|
|
73
|
+
* Used for general informational messages about system operation.
|
|
74
|
+
*
|
|
75
|
+
* @param message - Log message
|
|
76
|
+
* @param metadata - Additional context (PII will be redacted)
|
|
77
|
+
*/
|
|
12
78
|
log(message: string, metadata?: LogMetadata): void;
|
|
79
|
+
/**
|
|
80
|
+
* Log warning message
|
|
81
|
+
*
|
|
82
|
+
* Used for potentially harmful situations.
|
|
83
|
+
*
|
|
84
|
+
* @param message - Log message
|
|
85
|
+
* @param metadata - Additional context (PII will be redacted)
|
|
86
|
+
*/
|
|
13
87
|
warn(message: string, metadata?: LogMetadata): void;
|
|
88
|
+
/**
|
|
89
|
+
* Log error message (highest priority)
|
|
90
|
+
*
|
|
91
|
+
* Used for error events that might still allow the application to continue.
|
|
92
|
+
*
|
|
93
|
+
* @param message - Log message
|
|
94
|
+
* @param metadata - Additional context (PII will be redacted)
|
|
95
|
+
*/
|
|
14
96
|
error(message: string, metadata?: LogMetadata): void;
|
|
97
|
+
/**
|
|
98
|
+
* Set log level at runtime
|
|
99
|
+
*
|
|
100
|
+
* Note: NestJS Logger doesn't directly support runtime log level changes,
|
|
101
|
+
* but you can use Logger.overrideLogger() globally.
|
|
102
|
+
*
|
|
103
|
+
* @param level - Log level to set
|
|
104
|
+
*/
|
|
15
105
|
setLogLevel(level: LogLevel): void;
|
|
106
|
+
/**
|
|
107
|
+
* Check if a log level is enabled
|
|
108
|
+
*
|
|
109
|
+
* @param level - Log level to check
|
|
110
|
+
* @returns True if the level is enabled
|
|
111
|
+
*/
|
|
16
112
|
isLevelEnabled(_level: LogLevel): boolean;
|
|
17
113
|
}
|
|
18
114
|
//# sourceMappingURL=nestjs-logger.adapter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nestjs-logger.adapter.d.ts","sourceRoot":"","sources":["../../src/providers/nestjs-logger.adapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,QAAQ,EAAe,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"nestjs-logger.adapter.d.ts","sourceRoot":"","sources":["../../src/providers/nestjs-logger.adapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,QAAQ,EAAe,MAAM,qBAAqB,CAAC;AAEzF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,qBACa,mBAAoB,YAAW,cAAc;IACxD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;IAC1C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAU;IAE7C;;;;OAIG;gBACS,OAAO,CAAC,EAAE;QACpB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,kBAAkB,CAAC,EAAE,OAAO,CAAC;QAC7B,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAC/C;IASD;;;;;;;;OAQG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,WAAW,GAAG,IAAI;IAWpD;;;;;;;OAOG;IACH,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,WAAW,GAAG,IAAI;IAWlD;;;;;;;OAOG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,WAAW,GAAG,IAAI;IAWnD;;;;;;;OAOG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,WAAW,GAAG,IAAI;IAoBpD;;;;;;;OAOG;IACH,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAMlC;;;;;OAKG;IACH,cAAc,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO;CAK1C"}
|
|
@@ -12,15 +12,75 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.NestJsLoggerAdapter = void 0;
|
|
13
13
|
const common_1 = require("@nestjs/common");
|
|
14
14
|
const core_1 = require("@nauth-toolkit/core");
|
|
15
|
+
/**
|
|
16
|
+
* NestJS Logger Adapter
|
|
17
|
+
*
|
|
18
|
+
* Default logger adapter that uses NestJS's built-in Logger.
|
|
19
|
+
* Automatically redacts PII from all log messages and metadata.
|
|
20
|
+
*
|
|
21
|
+
* **Features:**
|
|
22
|
+
* - Uses NestJS Logger (familiar to NestJS developers)
|
|
23
|
+
* - Automatic PII redaction (emails, IPs, tokens, passwords)
|
|
24
|
+
* - Structured logging with metadata
|
|
25
|
+
* - Color-coded output in development
|
|
26
|
+
* - JSON output in production (via NestJS config)
|
|
27
|
+
*
|
|
28
|
+
* **Usage:**
|
|
29
|
+
* ```typescript
|
|
30
|
+
* // Default (automatically used if no logger provided)
|
|
31
|
+
* AuthModule.forRoot({
|
|
32
|
+
* logger: {
|
|
33
|
+
* provider: new NestJsLoggerAdapter(),
|
|
34
|
+
* },
|
|
35
|
+
* })
|
|
36
|
+
*
|
|
37
|
+
* // With custom configuration
|
|
38
|
+
* AuthModule.forRoot({
|
|
39
|
+
* logger: {
|
|
40
|
+
* provider: new NestJsLoggerAdapter({
|
|
41
|
+
* context: 'CustomAuth',
|
|
42
|
+
* enablePiiRedaction: true,
|
|
43
|
+
* }),
|
|
44
|
+
* },
|
|
45
|
+
* })
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* const logger = new NestJsLoggerAdapter();
|
|
51
|
+
*
|
|
52
|
+
* logger.log('User logged in', {
|
|
53
|
+
* userId: '123',
|
|
54
|
+
* email: 'user@example.com', // Redacted to u***@***.com
|
|
55
|
+
* ipAddress: '192.168.1.100' // Redacted to 192.168.1.***
|
|
56
|
+
* });
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
15
59
|
let NestJsLoggerAdapter = class NestJsLoggerAdapter {
|
|
16
60
|
logger;
|
|
17
61
|
piiRedactor;
|
|
18
62
|
enablePiiRedaction;
|
|
63
|
+
/**
|
|
64
|
+
* Constructor
|
|
65
|
+
*
|
|
66
|
+
* @param options - Logger configuration options
|
|
67
|
+
*/
|
|
19
68
|
constructor(options) {
|
|
69
|
+
// Initialize NestJS Logger with context
|
|
20
70
|
this.logger = new common_1.Logger(options?.context || 'nauth-toolkit');
|
|
21
|
-
|
|
71
|
+
// Initialize PII redactor
|
|
72
|
+
this.enablePiiRedaction = options?.enablePiiRedaction !== false; // Default: true
|
|
22
73
|
this.piiRedactor = new core_1.PiiRedactor(options?.piiRedactionOptions);
|
|
23
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Log debug message (lowest priority)
|
|
77
|
+
*
|
|
78
|
+
* Used for detailed debugging information.
|
|
79
|
+
* Only logged if log level is set to 'debug'.
|
|
80
|
+
*
|
|
81
|
+
* @param message - Log message
|
|
82
|
+
* @param metadata - Additional context (PII will be redacted)
|
|
83
|
+
*/
|
|
24
84
|
debug(message, metadata) {
|
|
25
85
|
const safeMessage = this.enablePiiRedaction ? this.piiRedactor.redactMessage(message) : message;
|
|
26
86
|
const safeMetadata = this.enablePiiRedaction ? this.piiRedactor.redactMetadata(metadata) : metadata;
|
|
@@ -31,6 +91,14 @@ let NestJsLoggerAdapter = class NestJsLoggerAdapter {
|
|
|
31
91
|
this.logger.debug(safeMessage);
|
|
32
92
|
}
|
|
33
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* Log informational message
|
|
96
|
+
*
|
|
97
|
+
* Used for general informational messages about system operation.
|
|
98
|
+
*
|
|
99
|
+
* @param message - Log message
|
|
100
|
+
* @param metadata - Additional context (PII will be redacted)
|
|
101
|
+
*/
|
|
34
102
|
log(message, metadata) {
|
|
35
103
|
const safeMessage = this.enablePiiRedaction ? this.piiRedactor.redactMessage(message) : message;
|
|
36
104
|
const safeMetadata = this.enablePiiRedaction ? this.piiRedactor.redactMetadata(metadata) : metadata;
|
|
@@ -41,6 +109,14 @@ let NestJsLoggerAdapter = class NestJsLoggerAdapter {
|
|
|
41
109
|
this.logger.log(safeMessage);
|
|
42
110
|
}
|
|
43
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* Log warning message
|
|
114
|
+
*
|
|
115
|
+
* Used for potentially harmful situations.
|
|
116
|
+
*
|
|
117
|
+
* @param message - Log message
|
|
118
|
+
* @param metadata - Additional context (PII will be redacted)
|
|
119
|
+
*/
|
|
44
120
|
warn(message, metadata) {
|
|
45
121
|
const safeMessage = this.enablePiiRedaction ? this.piiRedactor.redactMessage(message) : message;
|
|
46
122
|
const safeMetadata = this.enablePiiRedaction ? this.piiRedactor.redactMetadata(metadata) : metadata;
|
|
@@ -51,11 +127,21 @@ let NestJsLoggerAdapter = class NestJsLoggerAdapter {
|
|
|
51
127
|
this.logger.warn(safeMessage);
|
|
52
128
|
}
|
|
53
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* Log error message (highest priority)
|
|
132
|
+
*
|
|
133
|
+
* Used for error events that might still allow the application to continue.
|
|
134
|
+
*
|
|
135
|
+
* @param message - Log message
|
|
136
|
+
* @param metadata - Additional context (PII will be redacted)
|
|
137
|
+
*/
|
|
54
138
|
error(message, metadata) {
|
|
55
139
|
const safeMessage = this.enablePiiRedaction ? this.piiRedactor.redactMessage(message) : message;
|
|
56
140
|
const safeMetadata = this.enablePiiRedaction ? this.piiRedactor.redactMetadata(metadata) : metadata;
|
|
57
141
|
if (safeMetadata && safeMetadata.error instanceof Error) {
|
|
142
|
+
// Log error stack trace separately
|
|
58
143
|
this.logger.error(safeMessage, safeMetadata.error.stack);
|
|
144
|
+
// Log remaining metadata
|
|
59
145
|
const { error, ...rest } = safeMetadata;
|
|
60
146
|
if (Object.keys(rest).length > 0) {
|
|
61
147
|
this.logger.error(JSON.stringify(rest));
|
|
@@ -68,10 +154,28 @@ let NestJsLoggerAdapter = class NestJsLoggerAdapter {
|
|
|
68
154
|
this.logger.error(safeMessage);
|
|
69
155
|
}
|
|
70
156
|
}
|
|
157
|
+
/**
|
|
158
|
+
* Set log level at runtime
|
|
159
|
+
*
|
|
160
|
+
* Note: NestJS Logger doesn't directly support runtime log level changes,
|
|
161
|
+
* but you can use Logger.overrideLogger() globally.
|
|
162
|
+
*
|
|
163
|
+
* @param level - Log level to set
|
|
164
|
+
*/
|
|
71
165
|
setLogLevel(level) {
|
|
166
|
+
// NestJS Logger uses global log levels
|
|
167
|
+
// This is a placeholder for future enhancement
|
|
72
168
|
this.logger.log(`Log level set to: ${level}`);
|
|
73
169
|
}
|
|
170
|
+
/**
|
|
171
|
+
* Check if a log level is enabled
|
|
172
|
+
*
|
|
173
|
+
* @param level - Log level to check
|
|
174
|
+
* @returns True if the level is enabled
|
|
175
|
+
*/
|
|
74
176
|
isLevelEnabled(_level) {
|
|
177
|
+
// NestJS Logger doesn't expose this directly
|
|
178
|
+
// Default: all levels enabled
|
|
75
179
|
return true;
|
|
76
180
|
}
|
|
77
181
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nestjs-logger.adapter.js","sourceRoot":"","sources":["../../src/providers/nestjs-logger.adapter.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAAoD;AACpD,8CAAyF;
|
|
1
|
+
{"version":3,"file":"nestjs-logger.adapter.js","sourceRoot":"","sources":["../../src/providers/nestjs-logger.adapter.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAAoD;AACpD,8CAAyF;AAEzF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEI,IAAM,mBAAmB,GAAzB,MAAM,mBAAmB;IACb,MAAM,CAAS;IACf,WAAW,CAAc;IACzB,kBAAkB,CAAU;IAE7C;;;;OAIG;IACH,YAAY,OAIX;QACC,wCAAwC;QACxC,IAAI,CAAC,MAAM,GAAG,IAAI,eAAM,CAAC,OAAO,EAAE,OAAO,IAAI,eAAe,CAAC,CAAC;QAE9D,0BAA0B;QAC1B,IAAI,CAAC,kBAAkB,GAAG,OAAO,EAAE,kBAAkB,KAAK,KAAK,CAAC,CAAC,gBAAgB;QACjF,IAAI,CAAC,WAAW,GAAG,IAAI,kBAAW,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;IACnE,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,OAAe,EAAE,QAAsB;QAC3C,MAAM,WAAW,GAAG,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;QAChG,MAAM,YAAY,GAAG,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;QAEpG,IAAI,YAAY,EAAE,CAAC;YACjB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,WAAW,IAAI,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QACtE,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAED;;;;;;;OAOG;IACH,GAAG,CAAC,OAAe,EAAE,QAAsB;QACzC,MAAM,WAAW,GAAG,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;QAChG,MAAM,YAAY,GAAG,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;QAEpG,IAAI,YAAY,EAAE,CAAC;YACjB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,WAAW,IAAI,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QACpE,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAED;;;;;;;OAOG;IACH,IAAI,CAAC,OAAe,EAAE,QAAsB;QAC1C,MAAM,WAAW,GAAG,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;QAChG,MAAM,YAAY,GAAG,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;QAEpG,IAAI,YAAY,EAAE,CAAC;YACjB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,WAAW,IAAI,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QACrE,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,OAAe,EAAE,QAAsB;QAC3C,MAAM,WAAW,GAAG,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;QAChG,MAAM,YAAY,GAAG,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;QAEpG,IAAI,YAAY,IAAI,YAAY,CAAC,KAAK,YAAY,KAAK,EAAE,CAAC;YACxD,mCAAmC;YACnC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAEzD,yBAAyB;YACzB,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,GAAG,YAAY,CAAC;YACxC,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACjC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;aAAM,IAAI,YAAY,EAAE,CAAC;YACxB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,WAAW,IAAI,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QACtE,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAED;;;;;;;OAOG;IACH,WAAW,CAAC,KAAe;QACzB,uCAAuC;QACvC,+CAA+C;QAC/C,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,qBAAqB,KAAK,EAAE,CAAC,CAAC;IAChD,CAAC;IAED;;;;;OAKG;IACH,cAAc,CAAC,MAAgB;QAC7B,6CAA6C;QAC7C,8BAA8B;QAC9B,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAA;AAtIY,kDAAmB;8BAAnB,mBAAmB;IAD/B,IAAA,mBAAU,GAAE;;GACA,mBAAmB,CAsI/B"}
|
|
@@ -1,8 +1,44 @@
|
|
|
1
1
|
import { NAuthConfig } from '@nauth-toolkit/core';
|
|
2
|
+
/**
|
|
3
|
+
* CSRF Service
|
|
4
|
+
*
|
|
5
|
+
* Generates and manages CSRF tokens for cookie-based token delivery.
|
|
6
|
+
* CSRF protection prevents Cross-Site Request Forgery attacks when tokens
|
|
7
|
+
* are stored in httpOnly cookies.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* const csrfService = new CsrfService(config);
|
|
12
|
+
* const token = csrfService.generateToken();
|
|
13
|
+
* const cookieOptions = csrfService.getCookieOptions();
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
2
16
|
export declare class CsrfService {
|
|
3
17
|
private readonly config;
|
|
4
18
|
constructor(config: NAuthConfig);
|
|
19
|
+
/**
|
|
20
|
+
* Generate a cryptographically secure CSRF token
|
|
21
|
+
*
|
|
22
|
+
* @returns CSRF token as hexadecimal string
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* const token = csrfService.generateToken();
|
|
27
|
+
* // Returns: 'a1b2c3d4e5f6...' (length depends on config.security.csrf.tokenLength)
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
5
30
|
generateToken(): string;
|
|
31
|
+
/**
|
|
32
|
+
* Get CSRF cookie options from configuration
|
|
33
|
+
*
|
|
34
|
+
* @returns Cookie options object with defaults
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* const options = csrfService.getCookieOptions();
|
|
39
|
+
* res.cookie(csrfService.getCookieName(), token, options);
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
6
42
|
getCookieOptions(): {
|
|
7
43
|
httpOnly: boolean;
|
|
8
44
|
secure: boolean;
|
|
@@ -10,7 +46,32 @@ export declare class CsrfService {
|
|
|
10
46
|
domain?: string;
|
|
11
47
|
path?: string;
|
|
12
48
|
};
|
|
49
|
+
/**
|
|
50
|
+
* Get CSRF cookie name from configuration
|
|
51
|
+
*
|
|
52
|
+
* If explicitly configured via security.csrf.cookieName, uses that value.
|
|
53
|
+
* Otherwise, uses the prefix: `${prefix}csrf_token` (default: 'nauth_csrf_token')
|
|
54
|
+
*
|
|
55
|
+
* @returns Cookie name (default: 'nauth_csrf_token' with default prefix)
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```typescript
|
|
59
|
+
* const cookieName = csrfService.getCookieName();
|
|
60
|
+
* // Returns: 'nauth_csrf_token' (or configured value)
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
13
63
|
getCookieName(): string;
|
|
64
|
+
/**
|
|
65
|
+
* Get CSRF header name from configuration
|
|
66
|
+
*
|
|
67
|
+
* @returns Header name (default: 'x-csrf-token')
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```typescript
|
|
71
|
+
* const headerName = csrfService.getHeaderName();
|
|
72
|
+
* // Returns: 'x-csrf-token' (or configured value)
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
14
75
|
getHeaderName(): string;
|
|
15
76
|
}
|
|
16
77
|
//# sourceMappingURL=csrf.service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"csrf.service.d.ts","sourceRoot":"","sources":["../../src/services/csrf.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAA0B,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"csrf.service.d.ts","sourceRoot":"","sources":["../../src/services/csrf.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAA0B,MAAM,qBAAqB,CAAC;AAE1E;;;;;;;;;;;;;GAaG;AACH,qBACa,WAAW;IAGpB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,WAAW;IAGtC;;;;;;;;;;OAUG;IACH,aAAa,IAAI,MAAM;IAKvB;;;;;;;;;;OAUG;IACH,gBAAgB,IAAI;QAClB,QAAQ,EAAE,OAAO,CAAC;QAClB,MAAM,EAAE,OAAO,CAAC;QAChB,QAAQ,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;QACpC,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf;IAWD;;;;;;;;;;;;;OAaG;IACH,aAAa,IAAI,MAAM;IAIvB;;;;;;;;;;OAUG;IACH,aAAa,IAAI,MAAM;CAGxB"}
|
|
@@ -16,28 +16,89 @@ exports.CsrfService = void 0;
|
|
|
16
16
|
const common_1 = require("@nestjs/common");
|
|
17
17
|
const crypto_1 = require("crypto");
|
|
18
18
|
const core_1 = require("@nauth-toolkit/core");
|
|
19
|
+
/**
|
|
20
|
+
* CSRF Service
|
|
21
|
+
*
|
|
22
|
+
* Generates and manages CSRF tokens for cookie-based token delivery.
|
|
23
|
+
* CSRF protection prevents Cross-Site Request Forgery attacks when tokens
|
|
24
|
+
* are stored in httpOnly cookies.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* const csrfService = new CsrfService(config);
|
|
29
|
+
* const token = csrfService.generateToken();
|
|
30
|
+
* const cookieOptions = csrfService.getCookieOptions();
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
19
33
|
let CsrfService = class CsrfService {
|
|
20
34
|
config;
|
|
21
35
|
constructor(config) {
|
|
22
36
|
this.config = config;
|
|
23
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Generate a cryptographically secure CSRF token
|
|
40
|
+
*
|
|
41
|
+
* @returns CSRF token as hexadecimal string
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```typescript
|
|
45
|
+
* const token = csrfService.generateToken();
|
|
46
|
+
* // Returns: 'a1b2c3d4e5f6...' (length depends on config.security.csrf.tokenLength)
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
24
49
|
generateToken() {
|
|
25
50
|
const tokenLength = this.config.security?.csrf?.tokenLength || 32;
|
|
26
51
|
return (0, crypto_1.randomBytes)(tokenLength).toString('hex');
|
|
27
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Get CSRF cookie options from configuration
|
|
55
|
+
*
|
|
56
|
+
* @returns Cookie options object with defaults
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```typescript
|
|
60
|
+
* const options = csrfService.getCookieOptions();
|
|
61
|
+
* res.cookie(csrfService.getCookieName(), token, options);
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
28
64
|
getCookieOptions() {
|
|
29
65
|
const config = this.config.security?.csrf?.cookieOptions;
|
|
30
66
|
return {
|
|
31
|
-
httpOnly: false,
|
|
67
|
+
httpOnly: false, // Fixed: CSRF token must be readable by JavaScript to send in header
|
|
32
68
|
secure: config?.secure ?? true,
|
|
33
69
|
sameSite: config?.sameSite ?? 'strict',
|
|
34
70
|
domain: config?.domain,
|
|
35
71
|
path: config?.path ?? '/',
|
|
36
72
|
};
|
|
37
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Get CSRF cookie name from configuration
|
|
76
|
+
*
|
|
77
|
+
* If explicitly configured via security.csrf.cookieName, uses that value.
|
|
78
|
+
* Otherwise, uses the prefix: `${prefix}csrf_token` (default: 'nauth_csrf_token')
|
|
79
|
+
*
|
|
80
|
+
* @returns Cookie name (default: 'nauth_csrf_token' with default prefix)
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```typescript
|
|
84
|
+
* const cookieName = csrfService.getCookieName();
|
|
85
|
+
* // Returns: 'nauth_csrf_token' (or configured value)
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
38
88
|
getCookieName() {
|
|
39
89
|
return (0, core_1.getCsrfTokenCookieName)(this.config);
|
|
40
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Get CSRF header name from configuration
|
|
93
|
+
*
|
|
94
|
+
* @returns Header name (default: 'x-csrf-token')
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* const headerName = csrfService.getHeaderName();
|
|
99
|
+
* // Returns: 'x-csrf-token' (or configured value)
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
41
102
|
getHeaderName() {
|
|
42
103
|
return this.config.security?.csrf?.headerName || 'x-csrf-token';
|
|
43
104
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"csrf.service.js","sourceRoot":"","sources":["../../src/services/csrf.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAoD;AACpD,mCAAqC;AACrC,8CAA0E;
|
|
1
|
+
{"version":3,"file":"csrf.service.js","sourceRoot":"","sources":["../../src/services/csrf.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAoD;AACpD,mCAAqC;AACrC,8CAA0E;AAE1E;;;;;;;;;;;;;GAaG;AAEI,IAAM,WAAW,GAAjB,MAAM,WAAW;IAGH;IAFnB,YAEmB,MAAmB;QAAnB,WAAM,GAAN,MAAM,CAAa;IACnC,CAAC;IAEJ;;;;;;;;;;OAUG;IACH,aAAa;QACX,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,EAAE,WAAW,IAAI,EAAE,CAAC;QAClE,OAAO,IAAA,oBAAW,EAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClD,CAAC;IAED;;;;;;;;;;OAUG;IACH,gBAAgB;QAOd,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,EAAE,aAAa,CAAC;QACzD,OAAO;YACL,QAAQ,EAAE,KAAK,EAAE,qEAAqE;YACtF,MAAM,EAAE,MAAM,EAAE,MAAM,IAAI,IAAI;YAC9B,QAAQ,EAAE,MAAM,EAAE,QAAQ,IAAI,QAAQ;YACtC,MAAM,EAAE,MAAM,EAAE,MAAM;YACtB,IAAI,EAAE,MAAM,EAAE,IAAI,IAAI,GAAG;SAC1B,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,aAAa;QACX,OAAO,IAAA,6BAAsB,EAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC7C,CAAC;IAED;;;;;;;;;;OAUG;IACH,aAAa;QACX,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,EAAE,UAAU,IAAI,cAAc,CAAC;IAClE,CAAC;CACF,CAAA;AAlFY,kCAAW;sBAAX,WAAW;IADvB,IAAA,mBAAU,GAAE;IAGR,WAAA,IAAA,eAAM,EAAC,cAAc,CAAC,CAAA;;GAFd,WAAW,CAkFvB"}
|