b23-lib 1.1.0 → 1.2.0

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/index.d.mts CHANGED
@@ -235,30 +235,54 @@ declare const Schema: {
235
235
  };
236
236
  };
237
237
 
238
+ type StringifiedJSONArray = string;
239
+ type AuthUtilityConfig = {
240
+ maxTokenAge?: string;
241
+ userPrivateKeys?: StringifiedJSONArray;
242
+ userPublicKeys?: StringifiedJSONArray;
243
+ anonymousPrivateKeys?: StringifiedJSONArray;
244
+ anonymousPublicKeys?: StringifiedJSONArray;
245
+ systemPrivateKeys?: StringifiedJSONArray;
246
+ systemPublicKeys?: StringifiedJSONArray;
247
+ adminPrivateKeys?: StringifiedJSONArray;
248
+ adminPublicKeys?: StringifiedJSONArray;
249
+ };
250
+ type AuthMiddlewareConfig = {
251
+ allowAnonymous: boolean;
252
+ allowSystem: boolean;
253
+ allowUser: boolean;
254
+ };
238
255
  declare class AuthUtility {
239
- private secretToken;
240
256
  private maxTokenAge;
241
- constructor({ secret, maxTokenAge }: {
242
- secret: string;
243
- maxTokenAge: string;
244
- });
245
- createToken(id: string, additionalData: object): Promise<string>;
246
- verifyToken(token: string): Promise<jose.JWTPayload>;
247
- AuthMiddleware(): (req: any, res: any, next: any) => Promise<void>;
257
+ private userPrivateKeys;
258
+ private userPublicKeys;
259
+ private anonymousPrivateKeys;
260
+ private anonymousPublicKeys;
261
+ private systemPrivateKeys;
262
+ private systemPublicKeys;
263
+ private adminPrivateKeys;
264
+ private adminPublicKeys;
265
+ constructor({ maxTokenAge, userPrivateKeys, userPublicKeys, anonymousPrivateKeys, anonymousPublicKeys, systemPrivateKeys, systemPublicKeys, adminPrivateKeys, adminPublicKeys }?: AuthUtilityConfig);
266
+ private createSignedJWT;
267
+ private verifySignedJWT;
268
+ createAnonymousToken(id: string, additionalData?: object): Promise<string>;
269
+ verifyAnonymousToken(token: string): Promise<jose.JWTPayload>;
270
+ createUserToken(id: string, additionalData?: object): Promise<string>;
271
+ verifyUserToken(token: string): Promise<jose.JWTPayload>;
272
+ createSystemToken(id: string, additionalData?: object): Promise<string>;
273
+ verifySystemToken(token: string): Promise<jose.JWTPayload>;
274
+ createAdminToken(id: string, additionalData?: object): Promise<string>;
275
+ verifyAdminToken(token: string): Promise<jose.JWTPayload>;
276
+ AuthMiddleware({ allowAnonymous, allowSystem, allowUser }?: AuthMiddlewareConfig): (req: any, res: any, next: any) => Promise<void>;
248
277
  }
249
278
 
250
- declare const ResponseUtility: {
251
- handleException: (functionName: string, error: any, res: any) => void;
252
- generateResponse: (status: number, data?: any, error?: string) => {
253
- status: number;
254
- data: any;
255
- error: string | undefined;
256
- };
257
- generateError: (status: number, error: string, knownError?: Boolean, logError?: boolean) => {
258
- status: number;
259
- error: string;
260
- knownError: Boolean;
261
- logError: boolean;
279
+ declare const _default: {
280
+ isUUID: (value: string) => boolean;
281
+ generateUUID: (value?: string, namespace?: string) => string;
282
+ generateSearchId: (key: string, variantId: string) => string;
283
+ getKeyfromSearchId: (searchId: string) => {
284
+ key: string;
285
+ variantId: string;
262
286
  };
263
287
  };
264
288
 
@@ -272,8 +296,9 @@ declare const Fetch: (baseURL: string, endpoint: string, method?: "GET" | "POST"
272
296
  declare const Logger: {
273
297
  logException: (functionName: string, error: any) => void;
274
298
  logError: (functionName: string, errorMessage: string) => void;
299
+ logWarning: (functionName: string, message: any) => void;
275
300
  logMessage: (functionName: string, message: any) => void;
276
301
  logInvalidPayload: (functionName: string, errorMessage: string) => void;
277
302
  };
278
303
 
279
- export { AuthUtility as Auth, DynamoDBUtility as DynamoDB, Fetch, Logger, ResponseUtility, Schema };
304
+ export { AuthUtility as Auth, DynamoDBUtility as DynamoDB, Fetch, Logger, _default as ResponseUtility, Schema, _default as Utils };
package/dist/index.d.ts CHANGED
@@ -235,30 +235,54 @@ declare const Schema: {
235
235
  };
236
236
  };
237
237
 
238
+ type StringifiedJSONArray = string;
239
+ type AuthUtilityConfig = {
240
+ maxTokenAge?: string;
241
+ userPrivateKeys?: StringifiedJSONArray;
242
+ userPublicKeys?: StringifiedJSONArray;
243
+ anonymousPrivateKeys?: StringifiedJSONArray;
244
+ anonymousPublicKeys?: StringifiedJSONArray;
245
+ systemPrivateKeys?: StringifiedJSONArray;
246
+ systemPublicKeys?: StringifiedJSONArray;
247
+ adminPrivateKeys?: StringifiedJSONArray;
248
+ adminPublicKeys?: StringifiedJSONArray;
249
+ };
250
+ type AuthMiddlewareConfig = {
251
+ allowAnonymous: boolean;
252
+ allowSystem: boolean;
253
+ allowUser: boolean;
254
+ };
238
255
  declare class AuthUtility {
239
- private secretToken;
240
256
  private maxTokenAge;
241
- constructor({ secret, maxTokenAge }: {
242
- secret: string;
243
- maxTokenAge: string;
244
- });
245
- createToken(id: string, additionalData: object): Promise<string>;
246
- verifyToken(token: string): Promise<jose.JWTPayload>;
247
- AuthMiddleware(): (req: any, res: any, next: any) => Promise<void>;
257
+ private userPrivateKeys;
258
+ private userPublicKeys;
259
+ private anonymousPrivateKeys;
260
+ private anonymousPublicKeys;
261
+ private systemPrivateKeys;
262
+ private systemPublicKeys;
263
+ private adminPrivateKeys;
264
+ private adminPublicKeys;
265
+ constructor({ maxTokenAge, userPrivateKeys, userPublicKeys, anonymousPrivateKeys, anonymousPublicKeys, systemPrivateKeys, systemPublicKeys, adminPrivateKeys, adminPublicKeys }?: AuthUtilityConfig);
266
+ private createSignedJWT;
267
+ private verifySignedJWT;
268
+ createAnonymousToken(id: string, additionalData?: object): Promise<string>;
269
+ verifyAnonymousToken(token: string): Promise<jose.JWTPayload>;
270
+ createUserToken(id: string, additionalData?: object): Promise<string>;
271
+ verifyUserToken(token: string): Promise<jose.JWTPayload>;
272
+ createSystemToken(id: string, additionalData?: object): Promise<string>;
273
+ verifySystemToken(token: string): Promise<jose.JWTPayload>;
274
+ createAdminToken(id: string, additionalData?: object): Promise<string>;
275
+ verifyAdminToken(token: string): Promise<jose.JWTPayload>;
276
+ AuthMiddleware({ allowAnonymous, allowSystem, allowUser }?: AuthMiddlewareConfig): (req: any, res: any, next: any) => Promise<void>;
248
277
  }
249
278
 
250
- declare const ResponseUtility: {
251
- handleException: (functionName: string, error: any, res: any) => void;
252
- generateResponse: (status: number, data?: any, error?: string) => {
253
- status: number;
254
- data: any;
255
- error: string | undefined;
256
- };
257
- generateError: (status: number, error: string, knownError?: Boolean, logError?: boolean) => {
258
- status: number;
259
- error: string;
260
- knownError: Boolean;
261
- logError: boolean;
279
+ declare const _default: {
280
+ isUUID: (value: string) => boolean;
281
+ generateUUID: (value?: string, namespace?: string) => string;
282
+ generateSearchId: (key: string, variantId: string) => string;
283
+ getKeyfromSearchId: (searchId: string) => {
284
+ key: string;
285
+ variantId: string;
262
286
  };
263
287
  };
264
288
 
@@ -272,8 +296,9 @@ declare const Fetch: (baseURL: string, endpoint: string, method?: "GET" | "POST"
272
296
  declare const Logger: {
273
297
  logException: (functionName: string, error: any) => void;
274
298
  logError: (functionName: string, errorMessage: string) => void;
299
+ logWarning: (functionName: string, message: any) => void;
275
300
  logMessage: (functionName: string, message: any) => void;
276
301
  logInvalidPayload: (functionName: string, errorMessage: string) => void;
277
302
  };
278
303
 
279
- export { AuthUtility as Auth, DynamoDBUtility as DynamoDB, Fetch, Logger, ResponseUtility, Schema };
304
+ export { AuthUtility as Auth, DynamoDBUtility as DynamoDB, Fetch, Logger, _default as ResponseUtility, Schema, _default as Utils };
package/dist/index.js CHANGED
@@ -34,8 +34,9 @@ __export(src_exports, {
34
34
  DynamoDB: () => Dynamodb_default,
35
35
  Fetch: () => fetch_default,
36
36
  Logger: () => Logger_default,
37
- ResponseUtility: () => response_default,
38
- Schema: () => Schema_default
37
+ ResponseUtility: () => Utils_default,
38
+ Schema: () => Schema_default,
39
+ Utils: () => Utils_default
39
40
  });
40
41
  module.exports = __toCommonJS(src_exports);
41
42
 
@@ -414,8 +415,22 @@ var import_util2 = __toESM(require("util"));
414
415
 
415
416
  // src/enums/ErrorTypes.ts
416
417
  var ErrorTypes_default = Object.freeze({
418
+ INVALID_UUID: "Invalid UUID",
417
419
  INVALID_TOKEN: "Invalid Token",
418
420
  TOKEN_EXPIRED: "Token Expired",
421
+ INVALID_AUTH_TYPE: "Invalid Authorization Type",
422
+ USER_PRIVATE_KEY_NOT_FOUND: "User Private Key Not Found",
423
+ USER_PUBLIC_KEY_NOT_FOUND: "User Public Key Not Found",
424
+ ANONYMOUS_PRIVATE_KEY_NOT_FOUND: "Anonymous Private Key Not Found",
425
+ ANONYMOUS_PUBLIC_KEY_NOT_FOUND: "Anonymous Public Key Not Found",
426
+ SYSTEM_PRIVATE_KEY_NOT_FOUND: "System Private Key Not Found",
427
+ SYSTEM_PUBLIC_KEY_NOT_FOUND: "System Public Key Not Found",
428
+ ADMIN_PRIVATE_KEY_NOT_FOUND: "Admin Private Key Not Found",
429
+ ADMIN_PUBLIC_KEY_NOT_FOUND: "Admin Public Key Not Found",
430
+ SECRET_TOKEN_NOT_FOUND: "Secret Token Not Found",
431
+ ANONYMOUS_SESSION_NOT_ALLOWED: "Anonymous Session Not Allowed",
432
+ USER_SESSION_NOT_ALLOWED: "User Session Not Allowed",
433
+ SYSTEM_SESSION_NOT_ALLOWED: "System Session Not Allowed",
419
434
  INTERNAL_SERVER_ERROR: "Internal Server Error"
420
435
  });
421
436
 
@@ -423,20 +438,48 @@ var ErrorTypes_default = Object.freeze({
423
438
  var import_util = __toESM(require("util"));
424
439
  var Logger = {
425
440
  logException: (functionName, error) => {
426
- console.log(`Exception Occurred in Function: ${functionName}, Error: ${import_util.default.inspect(error)}`);
441
+ console.error(`Exception Occurred in Function: ${functionName}, Error: ${import_util.default.inspect(error)}`);
427
442
  },
428
443
  logError: (functionName, errorMessage) => {
429
- console.log(`Error Occurred in Function: ${functionName}, Error: ${import_util.default.inspect(errorMessage)}`);
444
+ console.error(`Error Occurred in Function: ${functionName}, Error: ${import_util.default.inspect(errorMessage)}`);
445
+ },
446
+ logWarning: (functionName, message) => {
447
+ console.warn(`Warning in Function: ${functionName} - ${import_util.default.inspect(message)}`);
430
448
  },
431
449
  logMessage: (functionName, message) => {
432
- console.log(`Message in Function: ${functionName}, Error: ${import_util.default.inspect(message)}`);
450
+ console.log(`Message in Function: ${functionName} - ${import_util.default.inspect(message)}`);
433
451
  },
434
452
  logInvalidPayload: (functionName, errorMessage) => {
435
- console.log(`Invalid Payload received for Function: ${functionName}, Error: ${errorMessage}`);
453
+ console.error(`Invalid Payload received for Function: ${functionName}, Error: ${errorMessage}`);
436
454
  }
437
455
  };
438
456
  var Logger_default = Logger;
439
457
 
458
+ // src/Utils/index.ts
459
+ var import_uuid = require("uuid");
460
+ var Utils_default = {
461
+ isUUID: (value) => {
462
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
463
+ return uuidRegex.test(value);
464
+ },
465
+ generateUUID: (value, namespace) => {
466
+ if (namespace && value) {
467
+ return (0, import_uuid.v5)(value, namespace);
468
+ }
469
+ return (0, import_uuid.v4)();
470
+ },
471
+ generateSearchId: (key, variantId) => {
472
+ return `${key}#${variantId}`;
473
+ },
474
+ getKeyfromSearchId: (searchId) => {
475
+ const [key, variantId] = searchId.split("#");
476
+ return {
477
+ key,
478
+ variantId
479
+ };
480
+ }
481
+ };
482
+
440
483
  // src/Utils/response.ts
441
484
  var ResponseUtility = {
442
485
  handleException: (functionName, error, res) => {
@@ -446,6 +489,12 @@ var ResponseUtility = {
446
489
  status: error.status,
447
490
  error: error.error
448
491
  });
492
+ } else if (error.status && error.error) {
493
+ Logger_default.logException(functionName, error);
494
+ res.status(error.status).json({
495
+ ...error.error,
496
+ status: error.status
497
+ });
449
498
  } else {
450
499
  Logger_default.logException(functionName, error);
451
500
  res.status(500).json({
@@ -473,40 +522,193 @@ var ResponseUtility = {
473
522
  var response_default = ResponseUtility;
474
523
 
475
524
  // src/Auth/index.ts
525
+ var import_assert = __toESM(require("assert"));
526
+ var DefaultAuthUtilityConfig = {
527
+ maxTokenAge: "30 days",
528
+ userPrivateKeys: "[]",
529
+ userPublicKeys: "[]",
530
+ anonymousPrivateKeys: "[]",
531
+ anonymousPublicKeys: "[]",
532
+ systemPrivateKeys: "[]",
533
+ systemPublicKeys: "[]",
534
+ adminPrivateKeys: "[]",
535
+ adminPublicKeys: "[]"
536
+ };
537
+ var DefaultAuthMiddlewareConfig = {
538
+ allowAnonymous: false,
539
+ allowSystem: true,
540
+ allowUser: true
541
+ };
476
542
  var AuthUtility = class {
477
- secretToken;
478
543
  maxTokenAge;
479
- constructor({ secret, maxTokenAge = "30 days" }) {
480
- this.secretToken = secret;
544
+ userPrivateKeys;
545
+ userPublicKeys;
546
+ anonymousPrivateKeys;
547
+ anonymousPublicKeys;
548
+ systemPrivateKeys;
549
+ systemPublicKeys;
550
+ adminPrivateKeys;
551
+ adminPublicKeys;
552
+ constructor({ maxTokenAge = "30 days", userPrivateKeys = "[]", userPublicKeys = "[]", anonymousPrivateKeys = "[]", anonymousPublicKeys = "[]", systemPrivateKeys = "[]", systemPublicKeys = "[]", adminPrivateKeys = "[]", adminPublicKeys = "[]" } = DefaultAuthUtilityConfig) {
481
553
  this.maxTokenAge = maxTokenAge;
554
+ this.userPrivateKeys = JSON.parse(userPrivateKeys);
555
+ if (this.userPrivateKeys.length > 3) {
556
+ Logger_default.logWarning("AuthUtility", "More than 1 user private key provided. The last key will be used for signing.");
557
+ }
558
+ this.userPublicKeys = JSON.parse(userPublicKeys);
559
+ if (this.userPublicKeys.length > 3) {
560
+ Logger_default.logWarning("AuthUtility", "More than 3 user public keys provided. This is not recommended.");
561
+ }
562
+ this.anonymousPrivateKeys = JSON.parse(anonymousPrivateKeys);
563
+ if (this.anonymousPrivateKeys.length > 1) {
564
+ Logger_default.logWarning("AuthUtility", "More than 1 anonymous private key provided. The last key will be used for signing.");
565
+ }
566
+ this.anonymousPublicKeys = JSON.parse(anonymousPublicKeys);
567
+ if (this.anonymousPublicKeys.length > 3) {
568
+ Logger_default.logWarning("AuthUtility", "More than 3 anonymous public keys provided. This is not recommended.");
569
+ }
570
+ this.systemPrivateKeys = JSON.parse(systemPrivateKeys);
571
+ if (this.systemPrivateKeys.length > 1) {
572
+ Logger_default.logWarning("AuthUtility", "More than 1 system private key provided. The last key will be used for signing.");
573
+ }
574
+ this.systemPublicKeys = JSON.parse(systemPublicKeys);
575
+ if (this.systemPublicKeys.length > 3) {
576
+ Logger_default.logWarning("AuthUtility", "More than 3 system public keys provided. This is not recommended.");
577
+ }
578
+ this.adminPrivateKeys = JSON.parse(adminPrivateKeys);
579
+ if (this.adminPrivateKeys.length > 1) {
580
+ Logger_default.logWarning("AuthUtility", "More than 1 admin private key provided. The last key will be used for signing.");
581
+ }
582
+ this.adminPublicKeys = JSON.parse(adminPublicKeys);
583
+ if (this.adminPublicKeys.length > 3) {
584
+ Logger_default.logWarning("AuthUtility", "More than 3 admin public keys provided. This is not recommended.");
585
+ }
586
+ }
587
+ async createSignedJWT(payload, privateKeyString, expiration) {
588
+ const privateKey = await (0, import_jose.importPKCS8)(privateKeyString, "RS256");
589
+ const token = await new import_jose.SignJWT(payload).setProtectedHeader({ alg: "RS256" }).setExpirationTime(expiration).setIssuedAt().sign(privateKey);
590
+ return token;
591
+ }
592
+ async verifySignedJWT(token, publicKeyString, expiration) {
593
+ for (let i = publicKeyString.length - 1; i > 0; i--) {
594
+ try {
595
+ const publicKey2 = await (0, import_jose.importSPKI)(publicKeyString[i], "RS256");
596
+ const jwt2 = await (0, import_jose.jwtVerify)(token, publicKey2, { clockTolerance: 30, maxTokenAge: expiration });
597
+ return jwt2.payload;
598
+ } catch (error) {
599
+ continue;
600
+ }
601
+ }
602
+ const publicKey = await (0, import_jose.importSPKI)(publicKeyString[0], "RS256");
603
+ const jwt = await (0, import_jose.jwtVerify)(token, publicKey, { clockTolerance: 30, maxTokenAge: expiration });
604
+ return jwt.payload;
482
605
  }
483
- async createToken(id, additionalData) {
606
+ async createAnonymousToken(id, additionalData) {
607
+ (0, import_assert.default)(this.anonymousPrivateKeys.length, ErrorTypes_default.ANONYMOUS_PRIVATE_KEY_NOT_FOUND);
608
+ (0, import_assert.default)(Utils_default.isUUID(id), ErrorTypes_default.INVALID_UUID);
484
609
  const payload = {
485
610
  id,
611
+ type: "Anon",
486
612
  ...additionalData
487
613
  };
488
- const secretKey = Buffer.from(this.secretToken, "hex");
489
- const token = await new import_jose.EncryptJWT(payload).setExpirationTime(this.maxTokenAge).setIssuedAt().setProtectedHeader({ alg: "dir", enc: "A256CBC-HS512" }).encrypt(secretKey);
490
- return token;
614
+ return await this.createSignedJWT(payload, this.anonymousPrivateKeys[this.anonymousPrivateKeys.length - 1], this.maxTokenAge);
491
615
  }
492
- async verifyToken(token) {
493
- const secretKey = Buffer.from(this.secretToken, "hex");
494
- const jwt = await (0, import_jose.jwtDecrypt)(token, secretKey, { maxTokenAge: this.maxTokenAge });
495
- return jwt.payload;
616
+ async verifyAnonymousToken(token) {
617
+ (0, import_assert.default)(this.anonymousPublicKeys.length, ErrorTypes_default.ANONYMOUS_PUBLIC_KEY_NOT_FOUND);
618
+ const payload = await this.verifySignedJWT(token, this.anonymousPublicKeys, this.maxTokenAge);
619
+ (0, import_assert.default)(payload.type === "Anon", ErrorTypes_default.INVALID_AUTH_TYPE);
620
+ return payload;
621
+ }
622
+ async createUserToken(id, additionalData) {
623
+ (0, import_assert.default)(this.userPrivateKeys.length, ErrorTypes_default.USER_PRIVATE_KEY_NOT_FOUND);
624
+ (0, import_assert.default)(Utils_default.isUUID(id), ErrorTypes_default.INVALID_UUID);
625
+ const payload = {
626
+ id,
627
+ type: "User",
628
+ ...additionalData
629
+ };
630
+ return await this.createSignedJWT(payload, this.userPrivateKeys[this.userPrivateKeys.length - 1], this.maxTokenAge);
631
+ }
632
+ async verifyUserToken(token) {
633
+ (0, import_assert.default)(this.userPublicKeys.length, ErrorTypes_default.USER_PUBLIC_KEY_NOT_FOUND);
634
+ const payload = await this.verifySignedJWT(token, this.userPublicKeys, this.maxTokenAge);
635
+ (0, import_assert.default)(payload.type === "User", ErrorTypes_default.INVALID_AUTH_TYPE);
636
+ return payload;
496
637
  }
497
- AuthMiddleware() {
638
+ async createSystemToken(id, additionalData) {
639
+ (0, import_assert.default)(this.userPrivateKeys.length, ErrorTypes_default.USER_PRIVATE_KEY_NOT_FOUND);
640
+ (0, import_assert.default)(Utils_default.isUUID(id), ErrorTypes_default.INVALID_UUID);
641
+ const payload = {
642
+ id,
643
+ type: "System",
644
+ ...additionalData
645
+ };
646
+ return await this.createSignedJWT(payload, this.systemPrivateKeys[this.systemPrivateKeys.length - 1], "5 min");
647
+ }
648
+ async verifySystemToken(token) {
649
+ (0, import_assert.default)(this.systemPublicKeys.length, ErrorTypes_default.USER_PUBLIC_KEY_NOT_FOUND);
650
+ const payload = await this.verifySignedJWT(token, this.systemPublicKeys, "5 min");
651
+ (0, import_assert.default)(payload.type === "System", ErrorTypes_default.INVALID_AUTH_TYPE);
652
+ return payload;
653
+ }
654
+ async createAdminToken(id, additionalData) {
655
+ (0, import_assert.default)(this.adminPrivateKeys.length, ErrorTypes_default.ADMIN_PRIVATE_KEY_NOT_FOUND);
656
+ (0, import_assert.default)(Utils_default.isUUID(id), ErrorTypes_default.INVALID_UUID);
657
+ const payload = {
658
+ id,
659
+ type: "Admin",
660
+ ...additionalData
661
+ };
662
+ return await this.createSignedJWT(payload, this.adminPrivateKeys[this.adminPrivateKeys.length - 1], this.maxTokenAge);
663
+ }
664
+ async verifyAdminToken(token) {
665
+ (0, import_assert.default)(this.adminPublicKeys.length, ErrorTypes_default.ADMIN_PUBLIC_KEY_NOT_FOUND);
666
+ const payload = await this.verifySignedJWT(token, this.adminPublicKeys, this.maxTokenAge);
667
+ (0, import_assert.default)(payload.type === "Admin", ErrorTypes_default.INVALID_AUTH_TYPE);
668
+ return payload;
669
+ }
670
+ AuthMiddleware({ allowAnonymous, allowSystem, allowUser } = DefaultAuthMiddlewareConfig) {
498
671
  return async (req, res, next) => {
499
672
  try {
500
- const token = req.get("Authorization")?.split(" ")?.[1];
673
+ const [authType, token] = req.get("Authorization")?.split(" ");
501
674
  if (!token) {
502
675
  throw new Error(ErrorTypes_default.INVALID_TOKEN);
503
676
  }
504
- const payload = await this.verifyToken(token);
505
- res.locals.auth = payload;
677
+ let payload;
678
+ switch (authType) {
679
+ case "Anon":
680
+ if (!allowAnonymous) {
681
+ throw response_default.generateError(403, ErrorTypes_default.ANONYMOUS_SESSION_NOT_ALLOWED);
682
+ }
683
+ payload = await this.verifyAnonymousToken(token);
684
+ break;
685
+ case "User":
686
+ if (!allowUser) {
687
+ throw response_default.generateError(403, ErrorTypes_default.USER_SESSION_NOT_ALLOWED);
688
+ }
689
+ payload = await this.verifyUserToken(token);
690
+ break;
691
+ case "System":
692
+ if (!allowSystem) {
693
+ throw response_default.generateError(403, ErrorTypes_default.SYSTEM_SESSION_NOT_ALLOWED);
694
+ }
695
+ payload = await this.verifySystemToken(token);
696
+ break;
697
+ case "Admin":
698
+ payload = await this.verifyAdminToken(token);
699
+ break;
700
+ default:
701
+ throw response_default.generateError(403, ErrorTypes_default.INVALID_AUTH_TYPE);
702
+ }
703
+ res.locals.auth = {
704
+ authType,
705
+ token,
706
+ ...payload
707
+ };
506
708
  next();
507
709
  } catch (error) {
508
710
  Logger_default.logError("AuthMiddleware", import_util2.default.inspect(error));
509
- response_default.handleException("AuthMiddleware", response_default.generateError(401, ErrorTypes_default.TOKEN_EXPIRED), res);
711
+ response_default.handleException("AuthMiddleware", response_default.generateError(401, error.error ? error.error : ErrorTypes_default.TOKEN_EXPIRED, true), res);
510
712
  }
511
713
  };
512
714
  }
@@ -565,5 +767,6 @@ var fetch_default = Fetch;
565
767
  Fetch,
566
768
  Logger,
567
769
  ResponseUtility,
568
- Schema
770
+ Schema,
771
+ Utils
569
772
  });
package/dist/index.mjs CHANGED
@@ -383,13 +383,27 @@ var Schema = {
383
383
  var Schema_default = Schema;
384
384
 
385
385
  // src/Auth/index.ts
386
- import { EncryptJWT, jwtDecrypt } from "jose";
386
+ import { importPKCS8, importSPKI, jwtVerify, SignJWT } from "jose";
387
387
  import util2 from "util";
388
388
 
389
389
  // src/enums/ErrorTypes.ts
390
390
  var ErrorTypes_default = Object.freeze({
391
+ INVALID_UUID: "Invalid UUID",
391
392
  INVALID_TOKEN: "Invalid Token",
392
393
  TOKEN_EXPIRED: "Token Expired",
394
+ INVALID_AUTH_TYPE: "Invalid Authorization Type",
395
+ USER_PRIVATE_KEY_NOT_FOUND: "User Private Key Not Found",
396
+ USER_PUBLIC_KEY_NOT_FOUND: "User Public Key Not Found",
397
+ ANONYMOUS_PRIVATE_KEY_NOT_FOUND: "Anonymous Private Key Not Found",
398
+ ANONYMOUS_PUBLIC_KEY_NOT_FOUND: "Anonymous Public Key Not Found",
399
+ SYSTEM_PRIVATE_KEY_NOT_FOUND: "System Private Key Not Found",
400
+ SYSTEM_PUBLIC_KEY_NOT_FOUND: "System Public Key Not Found",
401
+ ADMIN_PRIVATE_KEY_NOT_FOUND: "Admin Private Key Not Found",
402
+ ADMIN_PUBLIC_KEY_NOT_FOUND: "Admin Public Key Not Found",
403
+ SECRET_TOKEN_NOT_FOUND: "Secret Token Not Found",
404
+ ANONYMOUS_SESSION_NOT_ALLOWED: "Anonymous Session Not Allowed",
405
+ USER_SESSION_NOT_ALLOWED: "User Session Not Allowed",
406
+ SYSTEM_SESSION_NOT_ALLOWED: "System Session Not Allowed",
393
407
  INTERNAL_SERVER_ERROR: "Internal Server Error"
394
408
  });
395
409
 
@@ -397,20 +411,48 @@ var ErrorTypes_default = Object.freeze({
397
411
  import util from "util";
398
412
  var Logger = {
399
413
  logException: (functionName, error) => {
400
- console.log(`Exception Occurred in Function: ${functionName}, Error: ${util.inspect(error)}`);
414
+ console.error(`Exception Occurred in Function: ${functionName}, Error: ${util.inspect(error)}`);
401
415
  },
402
416
  logError: (functionName, errorMessage) => {
403
- console.log(`Error Occurred in Function: ${functionName}, Error: ${util.inspect(errorMessage)}`);
417
+ console.error(`Error Occurred in Function: ${functionName}, Error: ${util.inspect(errorMessage)}`);
418
+ },
419
+ logWarning: (functionName, message) => {
420
+ console.warn(`Warning in Function: ${functionName} - ${util.inspect(message)}`);
404
421
  },
405
422
  logMessage: (functionName, message) => {
406
- console.log(`Message in Function: ${functionName}, Error: ${util.inspect(message)}`);
423
+ console.log(`Message in Function: ${functionName} - ${util.inspect(message)}`);
407
424
  },
408
425
  logInvalidPayload: (functionName, errorMessage) => {
409
- console.log(`Invalid Payload received for Function: ${functionName}, Error: ${errorMessage}`);
426
+ console.error(`Invalid Payload received for Function: ${functionName}, Error: ${errorMessage}`);
410
427
  }
411
428
  };
412
429
  var Logger_default = Logger;
413
430
 
431
+ // src/Utils/index.ts
432
+ import { v4 as uuidv4, v5 as uuidv5 } from "uuid";
433
+ var Utils_default = {
434
+ isUUID: (value) => {
435
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
436
+ return uuidRegex.test(value);
437
+ },
438
+ generateUUID: (value, namespace) => {
439
+ if (namespace && value) {
440
+ return uuidv5(value, namespace);
441
+ }
442
+ return uuidv4();
443
+ },
444
+ generateSearchId: (key, variantId) => {
445
+ return `${key}#${variantId}`;
446
+ },
447
+ getKeyfromSearchId: (searchId) => {
448
+ const [key, variantId] = searchId.split("#");
449
+ return {
450
+ key,
451
+ variantId
452
+ };
453
+ }
454
+ };
455
+
414
456
  // src/Utils/response.ts
415
457
  var ResponseUtility = {
416
458
  handleException: (functionName, error, res) => {
@@ -420,6 +462,12 @@ var ResponseUtility = {
420
462
  status: error.status,
421
463
  error: error.error
422
464
  });
465
+ } else if (error.status && error.error) {
466
+ Logger_default.logException(functionName, error);
467
+ res.status(error.status).json({
468
+ ...error.error,
469
+ status: error.status
470
+ });
423
471
  } else {
424
472
  Logger_default.logException(functionName, error);
425
473
  res.status(500).json({
@@ -447,40 +495,193 @@ var ResponseUtility = {
447
495
  var response_default = ResponseUtility;
448
496
 
449
497
  // src/Auth/index.ts
498
+ import assert from "assert";
499
+ var DefaultAuthUtilityConfig = {
500
+ maxTokenAge: "30 days",
501
+ userPrivateKeys: "[]",
502
+ userPublicKeys: "[]",
503
+ anonymousPrivateKeys: "[]",
504
+ anonymousPublicKeys: "[]",
505
+ systemPrivateKeys: "[]",
506
+ systemPublicKeys: "[]",
507
+ adminPrivateKeys: "[]",
508
+ adminPublicKeys: "[]"
509
+ };
510
+ var DefaultAuthMiddlewareConfig = {
511
+ allowAnonymous: false,
512
+ allowSystem: true,
513
+ allowUser: true
514
+ };
450
515
  var AuthUtility = class {
451
- secretToken;
452
516
  maxTokenAge;
453
- constructor({ secret, maxTokenAge = "30 days" }) {
454
- this.secretToken = secret;
517
+ userPrivateKeys;
518
+ userPublicKeys;
519
+ anonymousPrivateKeys;
520
+ anonymousPublicKeys;
521
+ systemPrivateKeys;
522
+ systemPublicKeys;
523
+ adminPrivateKeys;
524
+ adminPublicKeys;
525
+ constructor({ maxTokenAge = "30 days", userPrivateKeys = "[]", userPublicKeys = "[]", anonymousPrivateKeys = "[]", anonymousPublicKeys = "[]", systemPrivateKeys = "[]", systemPublicKeys = "[]", adminPrivateKeys = "[]", adminPublicKeys = "[]" } = DefaultAuthUtilityConfig) {
455
526
  this.maxTokenAge = maxTokenAge;
527
+ this.userPrivateKeys = JSON.parse(userPrivateKeys);
528
+ if (this.userPrivateKeys.length > 3) {
529
+ Logger_default.logWarning("AuthUtility", "More than 1 user private key provided. The last key will be used for signing.");
530
+ }
531
+ this.userPublicKeys = JSON.parse(userPublicKeys);
532
+ if (this.userPublicKeys.length > 3) {
533
+ Logger_default.logWarning("AuthUtility", "More than 3 user public keys provided. This is not recommended.");
534
+ }
535
+ this.anonymousPrivateKeys = JSON.parse(anonymousPrivateKeys);
536
+ if (this.anonymousPrivateKeys.length > 1) {
537
+ Logger_default.logWarning("AuthUtility", "More than 1 anonymous private key provided. The last key will be used for signing.");
538
+ }
539
+ this.anonymousPublicKeys = JSON.parse(anonymousPublicKeys);
540
+ if (this.anonymousPublicKeys.length > 3) {
541
+ Logger_default.logWarning("AuthUtility", "More than 3 anonymous public keys provided. This is not recommended.");
542
+ }
543
+ this.systemPrivateKeys = JSON.parse(systemPrivateKeys);
544
+ if (this.systemPrivateKeys.length > 1) {
545
+ Logger_default.logWarning("AuthUtility", "More than 1 system private key provided. The last key will be used for signing.");
546
+ }
547
+ this.systemPublicKeys = JSON.parse(systemPublicKeys);
548
+ if (this.systemPublicKeys.length > 3) {
549
+ Logger_default.logWarning("AuthUtility", "More than 3 system public keys provided. This is not recommended.");
550
+ }
551
+ this.adminPrivateKeys = JSON.parse(adminPrivateKeys);
552
+ if (this.adminPrivateKeys.length > 1) {
553
+ Logger_default.logWarning("AuthUtility", "More than 1 admin private key provided. The last key will be used for signing.");
554
+ }
555
+ this.adminPublicKeys = JSON.parse(adminPublicKeys);
556
+ if (this.adminPublicKeys.length > 3) {
557
+ Logger_default.logWarning("AuthUtility", "More than 3 admin public keys provided. This is not recommended.");
558
+ }
559
+ }
560
+ async createSignedJWT(payload, privateKeyString, expiration) {
561
+ const privateKey = await importPKCS8(privateKeyString, "RS256");
562
+ const token = await new SignJWT(payload).setProtectedHeader({ alg: "RS256" }).setExpirationTime(expiration).setIssuedAt().sign(privateKey);
563
+ return token;
564
+ }
565
+ async verifySignedJWT(token, publicKeyString, expiration) {
566
+ for (let i = publicKeyString.length - 1; i > 0; i--) {
567
+ try {
568
+ const publicKey2 = await importSPKI(publicKeyString[i], "RS256");
569
+ const jwt2 = await jwtVerify(token, publicKey2, { clockTolerance: 30, maxTokenAge: expiration });
570
+ return jwt2.payload;
571
+ } catch (error) {
572
+ continue;
573
+ }
574
+ }
575
+ const publicKey = await importSPKI(publicKeyString[0], "RS256");
576
+ const jwt = await jwtVerify(token, publicKey, { clockTolerance: 30, maxTokenAge: expiration });
577
+ return jwt.payload;
456
578
  }
457
- async createToken(id, additionalData) {
579
+ async createAnonymousToken(id, additionalData) {
580
+ assert(this.anonymousPrivateKeys.length, ErrorTypes_default.ANONYMOUS_PRIVATE_KEY_NOT_FOUND);
581
+ assert(Utils_default.isUUID(id), ErrorTypes_default.INVALID_UUID);
458
582
  const payload = {
459
583
  id,
584
+ type: "Anon",
460
585
  ...additionalData
461
586
  };
462
- const secretKey = Buffer.from(this.secretToken, "hex");
463
- const token = await new EncryptJWT(payload).setExpirationTime(this.maxTokenAge).setIssuedAt().setProtectedHeader({ alg: "dir", enc: "A256CBC-HS512" }).encrypt(secretKey);
464
- return token;
587
+ return await this.createSignedJWT(payload, this.anonymousPrivateKeys[this.anonymousPrivateKeys.length - 1], this.maxTokenAge);
465
588
  }
466
- async verifyToken(token) {
467
- const secretKey = Buffer.from(this.secretToken, "hex");
468
- const jwt = await jwtDecrypt(token, secretKey, { maxTokenAge: this.maxTokenAge });
469
- return jwt.payload;
589
+ async verifyAnonymousToken(token) {
590
+ assert(this.anonymousPublicKeys.length, ErrorTypes_default.ANONYMOUS_PUBLIC_KEY_NOT_FOUND);
591
+ const payload = await this.verifySignedJWT(token, this.anonymousPublicKeys, this.maxTokenAge);
592
+ assert(payload.type === "Anon", ErrorTypes_default.INVALID_AUTH_TYPE);
593
+ return payload;
594
+ }
595
+ async createUserToken(id, additionalData) {
596
+ assert(this.userPrivateKeys.length, ErrorTypes_default.USER_PRIVATE_KEY_NOT_FOUND);
597
+ assert(Utils_default.isUUID(id), ErrorTypes_default.INVALID_UUID);
598
+ const payload = {
599
+ id,
600
+ type: "User",
601
+ ...additionalData
602
+ };
603
+ return await this.createSignedJWT(payload, this.userPrivateKeys[this.userPrivateKeys.length - 1], this.maxTokenAge);
604
+ }
605
+ async verifyUserToken(token) {
606
+ assert(this.userPublicKeys.length, ErrorTypes_default.USER_PUBLIC_KEY_NOT_FOUND);
607
+ const payload = await this.verifySignedJWT(token, this.userPublicKeys, this.maxTokenAge);
608
+ assert(payload.type === "User", ErrorTypes_default.INVALID_AUTH_TYPE);
609
+ return payload;
470
610
  }
471
- AuthMiddleware() {
611
+ async createSystemToken(id, additionalData) {
612
+ assert(this.userPrivateKeys.length, ErrorTypes_default.USER_PRIVATE_KEY_NOT_FOUND);
613
+ assert(Utils_default.isUUID(id), ErrorTypes_default.INVALID_UUID);
614
+ const payload = {
615
+ id,
616
+ type: "System",
617
+ ...additionalData
618
+ };
619
+ return await this.createSignedJWT(payload, this.systemPrivateKeys[this.systemPrivateKeys.length - 1], "5 min");
620
+ }
621
+ async verifySystemToken(token) {
622
+ assert(this.systemPublicKeys.length, ErrorTypes_default.USER_PUBLIC_KEY_NOT_FOUND);
623
+ const payload = await this.verifySignedJWT(token, this.systemPublicKeys, "5 min");
624
+ assert(payload.type === "System", ErrorTypes_default.INVALID_AUTH_TYPE);
625
+ return payload;
626
+ }
627
+ async createAdminToken(id, additionalData) {
628
+ assert(this.adminPrivateKeys.length, ErrorTypes_default.ADMIN_PRIVATE_KEY_NOT_FOUND);
629
+ assert(Utils_default.isUUID(id), ErrorTypes_default.INVALID_UUID);
630
+ const payload = {
631
+ id,
632
+ type: "Admin",
633
+ ...additionalData
634
+ };
635
+ return await this.createSignedJWT(payload, this.adminPrivateKeys[this.adminPrivateKeys.length - 1], this.maxTokenAge);
636
+ }
637
+ async verifyAdminToken(token) {
638
+ assert(this.adminPublicKeys.length, ErrorTypes_default.ADMIN_PUBLIC_KEY_NOT_FOUND);
639
+ const payload = await this.verifySignedJWT(token, this.adminPublicKeys, this.maxTokenAge);
640
+ assert(payload.type === "Admin", ErrorTypes_default.INVALID_AUTH_TYPE);
641
+ return payload;
642
+ }
643
+ AuthMiddleware({ allowAnonymous, allowSystem, allowUser } = DefaultAuthMiddlewareConfig) {
472
644
  return async (req, res, next) => {
473
645
  try {
474
- const token = req.get("Authorization")?.split(" ")?.[1];
646
+ const [authType, token] = req.get("Authorization")?.split(" ");
475
647
  if (!token) {
476
648
  throw new Error(ErrorTypes_default.INVALID_TOKEN);
477
649
  }
478
- const payload = await this.verifyToken(token);
479
- res.locals.auth = payload;
650
+ let payload;
651
+ switch (authType) {
652
+ case "Anon":
653
+ if (!allowAnonymous) {
654
+ throw response_default.generateError(403, ErrorTypes_default.ANONYMOUS_SESSION_NOT_ALLOWED);
655
+ }
656
+ payload = await this.verifyAnonymousToken(token);
657
+ break;
658
+ case "User":
659
+ if (!allowUser) {
660
+ throw response_default.generateError(403, ErrorTypes_default.USER_SESSION_NOT_ALLOWED);
661
+ }
662
+ payload = await this.verifyUserToken(token);
663
+ break;
664
+ case "System":
665
+ if (!allowSystem) {
666
+ throw response_default.generateError(403, ErrorTypes_default.SYSTEM_SESSION_NOT_ALLOWED);
667
+ }
668
+ payload = await this.verifySystemToken(token);
669
+ break;
670
+ case "Admin":
671
+ payload = await this.verifyAdminToken(token);
672
+ break;
673
+ default:
674
+ throw response_default.generateError(403, ErrorTypes_default.INVALID_AUTH_TYPE);
675
+ }
676
+ res.locals.auth = {
677
+ authType,
678
+ token,
679
+ ...payload
680
+ };
480
681
  next();
481
682
  } catch (error) {
482
683
  Logger_default.logError("AuthMiddleware", util2.inspect(error));
483
- response_default.handleException("AuthMiddleware", response_default.generateError(401, ErrorTypes_default.TOKEN_EXPIRED), res);
684
+ response_default.handleException("AuthMiddleware", response_default.generateError(401, error.error ? error.error : ErrorTypes_default.TOKEN_EXPIRED, true), res);
484
685
  }
485
686
  };
486
687
  }
@@ -537,6 +738,7 @@ export {
537
738
  Dynamodb_default as DynamoDB,
538
739
  fetch_default as Fetch,
539
740
  Logger_default as Logger,
540
- response_default as ResponseUtility,
541
- Schema_default as Schema
741
+ Utils_default as ResponseUtility,
742
+ Schema_default as Schema,
743
+ Utils_default as Utils
542
744
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "b23-lib",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "This repo hold common classes, type and util functiona",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -19,7 +19,7 @@
19
19
  "dependencies": {
20
20
  "@aws-sdk/client-dynamodb": "^3.620.0",
21
21
  "@aws-sdk/util-dynamodb": "^3.620.0",
22
- "jose": "^5.9.6",
22
+ "jose": "^5.6.3",
23
23
  "util": "^0.12.5"
24
24
  },
25
25
  "devDependencies": {