@igxjs/node-components 1.0.11 → 1.0.13

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/index.d.ts CHANGED
@@ -7,6 +7,70 @@ import { Application, RequestHandler, Request, Response, NextFunction, Router }
7
7
 
8
8
  export { JWTPayload } from 'jose';
9
9
 
10
+ // Logger class for configurable logging
11
+ export class Logger {
12
+ /**
13
+ * Get or create a Logger instance (singleton pattern)
14
+ * @param componentName Component name for log prefix
15
+ * @param enableLogging Enable/disable logging (defaults to NODE_ENV !== 'production')
16
+ * @returns Logger instance
17
+ */
18
+ static getInstance(componentName: string, enableLogging?: boolean): Logger;
19
+
20
+ /**
21
+ * Clear all logger instances (useful for testing)
22
+ */
23
+ static clearInstances(): void;
24
+
25
+ /**
26
+ * Disable colors globally for all logger instances
27
+ */
28
+ static disableColors(): void;
29
+
30
+ /**
31
+ * Enable colors globally for all logger instances
32
+ */
33
+ static enableColors(): void;
34
+
35
+ /**
36
+ * Create a new Logger instance (backward compatibility)
37
+ * Note: Use Logger.getInstance() for singleton pattern
38
+ * @param componentName Component name for log prefix
39
+ * @param enableLogging Enable/disable logging (defaults to NODE_ENV !== 'production')
40
+ */
41
+ constructor(componentName: string, enableLogging?: boolean);
42
+
43
+ /**
44
+ * Log debug message
45
+ * @param args Arguments to log
46
+ */
47
+ debug(...args: any[]): void;
48
+
49
+ /**
50
+ * Log info message
51
+ * @param args Arguments to log
52
+ */
53
+ info(...args: any[]): void;
54
+
55
+ /**
56
+ * Log warning message
57
+ * @param args Arguments to log
58
+ */
59
+ warn(...args: any[]): void;
60
+
61
+ /**
62
+ * Log error message
63
+ * @param args Arguments to log
64
+ */
65
+ error(...args: any[]): void;
66
+
67
+ /**
68
+ * Log general message
69
+ * @param args Arguments to log
70
+ */
71
+ log(...args: any[]): void;
72
+ }
73
+
10
74
  // Session Mode constants
11
75
  export const SessionMode: {
12
76
  SESSION: string;
@@ -15,31 +79,160 @@ export const SessionMode: {
15
79
 
16
80
  // Session Configuration - uses strict UPPERCASE naming convention for all property names
17
81
  export interface SessionConfig {
18
- /** Identity Provider */
82
+ /**
83
+ * SSO Identity Provider endpoint URL
84
+ * @example 'https://idp.example.com/open/api/v1'
85
+ * @required Required when using SSO authentication
86
+ */
19
87
  SSO_ENDPOINT_URL?: string;
88
+
89
+ /**
90
+ * OAuth2 Client ID registered with the Identity Provider
91
+ * @example 'my-app-client-id'
92
+ * @required Required when using SSO authentication
93
+ */
20
94
  SSO_CLIENT_ID?: string;
95
+
96
+ /**
97
+ * OAuth2 Client Secret for authentication
98
+ * @example 'super-secret-client-key'
99
+ * @required Required when using SSO authentication
100
+ */
21
101
  SSO_CLIENT_SECRET?: string;
102
+
103
+ /**
104
+ * Redirect URL after successful SSO login
105
+ * @example '/dashboard' or 'https://myapp.com/home'
106
+ * @default '/'
107
+ */
22
108
  SSO_SUCCESS_URL?: string;
109
+
110
+ /**
111
+ * Redirect URL after failed SSO login
112
+ * @example '/login?error=auth_failed'
113
+ * @default '/login'
114
+ */
23
115
  SSO_FAILURE_URL?: string;
24
116
 
25
- /** Authentication mode: 'session' or 'token' (default: 'session') */
117
+ /**
118
+ * Authentication mode: 'session' for cookie-based sessions, 'token' for JWT token-based auth
119
+ * @example 'session' | 'token'
120
+ * @default 'session'
121
+ */
26
122
  SESSION_MODE?: string;
27
123
 
124
+ /**
125
+ * Session expiration time in milliseconds
126
+ * @example 3600000 (1 hour) or 86400000 (24 hours)
127
+ * @default 3600000 (1 hour)
128
+ */
28
129
  SESSION_AGE?: number;
130
+
131
+ /**
132
+ * Cookie path for session cookies
133
+ * @example '/' for entire site or '/app' for specific path
134
+ * @default '/'
135
+ */
29
136
  SESSION_COOKIE_PATH?: string;
137
+
138
+ /**
139
+ * Secret key used for signing session cookies (should be a strong random string)
140
+ * @example 'your-super-secret-session-key-change-this-in-production'
141
+ * @required Required for session-based authentication
142
+ */
30
143
  SESSION_SECRET?: string;
144
+
145
+ /**
146
+ * Redis key prefix for storing session data
147
+ * @example 'myapp:session:' (will result in keys like 'myapp:session:user@example.com')
148
+ * @default 'sess:'
149
+ */
31
150
  SESSION_PREFIX?: string;
32
151
 
152
+ /**
153
+ * Redis key name for storing session data
154
+ * @example 'user' (results in session.user containing user data)
155
+ * @default 'user'
156
+ */
157
+ SESSION_KEY?: string;
158
+
159
+ /**
160
+ * Redis key name for storing session expiry timestamp
161
+ * @example 'expires' (results in session.expires containing expiry time)
162
+ * @default 'expires'
163
+ */
164
+ SESSION_EXPIRY_KEY?: string;
165
+
166
+ /**
167
+ * Path to custom HTML template for token storage page (TOKEN mode only)
168
+ * @example './templates/token-storage.html'
169
+ * @default Built-in template included in the library
170
+ */
171
+ TOKEN_STORAGE_TEMPLATE_PATH?: string;
172
+
173
+ /**
174
+ * Redis connection URL
175
+ * @example 'redis://localhost:6379' or 'rediss://user:pass@host:6380/0' (rediss for TLS)
176
+ * @required Required when using Redis for session storage
177
+ */
33
178
  REDIS_URL?: string;
179
+
180
+ /**
181
+ * Path to TLS certificate file for secure Redis connections
182
+ * @example '/path/to/redis-ca-cert.pem'
183
+ * @optional Only needed for TLS-enabled Redis connections
184
+ */
34
185
  REDIS_CERT_PATH?: string;
35
186
 
187
+ /**
188
+ * JWE algorithm for token encryption
189
+ * @example 'dir' (Direct Key Agreement) or 'RSA-OAEP' or 'A256KW'
190
+ * @default 'dir'
191
+ * @see https://tools.ietf.org/html/rfc7518#section-4.1
192
+ */
36
193
  JWT_ALGORITHM?: string;
194
+
195
+ /**
196
+ * JWE encryption method
197
+ * @example 'A256GCM' (AES-256 GCM) or 'A128GCM' or 'A192GCM'
198
+ * @default 'A256GCM'
199
+ * @see https://tools.ietf.org/html/rfc7518#section-5.1
200
+ */
37
201
  JWT_ENCRYPTION?: string;
38
- JWT_EXPIRATION_TIME?: string;
202
+
203
+ /**
204
+ * Clock tolerance in seconds for JWT token validation (allows for time drift between servers)
205
+ * @example 30 (allows 30 seconds of clock skew)
206
+ * @default 30
207
+ */
39
208
  JWT_CLOCK_TOLERANCE?: number;
209
+
210
+ /**
211
+ * Hash algorithm for deriving encryption key from secret
212
+ * @example 'SHA-256' or 'SHA-384' or 'SHA-512'
213
+ * @default 'SHA-256'
214
+ */
40
215
  JWT_SECRET_HASH_ALGORITHM?: string;
216
+
217
+ /**
218
+ * JWT issuer claim (iss) - identifies the principal that issued the token
219
+ * @example 'https://myapp.com' or 'my-auth-service'
220
+ * @optional Adds additional security validation
221
+ */
41
222
  JWT_ISSUER?: string;
223
+
224
+ /**
225
+ * JWT audience claim (aud) - identifies the recipients that the token is intended for
226
+ * @example 'https://api.myapp.com' or 'my-api-service'
227
+ * @optional Adds additional security validation
228
+ */
42
229
  JWT_AUDIENCE?: string;
230
+
231
+ /**
232
+ * JWT subject claim (sub) - identifies the principal that is the subject of the token
233
+ * @example 'user-authentication' or 'api-access'
234
+ * @optional Adds additional context to tokens
235
+ */
43
236
  JWT_SUBJECT?: string;
44
237
  }
45
238
 
@@ -78,8 +271,19 @@ export interface SessionUser {
78
271
  // Session Manager
79
272
  export class SessionManager {
80
273
  /**
81
- * Constructor
82
- * @param config - Session configuration (uses strict UPPERCASE property names)
274
+ * Create a new SessionManager instance
275
+ * @param config Session configuration object with UPPERCASE property names
276
+ * @example
277
+ * ```javascript
278
+ * const sessionManager = new SessionManager({
279
+ * SSO_ENDPOINT_URL: 'https://idp.example.com/open/api/v1',
280
+ * SSO_CLIENT_ID: 'my-app-client-id',
281
+ * SSO_CLIENT_SECRET: 'secret-key',
282
+ * SESSION_MODE: 'session', // or 'token' for JWT-based auth
283
+ * SESSION_SECRET: 'your-session-secret',
284
+ * REDIS_URL: 'redis://localhost:6379'
285
+ * });
286
+ * ```
83
287
  */
84
288
  constructor(config: SessionConfig);
85
289
 
@@ -241,89 +445,202 @@ export class RedisManager {
241
445
  * Disconnect from Redis
242
446
  * @returns Returns nothing
243
447
  */
244
- disConnect(): Promise<void>;
448
+ disconnect(): Promise<void>;
245
449
  }
246
450
 
247
451
  // JWT Manager Configuration - uses strict UPPERCASE naming convention with JWT_ prefix for all property names
248
452
  export interface JwtManagerOptions {
249
- /** JWE algorithm (default: 'dir') */
453
+ /**
454
+ * JWE algorithm for token encryption
455
+ * @example 'dir' (Direct Key Agreement - symmetric encryption, recommended for most cases)
456
+ * @example 'RSA-OAEP' (RSA with OAEP padding - for asymmetric encryption)
457
+ * @example 'A256KW' (AES Key Wrap with 256-bit key)
458
+ * @default 'dir'
459
+ * @see https://tools.ietf.org/html/rfc7518#section-4.1
460
+ */
250
461
  JWT_ALGORITHM?: string;
251
-
252
- /** JWE encryption method (default: 'A256GCM') */
462
+
463
+ /**
464
+ * JWE content encryption method
465
+ * @example 'A256GCM' (AES-256 GCM - recommended, highest security)
466
+ * @example 'A128GCM' (AES-128 GCM - faster, lower security)
467
+ * @example 'A192GCM' (AES-192 GCM - balanced)
468
+ * @default 'A256GCM'
469
+ * @see https://tools.ietf.org/html/rfc7518#section-5.1
470
+ */
253
471
  JWT_ENCRYPTION?: string;
254
-
255
- /** Token expiration time (default: '10m') */
256
- JWT_EXPIRATION_TIME?: string;
257
-
258
- /** Clock tolerance in seconds for token validation (default: 30) */
472
+
473
+ /**
474
+ * Token expiration time - accepts number (seconds) or string with time suffix
475
+ * @example 64800 (18 hours as number)
476
+ * @example '18h' (18 hours)
477
+ * @example '7d' (7 days)
478
+ * @example '1080m' (1080 minutes = 18 hours)
479
+ * @example '30s' (30 seconds)
480
+ * @default 64800 (18 hours)
481
+ */
482
+ JWT_EXPIRATION_TIME?: number | string;
483
+
484
+ /**
485
+ * Clock tolerance in seconds for token validation
486
+ * Allows for small time differences between client and server clocks
487
+ * @example 30 (allows 30 seconds of clock drift)
488
+ * @example 60 (more lenient, allows 1 minute of drift)
489
+ * @default 30
490
+ */
259
491
  JWT_CLOCK_TOLERANCE?: number;
260
-
261
- /** Hash algorithm for secret derivation (default: 'SHA-256') */
492
+
493
+ /**
494
+ * Hash algorithm used for deriving encryption key from secret string
495
+ * @example 'SHA-256' (recommended for most cases)
496
+ * @example 'SHA-384' (higher security)
497
+ * @example 'SHA-512' (highest security, slower)
498
+ * @default 'SHA-256'
499
+ */
262
500
  JWT_SECRET_HASH_ALGORITHM?: string;
263
-
264
- /** Optional JWT issuer claim */
501
+
502
+ /**
503
+ * JWT issuer claim (iss) - identifies who issued the token
504
+ * Used for token validation to ensure tokens are from expected source
505
+ * @example 'https://myapp.com'
506
+ * @example 'my-auth-service'
507
+ * @optional Recommended for production environments
508
+ */
265
509
  JWT_ISSUER?: string;
266
-
267
- /** Optional JWT audience claim */
510
+
511
+ /**
512
+ * JWT audience claim (aud) - identifies the intended recipients
513
+ * Used for token validation to ensure tokens are for the correct service
514
+ * @example 'https://api.myapp.com'
515
+ * @example ['api.myapp.com', 'admin.myapp.com'] (can be array)
516
+ * @optional Recommended for production environments
517
+ */
268
518
  JWT_AUDIENCE?: string;
269
-
270
- /** Optional JWT subject claim */
519
+
520
+ /**
521
+ * JWT subject claim (sub) - identifies the principal (subject) of the token
522
+ * Provides context about what the token represents
523
+ * @example 'user-authentication'
524
+ * @example 'api-access-token'
525
+ * @optional Adds semantic meaning to tokens
526
+ */
271
527
  JWT_SUBJECT?: string;
272
528
  }
273
529
 
274
530
  /**
275
531
  * Options for encrypt() method - uses camelCase naming convention
532
+ * These options allow you to override the defaults set in JwtManagerOptions for specific encryption operations
276
533
  */
277
534
  export interface JwtEncryptOptions {
278
- /** Override default algorithm */
535
+ /**
536
+ * Override default JWE algorithm for this specific token
537
+ * @example 'dir' or 'RSA-OAEP'
538
+ * @use-case Use when you need different encryption algorithms for different token types
539
+ */
279
540
  algorithm?: string;
280
541
 
281
- /** Override default encryption method */
542
+ /**
543
+ * Override default encryption method for this specific token
544
+ * @example 'A256GCM' or 'A128GCM'
545
+ * @use-case Use when you need different encryption strength for different token types
546
+ */
282
547
  encryption?: string;
283
548
 
284
- /** Override default expiration time */
285
- expirationTime?: string;
549
+ /**
550
+ * Override default expiration time for this specific token
551
+ * @example '1h' (short-lived token for sensitive operations)
552
+ * @example '30m' (half hour)
553
+ * @example '7d' (long-lived token for remember-me functionality)
554
+ * @example 3600 (1 hour as number in seconds)
555
+ * @use-case Use when different tokens need different lifetimes (e.g., access token vs refresh token)
556
+ */
557
+ expirationTime?: number | string;
286
558
 
287
- /** Override default hash algorithm */
559
+ /**
560
+ * Override default hash algorithm for deriving encryption key
561
+ * @example 'SHA-256' or 'SHA-512'
562
+ * @use-case Use when you need stronger hashing for specific high-security tokens
563
+ */
288
564
  secretHashAlgorithm?: string;
289
565
 
290
- /** Override default issuer claim */
566
+ /**
567
+ * Override default issuer claim for this specific token
568
+ * @example 'https://admin.myapp.com' (for admin tokens)
569
+ * @use-case Use when tokens are issued by different services
570
+ */
291
571
  issuer?: string;
292
572
 
293
- /** Override default audience claim */
573
+ /**
574
+ * Override default audience claim for this specific token
575
+ * @example 'https://api.myapp.com' (for API access tokens)
576
+ * @example ['service1.myapp.com', 'service2.myapp.com'] (multiple audiences)
577
+ * @use-case Use when tokens are intended for different services
578
+ */
294
579
  audience?: string;
295
580
 
296
- /** Override default subject claim */
581
+ /**
582
+ * Override default subject claim for this specific token
583
+ * @example 'password-reset' (for password reset tokens)
584
+ * @example 'email-verification' (for verification tokens)
585
+ * @use-case Use when different token types serve different purposes
586
+ */
297
587
  subject?: string;
298
588
  }
299
589
 
300
590
  /**
301
591
  * Options for decrypt() method - uses camelCase naming convention
592
+ * These options allow you to override validation settings and verify specific claims during decryption
302
593
  */
303
594
  export interface JwtDecryptOptions {
304
- /** Override default clock tolerance */
595
+ /**
596
+ * Override default clock tolerance for this specific token validation
597
+ * @example 30 (seconds) - allows 30 seconds of clock drift
598
+ * @example 60 (seconds) - more lenient for distributed systems
599
+ * @use-case Use when validating tokens from systems with known clock drift issues
600
+ */
305
601
  clockTolerance?: number;
306
602
 
307
- /** Override default hash algorithm */
603
+ /**
604
+ * Override default hash algorithm for deriving decryption key
605
+ * Must match the algorithm used during encryption
606
+ * @example 'SHA-256' or 'SHA-512'
607
+ * @use-case Use when tokens were encrypted with different hash algorithms
608
+ */
308
609
  secretHashAlgorithm?: string;
309
610
 
310
- /** Expected issuer claim for validation */
611
+ /**
612
+ * Expected issuer claim (iss) for validation
613
+ * Token will be rejected if issuer doesn't match
614
+ * @example 'https://myapp.com'
615
+ * @use-case Use to ensure tokens come from a specific trusted source
616
+ */
311
617
  issuer?: string;
312
618
 
313
- /** Expected audience claim for validation */
619
+ /**
620
+ * Expected audience claim (aud) for validation
621
+ * Token will be rejected if audience doesn't match
622
+ * @example 'https://api.myapp.com'
623
+ * @example ['service1.myapp.com', 'service2.myapp.com'] (multiple valid audiences)
624
+ * @use-case Use to ensure tokens are intended for your service
625
+ */
314
626
  audience?: string;
315
627
 
316
- /** Expected subject claim for validation */
628
+ /**
629
+ * Expected subject claim (sub) for validation
630
+ * Token will be rejected if subject doesn't match
631
+ * @example 'user-authentication'
632
+ * @use-case Use to validate tokens are of the expected type/purpose
633
+ */
317
634
  subject?: string;
318
635
  }
319
636
 
320
- export type JwtDecryptResult = JWTDecryptResult<EncryptJWT>;
637
+ export type JwtDecryptResult = JWTDecryptResult;
321
638
 
322
639
  // JwtManager class for JWT encryption and decryption
323
640
  export class JwtManager {
324
641
  algorithm: string;
325
642
  encryption: string;
326
- expirationTime: string;
643
+ expirationTime: number;
327
644
  clockTolerance: number;
328
645
  secretHashAlgorithm: string;
329
646
  issuer?: string;
@@ -333,6 +650,16 @@ export class JwtManager {
333
650
  /**
334
651
  * Create a new JwtManager instance with configurable defaults
335
652
  * @param options Configuration options (uses strict UPPERCASE with JWT_ prefix property names)
653
+ * @example
654
+ * ```javascript
655
+ * const jwtManager = new JwtManager({
656
+ * JWT_ALGORITHM: 'dir',
657
+ * JWT_ENCRYPTION: 'A256GCM',
658
+ * JWT_EXPIRATION_TIME: '18h', // or 64800 seconds
659
+ * JWT_ISSUER: 'https://myapp.com',
660
+ * JWT_AUDIENCE: 'https://api.myapp.com'
661
+ * });
662
+ * ```
336
663
  */
337
664
  constructor(options?: JwtManagerOptions);
338
665
 
@@ -340,17 +667,31 @@ export class JwtManager {
340
667
  * Generate JWT token for user session
341
668
  * @param data User data payload
342
669
  * @param input Secret key or password for encryption
343
- * @param options Per-call configuration overrides (uses strict UPPERCASE with JWT_ prefix property names)
670
+ * @param options Per-call configuration overrides (uses camelCase property names)
344
671
  * @returns Returns encrypted JWT token
345
672
  */
346
673
  encrypt(data: JWTPayload, input: string, options?: JwtEncryptOptions): Promise<string>;
347
674
 
348
675
  /**
349
- * Decrypt JWT token for user session
350
- * @param token JWT token to decrypt
351
- * @param input Secret key or password for decryption
352
- * @param options Per-call configuration overrides (uses strict UPPERCASE with JWT_ prefix property names)
353
- * @returns Returns decrypted JWT token
676
+ * Decrypt and validate JWT token for user session
677
+ * @param token JWT token string to decrypt and validate
678
+ * @param input Secret key or password for decryption (must match the key used for encryption)
679
+ * @param options Per-call validation overrides (uses camelCase property names)
680
+ * @returns Returns decrypted JWT token result containing payload and protected header
681
+ * @throws Will throw error if token is invalid, expired, or validation fails
682
+ * @example
683
+ * ```javascript
684
+ * try {
685
+ * const result = await jwtManager.decrypt(
686
+ * tokenString,
687
+ * 'my-secret-key',
688
+ * { issuer: 'https://myapp.com' } // Optional: validate issuer claim
689
+ * );
690
+ * console.log(result.payload); // Access decrypted data
691
+ * } catch (error) {
692
+ * console.error('Token validation failed:', error.message);
693
+ * }
694
+ * ```
354
695
  */
355
696
  decrypt(token: string, input: string, options?: JwtDecryptOptions): Promise<JwtDecryptResult>;
356
697
  }
@@ -470,4 +811,4 @@ declare module 'express-session' {
470
811
  [key: string]: any;
471
812
  user?: SessionUser;
472
813
  }
473
- }
814
+ }
package/index.js CHANGED
@@ -3,3 +3,4 @@ export { httpCodes, httpMessages, httpErrorHandler, httpNotFoundHandler, CustomE
3
3
  export { RedisManager } from './components/redis.js';
4
4
  export { FlexRouter } from './components/router.js';
5
5
  export { JwtManager } from './components/jwt.js';
6
+ export { Logger } from './components/logger.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@igxjs/node-components",
3
- "version": "1.0.11",
3
+ "version": "1.0.13",
4
4
  "description": "Node components for igxjs",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -12,7 +12,21 @@
12
12
  "url": "git+https://github.com/igxjs/node-components.git"
13
13
  },
14
14
  "keywords": [
15
- "igxjs"
15
+ "igxjs",
16
+ "express",
17
+ "session-management",
18
+ "jwt",
19
+ "jwe",
20
+ "redis",
21
+ "authentication",
22
+ "sso",
23
+ "oauth",
24
+ "middleware",
25
+ "node-components",
26
+ "session",
27
+ "token-auth",
28
+ "bearer-token",
29
+ "express-middleware"
16
30
  ],
17
31
  "author": "Michael",
18
32
  "license": "Apache-2.0",
@@ -20,22 +34,32 @@
20
34
  "url": "https://github.com/igxjs/node-components/issues"
21
35
  },
22
36
  "homepage": "https://github.com/igxjs/node-components#readme",
37
+ "engines": {
38
+ "node": ">=18.0.0"
39
+ },
23
40
  "dependencies": {
24
41
  "@redis/client": "^5.11.0",
25
42
  "@types/express": "^5.0.6",
26
43
  "axios": "^1.13.6",
27
44
  "connect-redis": "^9.0.0",
28
45
  "express-session": "^1.19.0",
29
- "jose": "^6.2.0",
46
+ "jose": "^6.2.1",
30
47
  "memorystore": "^1.6.7"
31
48
  },
32
49
  "devDependencies": {
33
50
  "chai": "^6.2.2",
34
- "express": "^5.2.1",
35
51
  "mocha": "^12.0.0-beta-10",
36
- "sinon": "^21.0.2",
52
+ "sinon": "^21.0.3",
37
53
  "supertest": "^7.0.0"
38
54
  },
55
+ "peerDependencies": {
56
+ "express": "^4.0.0 || ^5.0.0"
57
+ },
58
+ "peerDependenciesMeta": {
59
+ "express": {
60
+ "optional": false
61
+ }
62
+ },
39
63
  "files": [
40
64
  "index.js",
41
65
  "index.d.ts",