dms-middleware-auth 1.0.9 → 1.0.10
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.middleware.d.ts +9 -2
- package/dist/auth.middleware.js +66 -17
- package/package.json +1 -1
- package/src/auth.middleware.ts +135 -87
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { NestMiddleware } from '@nestjs/common';
|
|
1
|
+
import { NestMiddleware, OnModuleInit } from '@nestjs/common';
|
|
2
2
|
import { Response, NextFunction } from 'express';
|
|
3
3
|
import { Cache } from 'cache-manager';
|
|
4
4
|
interface AuthMiddlewareOptions {
|
|
@@ -10,13 +10,18 @@ interface AuthMiddlewareOptions {
|
|
|
10
10
|
clientUuid: string;
|
|
11
11
|
bypassURL: string;
|
|
12
12
|
}
|
|
13
|
-
export declare class AuthMiddleware implements NestMiddleware {
|
|
13
|
+
export declare class AuthMiddleware implements NestMiddleware, OnModuleInit {
|
|
14
14
|
private cacheManager;
|
|
15
15
|
private readonly options;
|
|
16
16
|
private static licenceExpired;
|
|
17
17
|
private static shutdownTimer;
|
|
18
|
+
private static licenceExpiryTimer;
|
|
19
|
+
private static licenceValidatedUntilMs;
|
|
20
|
+
private static licenceValidationPromise;
|
|
21
|
+
private static shutdownInitiated;
|
|
18
22
|
private static readonly licenceExpiredMessage;
|
|
19
23
|
constructor(cacheManager: Cache, options: AuthMiddlewareOptions);
|
|
24
|
+
onModuleInit(): Promise<void>;
|
|
20
25
|
use(req: any, res: Response, next: NextFunction): Promise<void | Response<any, Record<string, any>>>;
|
|
21
26
|
private clientLogin;
|
|
22
27
|
private getUserDetails;
|
|
@@ -25,6 +30,8 @@ export declare class AuthMiddleware implements NestMiddleware {
|
|
|
25
30
|
private getLicencingDetails;
|
|
26
31
|
private validateLicence;
|
|
27
32
|
private markLicenceExpired;
|
|
33
|
+
private scheduleLicenceShutdown;
|
|
34
|
+
private stopServer;
|
|
28
35
|
private normalizeEpochMs;
|
|
29
36
|
private verifyJwt;
|
|
30
37
|
private decodeAccessToken;
|
package/dist/auth.middleware.js
CHANGED
|
@@ -57,18 +57,23 @@ let AuthMiddleware = AuthMiddleware_1 = class AuthMiddleware {
|
|
|
57
57
|
this.cacheManager = cacheManager;
|
|
58
58
|
this.options = options;
|
|
59
59
|
}
|
|
60
|
+
async onModuleInit() {
|
|
61
|
+
const { publicKey, realm } = this.options;
|
|
62
|
+
const isValid = await this.checkLicenceAndValidate(realm, publicKey);
|
|
63
|
+
if (!isValid) {
|
|
64
|
+
this.stopServer();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
60
67
|
async use(req, res, next) {
|
|
61
68
|
const { publicKey, clientId, realm, bypassURL } = this.options;
|
|
62
69
|
try {
|
|
63
70
|
if (AuthMiddleware_1.licenceExpired) {
|
|
64
71
|
return res.status(axios_1.HttpStatusCode.Forbidden).json({ message: AuthMiddleware_1.licenceExpiredMessage });
|
|
65
72
|
}
|
|
66
|
-
|
|
67
|
-
const validate_lic = await this.checkLicenceAndValidate(realm, publicKey);
|
|
68
|
-
if (!validate_lic) {
|
|
73
|
+
if (!AuthMiddleware_1.licenceValidatedUntilMs) {
|
|
69
74
|
return res.status(axios_1.HttpStatusCode.Forbidden).json({ message: AuthMiddleware_1.licenceExpiredMessage });
|
|
70
75
|
}
|
|
71
|
-
|
|
76
|
+
if (req.originalUrl == bypassURL) {
|
|
72
77
|
return next();
|
|
73
78
|
}
|
|
74
79
|
const authHeader = req.headers['authorization'];
|
|
@@ -170,26 +175,30 @@ let AuthMiddleware = AuthMiddleware_1 = class AuthMiddleware {
|
|
|
170
175
|
}
|
|
171
176
|
async checkLicenceAndValidate(realm, publicKey) {
|
|
172
177
|
try {
|
|
173
|
-
// Reuse cached licence when possible; short-circuit if already marked expired.
|
|
174
178
|
if (AuthMiddleware_1.licenceExpired) {
|
|
175
179
|
return false;
|
|
176
180
|
}
|
|
177
|
-
|
|
178
|
-
|
|
181
|
+
if (AuthMiddleware_1.licenceValidatedUntilMs && AuthMiddleware_1.licenceValidatedUntilMs > Date.now()) {
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
if (AuthMiddleware_1.licenceValidationPromise) {
|
|
185
|
+
return await AuthMiddleware_1.licenceValidationPromise;
|
|
186
|
+
}
|
|
187
|
+
AuthMiddleware_1.licenceValidationPromise = (async () => {
|
|
179
188
|
const response = await this.getLicencingDetails(realm);
|
|
180
189
|
if (response.code === axios_1.HttpStatusCode.InternalServerError) {
|
|
181
190
|
return false;
|
|
182
191
|
}
|
|
183
192
|
else {
|
|
184
193
|
const validate = await this.validateLicence(response.data, publicKey);
|
|
185
|
-
if (validate.status && validate.ttl) {
|
|
186
|
-
await this.cacheManager.set('client_Licence_token', response.data, validate.ttl);
|
|
187
|
-
}
|
|
188
194
|
return validate.status;
|
|
189
195
|
}
|
|
196
|
+
})();
|
|
197
|
+
try {
|
|
198
|
+
return await AuthMiddleware_1.licenceValidationPromise;
|
|
190
199
|
}
|
|
191
|
-
|
|
192
|
-
|
|
200
|
+
finally {
|
|
201
|
+
AuthMiddleware_1.licenceValidationPromise = null;
|
|
193
202
|
}
|
|
194
203
|
}
|
|
195
204
|
catch (error) {
|
|
@@ -227,6 +236,7 @@ let AuthMiddleware = AuthMiddleware_1 = class AuthMiddleware {
|
|
|
227
236
|
const licEndMs = this.normalizeEpochMs(token?.lic_end);
|
|
228
237
|
// Reject when licence end (epoch) is missing or already in the past.
|
|
229
238
|
if (!licEndMs) {
|
|
239
|
+
this.markLicenceExpired();
|
|
230
240
|
return {
|
|
231
241
|
status: false
|
|
232
242
|
};
|
|
@@ -238,6 +248,8 @@ let AuthMiddleware = AuthMiddleware_1 = class AuthMiddleware {
|
|
|
238
248
|
};
|
|
239
249
|
}
|
|
240
250
|
else {
|
|
251
|
+
AuthMiddleware_1.licenceValidatedUntilMs = licEndMs;
|
|
252
|
+
this.scheduleLicenceShutdown(licEndMs);
|
|
241
253
|
return {
|
|
242
254
|
status: true,
|
|
243
255
|
ttl: (licEndMs - Date.now()) > 0 ? (licEndMs - Date.now()) : null
|
|
@@ -246,18 +258,51 @@ let AuthMiddleware = AuthMiddleware_1 = class AuthMiddleware {
|
|
|
246
258
|
}
|
|
247
259
|
catch (error) {
|
|
248
260
|
this.markLicenceExpired();
|
|
249
|
-
return
|
|
261
|
+
return {
|
|
262
|
+
status: false
|
|
263
|
+
};
|
|
250
264
|
}
|
|
251
265
|
}
|
|
252
266
|
markLicenceExpired() {
|
|
253
267
|
if (!AuthMiddleware_1.licenceExpired) {
|
|
254
268
|
AuthMiddleware_1.licenceExpired = true;
|
|
255
269
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
270
|
+
this.stopServer();
|
|
271
|
+
}
|
|
272
|
+
scheduleLicenceShutdown(licEndMs) {
|
|
273
|
+
if (!licEndMs) {
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
const delay = licEndMs - Date.now();
|
|
277
|
+
if (delay <= 0) {
|
|
278
|
+
this.markLicenceExpired();
|
|
279
|
+
return;
|
|
260
280
|
}
|
|
281
|
+
if (AuthMiddleware_1.licenceExpiryTimer) {
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
AuthMiddleware_1.licenceExpiryTimer = setTimeout(() => {
|
|
285
|
+
this.markLicenceExpired();
|
|
286
|
+
}, delay);
|
|
287
|
+
}
|
|
288
|
+
stopServer() {
|
|
289
|
+
if (AuthMiddleware_1.shutdownInitiated) {
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
AuthMiddleware_1.shutdownInitiated = true;
|
|
293
|
+
setTimeout(() => {
|
|
294
|
+
try {
|
|
295
|
+
process.kill(process.pid, 'SIGTERM');
|
|
296
|
+
}
|
|
297
|
+
catch {
|
|
298
|
+
process.exit(1);
|
|
299
|
+
}
|
|
300
|
+
if (!AuthMiddleware_1.shutdownTimer) {
|
|
301
|
+
AuthMiddleware_1.shutdownTimer = setTimeout(() => {
|
|
302
|
+
process.exit(1);
|
|
303
|
+
}, 5000);
|
|
304
|
+
}
|
|
305
|
+
}, 0);
|
|
261
306
|
}
|
|
262
307
|
normalizeEpochMs(epoch) {
|
|
263
308
|
if (!epoch || Number.isNaN(epoch)) {
|
|
@@ -284,6 +329,10 @@ let AuthMiddleware = AuthMiddleware_1 = class AuthMiddleware {
|
|
|
284
329
|
exports.AuthMiddleware = AuthMiddleware;
|
|
285
330
|
AuthMiddleware.licenceExpired = false;
|
|
286
331
|
AuthMiddleware.shutdownTimer = null;
|
|
332
|
+
AuthMiddleware.licenceExpiryTimer = null;
|
|
333
|
+
AuthMiddleware.licenceValidatedUntilMs = null;
|
|
334
|
+
AuthMiddleware.licenceValidationPromise = null;
|
|
335
|
+
AuthMiddleware.shutdownInitiated = false;
|
|
287
336
|
AuthMiddleware.licenceExpiredMessage = "server Licence is expired!. please renew";
|
|
288
337
|
exports.AuthMiddleware = AuthMiddleware = AuthMiddleware_1 = __decorate([
|
|
289
338
|
(0, common_1.Injectable)(),
|
package/package.json
CHANGED
package/src/auth.middleware.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Inject, Injectable, NestMiddleware } from '@nestjs/common';
|
|
1
|
+
import { Inject, Injectable, NestMiddleware, OnModuleInit } from '@nestjs/common';
|
|
2
2
|
import { Response, NextFunction } from 'express';
|
|
3
3
|
import * as jwt from 'jsonwebtoken';
|
|
4
4
|
import axios, { HttpStatusCode } from 'axios';
|
|
@@ -16,17 +16,29 @@ interface AuthMiddlewareOptions {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
@Injectable()
|
|
19
|
-
export class AuthMiddleware implements NestMiddleware {
|
|
20
|
-
private static licenceExpired = false;
|
|
21
|
-
private static shutdownTimer: NodeJS.Timeout | null = null;
|
|
22
|
-
private static
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
19
|
+
export class AuthMiddleware implements NestMiddleware, OnModuleInit {
|
|
20
|
+
private static licenceExpired = false;
|
|
21
|
+
private static shutdownTimer: NodeJS.Timeout | null = null;
|
|
22
|
+
private static licenceExpiryTimer: NodeJS.Timeout | null = null;
|
|
23
|
+
private static licenceValidatedUntilMs: number | null = null;
|
|
24
|
+
private static licenceValidationPromise: Promise<boolean> | null = null;
|
|
25
|
+
private static shutdownInitiated = false;
|
|
26
|
+
private static readonly licenceExpiredMessage = "server Licence is expired!. please renew";
|
|
27
|
+
|
|
28
|
+
constructor(
|
|
29
|
+
@Inject(CACHE_MANAGER) private cacheManager: Cache,
|
|
30
|
+
@Inject('AUTH_MIDDLEWARE_OPTIONS') private readonly options: AuthMiddlewareOptions
|
|
31
|
+
) {}
|
|
32
|
+
|
|
33
|
+
async onModuleInit() {
|
|
34
|
+
const { publicKey, realm } = this.options;
|
|
35
|
+
const isValid = await this.checkLicenceAndValidate(realm, publicKey);
|
|
36
|
+
if (!isValid) {
|
|
37
|
+
this.stopServer();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async use(req: any, res: Response, next: NextFunction) {
|
|
30
42
|
|
|
31
43
|
|
|
32
44
|
const { publicKey, clientId, realm, bypassURL } = this.options;
|
|
@@ -36,14 +48,12 @@ export class AuthMiddleware implements NestMiddleware {
|
|
|
36
48
|
return res.status(HttpStatusCode.Forbidden).json({ message: AuthMiddleware.licenceExpiredMessage });
|
|
37
49
|
}
|
|
38
50
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
return next();
|
|
46
|
-
}
|
|
51
|
+
if (!AuthMiddleware.licenceValidatedUntilMs) {
|
|
52
|
+
return res.status(HttpStatusCode.Forbidden).json({ message: AuthMiddleware.licenceExpiredMessage });
|
|
53
|
+
}
|
|
54
|
+
if (req.originalUrl == bypassURL) {
|
|
55
|
+
return next();
|
|
56
|
+
}
|
|
47
57
|
const authHeader = req.headers['authorization'];
|
|
48
58
|
|
|
49
59
|
if (!authHeader || !authHeader.startsWith('Bearer ')) {
|
|
@@ -163,34 +173,36 @@ export class AuthMiddleware implements NestMiddleware {
|
|
|
163
173
|
}
|
|
164
174
|
}
|
|
165
175
|
|
|
166
|
-
private async checkLicenceAndValidate(realm: string, publicKey:string) {
|
|
167
|
-
try {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
return validate.status;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
return await
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
176
|
+
private async checkLicenceAndValidate(realm: string, publicKey:string) {
|
|
177
|
+
try {
|
|
178
|
+
if (AuthMiddleware.licenceExpired) {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
if (AuthMiddleware.licenceValidatedUntilMs && AuthMiddleware.licenceValidatedUntilMs > Date.now()) {
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
if (AuthMiddleware.licenceValidationPromise) {
|
|
185
|
+
return await AuthMiddleware.licenceValidationPromise;
|
|
186
|
+
}
|
|
187
|
+
AuthMiddleware.licenceValidationPromise = (async () => {
|
|
188
|
+
const response:any = await this.getLicencingDetails(realm);
|
|
189
|
+
if (response.code === HttpStatusCode.InternalServerError) {
|
|
190
|
+
return false
|
|
191
|
+
}
|
|
192
|
+
else{
|
|
193
|
+
const validate = await this.validateLicence(response.data, publicKey);
|
|
194
|
+
return validate.status;
|
|
195
|
+
}
|
|
196
|
+
})();
|
|
197
|
+
try {
|
|
198
|
+
return await AuthMiddleware.licenceValidationPromise;
|
|
199
|
+
} finally {
|
|
200
|
+
AuthMiddleware.licenceValidationPromise = null;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
catch(error:any){
|
|
204
|
+
return false;
|
|
205
|
+
|
|
194
206
|
}
|
|
195
207
|
}
|
|
196
208
|
private async getLicencingDetails(realm: string) {
|
|
@@ -222,45 +234,81 @@ export class AuthMiddleware implements NestMiddleware {
|
|
|
222
234
|
};
|
|
223
235
|
}
|
|
224
236
|
}
|
|
225
|
-
private async validateLicence(lic_data:any, publicKey:any){
|
|
226
|
-
try{
|
|
227
|
-
const token:any = await this.verifyJwt(lic_data, publicKey);
|
|
228
|
-
const licEndMs = this.normalizeEpochMs(token?.lic_end);
|
|
229
|
-
// Reject when licence end (epoch) is missing or already in the past.
|
|
230
|
-
if (!licEndMs) {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
}
|
|
237
|
+
private async validateLicence(lic_data:any, publicKey:any){
|
|
238
|
+
try{
|
|
239
|
+
const token:any = await this.verifyJwt(lic_data, publicKey);
|
|
240
|
+
const licEndMs = this.normalizeEpochMs(token?.lic_end);
|
|
241
|
+
// Reject when licence end (epoch) is missing or already in the past.
|
|
242
|
+
if (!licEndMs) {
|
|
243
|
+
this.markLicenceExpired();
|
|
244
|
+
return{
|
|
245
|
+
status: false
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
if (licEndMs <= Date.now()) {
|
|
249
|
+
this.markLicenceExpired();
|
|
250
|
+
return {
|
|
251
|
+
status: false
|
|
252
|
+
}
|
|
253
|
+
} else {
|
|
254
|
+
AuthMiddleware.licenceValidatedUntilMs = licEndMs;
|
|
255
|
+
this.scheduleLicenceShutdown(licEndMs);
|
|
256
|
+
return {
|
|
257
|
+
status: true,
|
|
258
|
+
ttl: (licEndMs - Date.now()) > 0 ? (licEndMs - Date.now()) : null
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
catch(error:any){
|
|
263
|
+
this.markLicenceExpired();
|
|
264
|
+
return {
|
|
265
|
+
status: false
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
private markLicenceExpired() {
|
|
271
|
+
if (!AuthMiddleware.licenceExpired) {
|
|
272
|
+
AuthMiddleware.licenceExpired = true;
|
|
273
|
+
}
|
|
274
|
+
this.stopServer();
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
private scheduleLicenceShutdown(licEndMs: number) {
|
|
278
|
+
if (!licEndMs) {
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
const delay = licEndMs - Date.now();
|
|
282
|
+
if (delay <= 0) {
|
|
283
|
+
this.markLicenceExpired();
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
if (AuthMiddleware.licenceExpiryTimer) {
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
AuthMiddleware.licenceExpiryTimer = setTimeout(() => {
|
|
290
|
+
this.markLicenceExpired();
|
|
291
|
+
}, delay);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
private stopServer() {
|
|
295
|
+
if (AuthMiddleware.shutdownInitiated) {
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
AuthMiddleware.shutdownInitiated = true;
|
|
299
|
+
setTimeout(() => {
|
|
300
|
+
try {
|
|
301
|
+
process.kill(process.pid, 'SIGTERM');
|
|
302
|
+
} catch {
|
|
303
|
+
process.exit(1);
|
|
304
|
+
}
|
|
305
|
+
if (!AuthMiddleware.shutdownTimer) {
|
|
306
|
+
AuthMiddleware.shutdownTimer = setTimeout(() => {
|
|
307
|
+
process.exit(1);
|
|
308
|
+
}, 5000);
|
|
309
|
+
}
|
|
310
|
+
}, 0);
|
|
311
|
+
}
|
|
264
312
|
|
|
265
313
|
private normalizeEpochMs(epoch: number): number | null {
|
|
266
314
|
if (!epoch || Number.isNaN(epoch)) {
|