dms-middleware-auth 1.2.2 → 1.2.3

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.
@@ -23,7 +23,7 @@ export declare class AuthMiddleware implements NestMiddleware, OnModuleInit {
23
23
  private static licenceExpiryInterval;
24
24
  private static readonly licenceExpiredMessage;
25
25
  private static readonly licenceValidationFailedMessage;
26
- private static readonly CLOCK_TOLERANCE_MS;
26
+ private static readonly LICENCE_MONITOR_INTERVAL_MS;
27
27
  private static readonly LIC_CACHE_TTL_SECONDS;
28
28
  private static readonly CLIENT_TOKEN_TTL_MAX_SECONDS;
29
29
  private static readonly CLIENT_TOKEN_TTL_SAFETY_SKEW_SECONDS;
@@ -33,6 +33,7 @@ export declare class AuthMiddleware implements NestMiddleware, OnModuleInit {
33
33
  onModuleInit(): Promise<void>;
34
34
  use(req: any, res: Response, next: NextFunction): Promise<void | Response<any, Record<string, any>>>;
35
35
  private enforceLicenceExpiry;
36
+ private monitorLicenceRuntime;
36
37
  private markLicenceExpired;
37
38
  private stopServer;
38
39
  private checkLicenceAndValidate;
@@ -65,16 +65,17 @@ let AuthMiddleware = AuthMiddleware_1 = class AuthMiddleware {
65
65
  const { realm, publicKey } = this.options;
66
66
  // Validate once on boot
67
67
  await this.checkLicenceAndValidate(realm, publicKey);
68
- // Periodic expiry check (safe: small interval only)
68
+ this.monitorLicenceRuntime();
69
+ // Periodic expiry check (safe: short interval, no long timers)
69
70
  if (!AuthMiddleware_1.licenceExpiryInterval) {
70
71
  AuthMiddleware_1.licenceExpiryInterval = setInterval(() => {
71
72
  try {
72
- this.enforceLicenceExpiry();
73
+ this.monitorLicenceRuntime();
73
74
  }
74
75
  catch (e) {
75
76
  this.logger.warn(`Licence expiry interval error: ${e?.message || e}`);
76
77
  }
77
- }, 60 * 60 * 1000); // Check every hour
78
+ }, AuthMiddleware_1.LICENCE_MONITOR_INTERVAL_MS);
78
79
  }
79
80
  }
80
81
  // -------------------------
@@ -172,8 +173,14 @@ let AuthMiddleware = AuthMiddleware_1 = class AuthMiddleware {
172
173
  if (!AuthMiddleware_1.licenceValidatedUntilMs)
173
174
  return;
174
175
  const now = Date.now();
175
- if (now >= AuthMiddleware_1.licenceValidatedUntilMs + AuthMiddleware_1.CLOCK_TOLERANCE_MS) {
176
- this.markLicenceExpired(AuthMiddleware_1.licenceValidatedUntilMs, 'licence end time reached');
176
+ if (now >= AuthMiddleware_1.licenceValidatedUntilMs) {
177
+ this.markLicenceExpired(AuthMiddleware_1.licenceValidatedUntilMs, 'Licence Expired');
178
+ }
179
+ }
180
+ monitorLicenceRuntime() {
181
+ this.enforceLicenceExpiry();
182
+ if (AuthMiddleware_1.licenceExpired) {
183
+ this.stopServer();
177
184
  }
178
185
  }
179
186
  markLicenceExpired(expiredAtMs, reason) {
@@ -223,8 +230,8 @@ let AuthMiddleware = AuthMiddleware_1 = class AuthMiddleware {
223
230
  // If we already have an expiry in memory, decide immediately.
224
231
  if (AuthMiddleware_1.licenceValidatedUntilMs) {
225
232
  const now = Date.now();
226
- if (now >= AuthMiddleware_1.licenceValidatedUntilMs + AuthMiddleware_1.CLOCK_TOLERANCE_MS) {
227
- this.markLicenceExpired(AuthMiddleware_1.licenceValidatedUntilMs, 'in-memory licence already expired');
233
+ if (now >= AuthMiddleware_1.licenceValidatedUntilMs) {
234
+ this.markLicenceExpired(AuthMiddleware_1.licenceValidatedUntilMs, 'Licence Expired');
228
235
  return false;
229
236
  }
230
237
  return true;
@@ -281,7 +288,7 @@ let AuthMiddleware = AuthMiddleware_1 = class AuthMiddleware {
281
288
  }
282
289
  return false;
283
290
  }
284
- if (now >= licEndMs + AuthMiddleware_1.CLOCK_TOLERANCE_MS) {
291
+ if (now >= licEndMs) {
285
292
  if (isAuthoritativeToken) {
286
293
  this.logger.error(`Licence already expired. lic_end=${new Date(licEndMs).toISOString()} now=${new Date(now).toISOString()}`);
287
294
  this.markLicenceExpired(licEndMs, 'authoritative token already expired');
@@ -455,8 +462,8 @@ AuthMiddleware.licenceExpiryInterval = null;
455
462
  // ---- Constants ----
456
463
  AuthMiddleware.licenceExpiredMessage = 'Server Licence is expired! Please renew';
457
464
  AuthMiddleware.licenceValidationFailedMessage = 'Server licence validation failed. Please try again.';
458
- // Allow small clock drift
459
- AuthMiddleware.CLOCK_TOLERANCE_MS = 60_000; // 1 minute
465
+ // Runtime monitor cadence for strict licence end enforcement.
466
+ AuthMiddleware.LICENCE_MONITOR_INTERVAL_MS = 10_000; // 10 seconds
460
467
  // Cache TTLs (safe by design; prevents timer overflow)
461
468
  AuthMiddleware.LIC_CACHE_TTL_SECONDS = 24 * 60 * 60; // 24 hours TTL for licence
462
469
  AuthMiddleware.CLIENT_TOKEN_TTL_MAX_SECONDS = 60 * 60; // 1 hour cap
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dms-middleware-auth",
3
- "version": "1.2.2",
3
+ "version": "1.2.3",
4
4
  "description": "Reusable middleware for authentication and authorization in NestJS applications.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -49,8 +49,8 @@ export class AuthMiddleware implements NestMiddleware, OnModuleInit {
49
49
  private static readonly licenceValidationFailedMessage =
50
50
  'Server licence validation failed. Please try again.';
51
51
 
52
- // Allow small clock drift
53
- private static readonly CLOCK_TOLERANCE_MS = 60_000; // 1 minute
52
+ // Runtime monitor cadence for strict licence end enforcement.
53
+ private static readonly LICENCE_MONITOR_INTERVAL_MS = 10_000; // 10 seconds
54
54
 
55
55
  // Cache TTLs (safe by design; prevents timer overflow)
56
56
  private static readonly LIC_CACHE_TTL_SECONDS = 24 * 60 * 60; // 24 hours TTL for licence
@@ -74,16 +74,17 @@ export class AuthMiddleware implements NestMiddleware, OnModuleInit {
74
74
 
75
75
  // Validate once on boot
76
76
  await this.checkLicenceAndValidate(realm, publicKey);
77
+ this.monitorLicenceRuntime();
77
78
 
78
- // Periodic expiry check (safe: small interval only)
79
+ // Periodic expiry check (safe: short interval, no long timers)
79
80
  if (!AuthMiddleware.licenceExpiryInterval) {
80
81
  AuthMiddleware.licenceExpiryInterval = setInterval(() => {
81
82
  try {
82
- this.enforceLicenceExpiry();
83
+ this.monitorLicenceRuntime();
83
84
  } catch (e: any) {
84
85
  this.logger.warn(`Licence expiry interval error: ${e?.message || e}`);
85
86
  }
86
- }, 60 * 60 * 1000); // Check every hour
87
+ }, AuthMiddleware.LICENCE_MONITOR_INTERVAL_MS);
87
88
  }
88
89
  }
89
90
 
@@ -201,31 +202,38 @@ export class AuthMiddleware implements NestMiddleware, OnModuleInit {
201
202
  if (AuthMiddleware.licenceExpired) return;
202
203
  if (!AuthMiddleware.licenceValidatedUntilMs) return;
203
204
 
204
- const now = Date.now();
205
- if (now >= AuthMiddleware.licenceValidatedUntilMs + AuthMiddleware.CLOCK_TOLERANCE_MS) {
206
- this.markLicenceExpired(
207
- AuthMiddleware.licenceValidatedUntilMs,
208
- 'licence end time reached'
209
- );
210
- }
211
- }
212
-
213
- private markLicenceExpired(expiredAtMs?: number | null, reason?: string) {
214
- if (Number.isFinite(expiredAtMs) && Number(expiredAtMs) > 0) {
215
- AuthMiddleware.licenceValidatedUntilMs = Number(expiredAtMs);
216
- }
217
-
218
- if (!AuthMiddleware.licenceExpired) {
219
- AuthMiddleware.licenceExpired = true;
220
- const expiryText = AuthMiddleware.licenceValidatedUntilMs
221
- ? new Date(AuthMiddleware.licenceValidatedUntilMs).toISOString()
222
- : 'unknown';
223
- const reasonText = reason ? ` (reason: ${reason})` : '';
224
- this.logger.error(
225
- `Licence expired at ${expiryText}${reasonText}`
226
- );
227
- }
228
- }
205
+ const now = Date.now();
206
+ if (now >= AuthMiddleware.licenceValidatedUntilMs) {
207
+ this.markLicenceExpired(
208
+ AuthMiddleware.licenceValidatedUntilMs,
209
+ 'Licence Expired'
210
+ );
211
+ }
212
+ }
213
+
214
+ private monitorLicenceRuntime() {
215
+ this.enforceLicenceExpiry();
216
+ if (AuthMiddleware.licenceExpired) {
217
+ this.stopServer();
218
+ }
219
+ }
220
+
221
+ private markLicenceExpired(expiredAtMs?: number | null, reason?: string) {
222
+ if (Number.isFinite(expiredAtMs) && Number(expiredAtMs) > 0) {
223
+ AuthMiddleware.licenceValidatedUntilMs = Number(expiredAtMs);
224
+ }
225
+
226
+ if (!AuthMiddleware.licenceExpired) {
227
+ AuthMiddleware.licenceExpired = true;
228
+ const expiryText = AuthMiddleware.licenceValidatedUntilMs
229
+ ? new Date(AuthMiddleware.licenceValidatedUntilMs).toISOString()
230
+ : 'unknown';
231
+ const reasonText = reason ? ` (reason: ${reason})` : '';
232
+ this.logger.error(
233
+ `Licence expired at ${expiryText}${reasonText}`
234
+ );
235
+ }
236
+ }
229
237
 
230
238
  // -------------------------
231
239
  // Graceful shutdown for EKS
@@ -262,15 +270,15 @@ export class AuthMiddleware implements NestMiddleware, OnModuleInit {
262
270
 
263
271
  // If we already have an expiry in memory, decide immediately.
264
272
  if (AuthMiddleware.licenceValidatedUntilMs) {
265
- const now = Date.now();
266
- if (now >= AuthMiddleware.licenceValidatedUntilMs + AuthMiddleware.CLOCK_TOLERANCE_MS) {
267
- this.markLicenceExpired(
268
- AuthMiddleware.licenceValidatedUntilMs,
269
- 'in-memory licence already expired'
270
- );
271
- return false;
272
- }
273
- return true;
273
+ const now = Date.now();
274
+ if (now >= AuthMiddleware.licenceValidatedUntilMs) {
275
+ this.markLicenceExpired(
276
+ AuthMiddleware.licenceValidatedUntilMs,
277
+ 'Licence Expired'
278
+ );
279
+ return false;
280
+ }
281
+ return true;
274
282
  }
275
283
 
276
284
  // De-duplicate concurrent validations
@@ -328,24 +336,24 @@ export class AuthMiddleware implements NestMiddleware, OnModuleInit {
328
336
  const now = Date.now();
329
337
 
330
338
  if (!licEndMs) {
331
- if (isAuthoritativeToken) {
332
- this.logger.error('Licence token missing lic_end');
333
- this.markLicenceExpired(null, 'authoritative token missing lic_end');
334
- } else {
335
- this.logger.warn('Cached licence token missing lic_end, refetching from service');
336
- }
339
+ if (isAuthoritativeToken) {
340
+ this.logger.error('Licence token missing lic_end');
341
+ this.markLicenceExpired(null, 'authoritative token missing lic_end');
342
+ } else {
343
+ this.logger.warn('Cached licence token missing lic_end, refetching from service');
344
+ }
337
345
  return false;
338
346
  }
339
347
 
340
- if (now >= licEndMs + AuthMiddleware.CLOCK_TOLERANCE_MS) {
341
- if (isAuthoritativeToken) {
342
- this.logger.error(
343
- `Licence already expired. lic_end=${new Date(licEndMs).toISOString()} now=${new Date(now).toISOString()}`
344
- );
345
- this.markLicenceExpired(licEndMs, 'authoritative token already expired');
346
- } else {
347
- this.logger.warn(
348
- `Cached licence token expired. lic_end=${new Date(licEndMs).toISOString()} now=${new Date(now).toISOString()}`
348
+ if (now >= licEndMs) {
349
+ if (isAuthoritativeToken) {
350
+ this.logger.error(
351
+ `Licence already expired. lic_end=${new Date(licEndMs).toISOString()} now=${new Date(now).toISOString()}`
352
+ );
353
+ this.markLicenceExpired(licEndMs, 'authoritative token already expired');
354
+ } else {
355
+ this.logger.warn(
356
+ `Cached licence token expired. lic_end=${new Date(licEndMs).toISOString()} now=${new Date(now).toISOString()}`
349
357
  );
350
358
  }
351
359
  return false;
@@ -370,12 +378,12 @@ export class AuthMiddleware implements NestMiddleware, OnModuleInit {
370
378
  // If JWT invalid, expire
371
379
  const name = e?.name || '';
372
380
  if (name === 'JsonWebTokenError' || name === 'TokenExpiredError' || name === 'NotBeforeError') {
373
- if (isAuthoritativeToken) {
374
- this.logger.error(`Invalid licence token: ${e?.message || e}`);
375
- this.markLicenceExpired(null, `authoritative token invalid (${name})`);
376
- } else {
377
- this.logger.warn(`Cached licence token invalid, refetching from service: ${e?.message || e}`);
378
- }
381
+ if (isAuthoritativeToken) {
382
+ this.logger.error(`Invalid licence token: ${e?.message || e}`);
383
+ this.markLicenceExpired(null, `authoritative token invalid (${name})`);
384
+ } else {
385
+ this.logger.warn(`Cached licence token invalid, refetching from service: ${e?.message || e}`);
386
+ }
379
387
  return false;
380
388
  }
381
389