hi-secure 1.0.32 → 1.0.33

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.
@@ -1 +1 @@
1
- {"version":3,"file":"JWTAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/JWTAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,cAAc,CAAC;AAK/B,MAAM,WAAW,iBAAiB;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,SAAS,CAAC,EAAE,GAAG,CAAC,SAAS,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,WAAW;IACxB,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAChC;AAED,qBAAa,UAAU;IACnB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAC,CAAkB;IACpC,OAAO,CAAC,SAAS,CAAgB;IACjC,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAC,CAAoB;gBAEzB,OAAO,EAAE,iBAAiB;IAoBtC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW;IA6B3C,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;KAAE;CA4BnE"}
1
+ {"version":3,"file":"JWTAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/JWTAdapter.ts"],"names":[],"mappings":"AA6GA,OAAO,GAAsC,MAAM,cAAc,CAAC;AAOlE,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,SAAS,CAAC,EAAE,GAAG,CAAC,SAAS,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC9B;AAWD,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAC,CAAY;IAC9B,OAAO,CAAC,SAAS,CAAgB;IACjC,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAC,CAAoB;gBAEzB,OAAO,EAAE,iBAAiB;IAoBtC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW;IAmC3C,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;KAAE;CA8BjE"}
@@ -1,13 +1,111 @@
1
1
  "use strict";
2
+ // import jwt from "jsonwebtoken";
3
+ // import { randomUUID } from "crypto";
4
+ // import { AdapterError } from "../core/errors/AdapterError";
5
+ // import { logger } from "../logging";
2
6
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
7
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
8
  };
5
9
  Object.defineProperty(exports, "__esModule", { value: true });
6
10
  exports.JWTAdapter = void 0;
11
+ // export interface JWTAdapterOptions {
12
+ // secret: string;
13
+ // expiresIn?: string | number;
14
+ // algorithm?: jwt.Algorithm;
15
+ // issuer?: string;
16
+ // audience?: string | string[];
17
+ // }
18
+ // export interface SignOptions {
19
+ // expiresIn?: string | number;
20
+ // jti?: string;
21
+ // subject?: string;
22
+ // issuer?: string;
23
+ // audience?: string | string[];
24
+ // }
25
+ // export class JWTAdapter {
26
+ // private secret: string;
27
+ // private expiresIn?: string | number;
28
+ // private algorithm: jwt.Algorithm;
29
+ // private issuer?: string;
30
+ // private audience?: string | string[];
31
+ // constructor(options: JWTAdapterOptions) {
32
+ // if (!options.secret) {
33
+ // throw new AdapterError("JWT secret is required");
34
+ // }
35
+ // if (options.secret.length < 32) {
36
+ // logger.warn("Weak JWT secret detected", {
37
+ // adapter: "jwt",
38
+ // operation: "init",
39
+ // secretLength: options.secret.length
40
+ // });
41
+ // }
42
+ // this.secret = options.secret;
43
+ // this.expiresIn = options.expiresIn;
44
+ // this.algorithm = options.algorithm || "HS256";
45
+ // this.issuer = options.issuer;
46
+ // this.audience = options.audience;
47
+ // }
48
+ // sign(payload: object, options?: SignOptions) {
49
+ // try {
50
+ // const jwtOptions: jwt.SignOptions = {
51
+ // algorithm: this.algorithm,
52
+ // issuer: options?.issuer || this.issuer,
53
+ // audience: options?.audience || this.audience,
54
+ // jwtid: options?.jti || randomUUID(),
55
+ // subject: options?.subject
56
+ // };
57
+ // if (options?.expiresIn !== undefined) {
58
+ // jwtOptions.expiresIn = options.expiresIn as any;
59
+ // } else if (this.expiresIn !== undefined) {
60
+ // jwtOptions.expiresIn = this.expiresIn as any;
61
+ // }
62
+ // return jwt.sign(payload, this.secret, jwtOptions);
63
+ // } catch (err: any) {
64
+ // logger.error("JWT signing failed", {
65
+ // adapter: "jwt",
66
+ // operation: "sign",
67
+ // reason: err?.message
68
+ // });
69
+ // throw new AdapterError("JWT sign failed");
70
+ // }
71
+ // }
72
+ // verify(token: string, options?: { audience?: string | string[] }) {
73
+ // try {
74
+ // const verifyOptions: jwt.VerifyOptions = {
75
+ // algorithms: [this.algorithm],
76
+ // issuer: this.issuer,
77
+ // audience: (options?.audience || this.audience) as string
78
+ // };
79
+ // return jwt.verify(token, this.secret, verifyOptions);
80
+ // } catch (err: any) {
81
+ // logger.error("JWT verification failed", {
82
+ // adapter: "jwt",
83
+ // operation: "verify",
84
+ // reason: err?.message
85
+ // });
86
+ // if (err?.name === "TokenExpiredError") {
87
+ // throw new AdapterError("JWT token has expired");
88
+ // }
89
+ // if (err?.name === "JsonWebTokenError") {
90
+ // throw new AdapterError("Invalid JWT token");
91
+ // }
92
+ // throw new AdapterError("JWT verification failed");
93
+ // }
94
+ // }
95
+ // }
7
96
  const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
8
97
  const crypto_1 = require("crypto");
9
98
  const AdapterError_1 = require("../core/errors/AdapterError");
10
99
  const logging_1 = require("../logging");
100
+ function normalizeAudience(aud) {
101
+ if (!aud)
102
+ return undefined;
103
+ if (typeof aud === "string")
104
+ return aud;
105
+ if (aud.length > 0)
106
+ return aud;
107
+ return undefined;
108
+ }
11
109
  class JWTAdapter {
12
110
  constructor(options) {
13
111
  if (!options.secret) {
@@ -16,30 +114,34 @@ class JWTAdapter {
16
114
  if (options.secret.length < 32) {
17
115
  logging_1.logger.warn("Weak JWT secret detected", {
18
116
  adapter: "jwt",
19
- operation: "init",
20
117
  secretLength: options.secret.length
21
118
  });
22
119
  }
23
120
  this.secret = options.secret;
24
- this.expiresIn = options.expiresIn;
25
- this.algorithm = options.algorithm || "HS256";
121
+ this.algorithm = options.algorithm ?? "HS256";
26
122
  this.issuer = options.issuer;
27
123
  this.audience = options.audience;
124
+ this.expiresIn = options.expiresIn;
28
125
  }
126
+ // ================= SIGN =================
29
127
  sign(payload, options) {
30
128
  try {
31
129
  const jwtOptions = {
32
130
  algorithm: this.algorithm,
33
- issuer: options?.issuer || this.issuer,
34
- audience: options?.audience || this.audience,
35
- jwtid: options?.jti || (0, crypto_1.randomUUID)(),
131
+ jwtid: options?.jti ?? (0, crypto_1.randomUUID)(),
36
132
  subject: options?.subject
37
133
  };
38
- if (options?.expiresIn !== undefined) {
39
- jwtOptions.expiresIn = options.expiresIn;
40
- }
41
- else if (this.expiresIn !== undefined) {
42
- jwtOptions.expiresIn = this.expiresIn;
134
+ const issuer = options?.issuer ?? this.issuer;
135
+ if (issuer)
136
+ jwtOptions.issuer = issuer;
137
+ const audience = normalizeAudience(options?.audience ?? this.audience);
138
+ if (audience)
139
+ jwtOptions.audience = audience;
140
+ const expires = options?.expiresIn !== undefined
141
+ ? options.expiresIn
142
+ : this.expiresIn;
143
+ if (expires !== undefined) {
144
+ jwtOptions.expiresIn = expires;
43
145
  }
44
146
  return jsonwebtoken_1.default.sign(payload, this.secret, jwtOptions);
45
147
  }
@@ -52,13 +154,17 @@ class JWTAdapter {
52
154
  throw new AdapterError_1.AdapterError("JWT sign failed");
53
155
  }
54
156
  }
157
+ // ================= VERIFY =================
55
158
  verify(token, options) {
56
159
  try {
57
160
  const verifyOptions = {
58
- algorithms: [this.algorithm],
59
- issuer: this.issuer,
60
- audience: (options?.audience || this.audience)
161
+ algorithms: [this.algorithm]
61
162
  };
163
+ if (this.issuer)
164
+ verifyOptions.issuer = this.issuer;
165
+ const audience = normalizeAudience(options?.audience ?? this.audience);
166
+ if (audience)
167
+ verifyOptions.audience = audience;
62
168
  return jsonwebtoken_1.default.verify(token, this.secret, verifyOptions);
63
169
  }
64
170
  catch (err) {
@@ -1 +1 @@
1
- {"version":3,"file":"JWTAdapter.js","sourceRoot":"","sources":["../../src/adapters/JWTAdapter.ts"],"names":[],"mappings":"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","sourcesContent":["import jwt from \"jsonwebtoken\";\r\nimport { randomUUID } from \"crypto\";\r\nimport { AdapterError } from \"../core/errors/AdapterError\";\r\nimport { logger } from \"../logging\";\r\n\r\nexport interface JWTAdapterOptions {\r\n secret: string;\r\n expiresIn?: string | number;\r\n algorithm?: jwt.Algorithm;\r\n issuer?: string;\r\n audience?: string | string[];\r\n}\r\n\r\nexport interface SignOptions {\r\n expiresIn?: string | number;\r\n jti?: string;\r\n subject?: string;\r\n issuer?: string;\r\n audience?: string | string[];\r\n}\r\n\r\nexport class JWTAdapter {\r\n private secret: string;\r\n private expiresIn?: string | number;\r\n private algorithm: jwt.Algorithm;\r\n private issuer?: string;\r\n private audience?: string | string[];\r\n\r\n constructor(options: JWTAdapterOptions) {\r\n if (!options.secret) {\r\n throw new AdapterError(\"JWT secret is required\");\r\n }\r\n\r\n if (options.secret.length < 32) {\r\n logger.warn(\"Weak JWT secret detected\", {\r\n adapter: \"jwt\",\r\n operation: \"init\",\r\n secretLength: options.secret.length\r\n });\r\n }\r\n\r\n this.secret = options.secret;\r\n this.expiresIn = options.expiresIn;\r\n this.algorithm = options.algorithm || \"HS256\";\r\n this.issuer = options.issuer;\r\n this.audience = options.audience;\r\n }\r\n\r\n sign(payload: object, options?: SignOptions) {\r\n try {\r\n const jwtOptions: jwt.SignOptions = {\r\n algorithm: this.algorithm,\r\n issuer: options?.issuer || this.issuer,\r\n audience: options?.audience || this.audience,\r\n jwtid: options?.jti || randomUUID(),\r\n subject: options?.subject\r\n };\r\n\r\n if (options?.expiresIn !== undefined) {\r\n jwtOptions.expiresIn = options.expiresIn as any;\r\n } else if (this.expiresIn !== undefined) {\r\n jwtOptions.expiresIn = this.expiresIn as any;\r\n }\r\n\r\n return jwt.sign(payload, this.secret, jwtOptions);\r\n\r\n } catch (err: any) {\r\n logger.error(\"JWT signing failed\", {\r\n adapter: \"jwt\",\r\n operation: \"sign\",\r\n reason: err?.message\r\n });\r\n\r\n throw new AdapterError(\"JWT sign failed\");\r\n }\r\n }\r\n\r\n verify(token: string, options?: { audience?: string | string[] }) {\r\n try {\r\n const verifyOptions: jwt.VerifyOptions = {\r\n algorithms: [this.algorithm],\r\n issuer: this.issuer,\r\n audience: (options?.audience || this.audience) as string\r\n };\r\n\r\n return jwt.verify(token, this.secret, verifyOptions);\r\n\r\n } catch (err: any) {\r\n logger.error(\"JWT verification failed\", {\r\n adapter: \"jwt\",\r\n operation: \"verify\",\r\n reason: err?.message\r\n });\r\n\r\n if (err?.name === \"TokenExpiredError\") {\r\n throw new AdapterError(\"JWT token has expired\");\r\n }\r\n\r\n if (err?.name === \"JsonWebTokenError\") {\r\n throw new AdapterError(\"Invalid JWT token\");\r\n }\r\n\r\n throw new AdapterError(\"JWT verification failed\");\r\n }\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"JWTAdapter.js","sourceRoot":"","sources":["../../src/adapters/JWTAdapter.ts"],"names":[],"mappings":"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","sourcesContent":["// import jwt from \"jsonwebtoken\";\r\n// import { randomUUID } from \"crypto\";\r\n// import { AdapterError } from \"../core/errors/AdapterError\";\r\n// import { logger } from \"../logging\";\r\n\r\n// export interface JWTAdapterOptions {\r\n// secret: string;\r\n// expiresIn?: string | number;\r\n// algorithm?: jwt.Algorithm;\r\n// issuer?: string;\r\n// audience?: string | string[];\r\n// }\r\n\r\n// export interface SignOptions {\r\n// expiresIn?: string | number;\r\n// jti?: string;\r\n// subject?: string;\r\n// issuer?: string;\r\n// audience?: string | string[];\r\n// }\r\n\r\n// export class JWTAdapter {\r\n// private secret: string;\r\n// private expiresIn?: string | number;\r\n// private algorithm: jwt.Algorithm;\r\n// private issuer?: string;\r\n// private audience?: string | string[];\r\n\r\n// constructor(options: JWTAdapterOptions) {\r\n// if (!options.secret) {\r\n// throw new AdapterError(\"JWT secret is required\");\r\n// }\r\n\r\n// if (options.secret.length < 32) {\r\n// logger.warn(\"Weak JWT secret detected\", {\r\n// adapter: \"jwt\",\r\n// operation: \"init\",\r\n// secretLength: options.secret.length\r\n// });\r\n// }\r\n\r\n// this.secret = options.secret;\r\n// this.expiresIn = options.expiresIn;\r\n// this.algorithm = options.algorithm || \"HS256\";\r\n// this.issuer = options.issuer;\r\n// this.audience = options.audience;\r\n// }\r\n\r\n// sign(payload: object, options?: SignOptions) {\r\n// try {\r\n// const jwtOptions: jwt.SignOptions = {\r\n// algorithm: this.algorithm,\r\n// issuer: options?.issuer || this.issuer,\r\n// audience: options?.audience || this.audience,\r\n// jwtid: options?.jti || randomUUID(),\r\n// subject: options?.subject\r\n// };\r\n\r\n// if (options?.expiresIn !== undefined) {\r\n// jwtOptions.expiresIn = options.expiresIn as any;\r\n// } else if (this.expiresIn !== undefined) {\r\n// jwtOptions.expiresIn = this.expiresIn as any;\r\n// }\r\n\r\n// return jwt.sign(payload, this.secret, jwtOptions);\r\n\r\n// } catch (err: any) {\r\n// logger.error(\"JWT signing failed\", {\r\n// adapter: \"jwt\",\r\n// operation: \"sign\",\r\n// reason: err?.message\r\n// });\r\n\r\n// throw new AdapterError(\"JWT sign failed\");\r\n// }\r\n// }\r\n\r\n// verify(token: string, options?: { audience?: string | string[] }) {\r\n// try {\r\n// const verifyOptions: jwt.VerifyOptions = {\r\n// algorithms: [this.algorithm],\r\n// issuer: this.issuer,\r\n// audience: (options?.audience || this.audience) as string\r\n// };\r\n\r\n// return jwt.verify(token, this.secret, verifyOptions);\r\n\r\n// } catch (err: any) {\r\n// logger.error(\"JWT verification failed\", {\r\n// adapter: \"jwt\",\r\n// operation: \"verify\",\r\n// reason: err?.message\r\n// });\r\n\r\n// if (err?.name === \"TokenExpiredError\") {\r\n// throw new AdapterError(\"JWT token has expired\");\r\n// }\r\n\r\n// if (err?.name === \"JsonWebTokenError\") {\r\n// throw new AdapterError(\"Invalid JWT token\");\r\n// }\r\n\r\n// throw new AdapterError(\"JWT verification failed\");\r\n// }\r\n// }\r\n// }\r\n\r\n\r\n\r\nimport jwt, { SignOptions as JwtSignOptions } from \"jsonwebtoken\";\r\nimport { randomUUID } from \"crypto\";\r\nimport { AdapterError } from \"../core/errors/AdapterError\";\r\nimport { logger } from \"../logging\";\r\n\r\ntype ExpiresIn = JwtSignOptions[\"expiresIn\"]; // ✅ important\r\n\r\nexport interface JWTAdapterOptions {\r\n secret: string;\r\n expiresIn?: string | number;\r\n algorithm?: jwt.Algorithm;\r\n issuer?: string;\r\n audience?: string | string[];\r\n}\r\n\r\nexport interface SignOptions {\r\n expiresIn?: string | number;\r\n jti?: string;\r\n subject?: string;\r\n issuer?: string;\r\n audience?: string | string[];\r\n}\r\n\r\nfunction normalizeAudience(\r\n aud?: string | string[]\r\n): string | [string, ...string[]] | undefined {\r\n if (!aud) return undefined;\r\n if (typeof aud === \"string\") return aud;\r\n if (aud.length > 0) return aud as [string, ...string[]];\r\n return undefined;\r\n}\r\n\r\nexport class JWTAdapter {\r\n private secret: string;\r\n private expiresIn?: ExpiresIn;\r\n private algorithm: jwt.Algorithm;\r\n private issuer?: string;\r\n private audience?: string | string[];\r\n\r\n constructor(options: JWTAdapterOptions) {\r\n if (!options.secret) {\r\n throw new AdapterError(\"JWT secret is required\");\r\n }\r\n\r\n if (options.secret.length < 32) {\r\n logger.warn(\"Weak JWT secret detected\", {\r\n adapter: \"jwt\",\r\n secretLength: options.secret.length\r\n });\r\n }\r\n\r\n this.secret = options.secret;\r\n this.algorithm = options.algorithm ?? \"HS256\";\r\n this.issuer = options.issuer;\r\n this.audience = options.audience;\r\n this.expiresIn = options.expiresIn as ExpiresIn;\r\n }\r\n\r\n // ================= SIGN =================\r\n sign(payload: object, options?: SignOptions) {\r\n try {\r\n const jwtOptions: jwt.SignOptions = {\r\n algorithm: this.algorithm,\r\n jwtid: options?.jti ?? randomUUID(),\r\n subject: options?.subject\r\n };\r\n\r\n const issuer = options?.issuer ?? this.issuer;\r\n if (issuer) jwtOptions.issuer = issuer;\r\n\r\n const audience = normalizeAudience(options?.audience ?? this.audience);\r\n if (audience) jwtOptions.audience = audience;\r\n\r\n const expires =\r\n options?.expiresIn !== undefined\r\n ? (options.expiresIn as ExpiresIn)\r\n : this.expiresIn;\r\n\r\n if (expires !== undefined) {\r\n jwtOptions.expiresIn = expires;\r\n }\r\n\r\n return jwt.sign(payload, this.secret, jwtOptions);\r\n } catch (err: any) {\r\n logger.error(\"JWT signing failed\", {\r\n adapter: \"jwt\",\r\n operation: \"sign\",\r\n reason: err?.message\r\n });\r\n throw new AdapterError(\"JWT sign failed\");\r\n }\r\n }\r\n\r\n // ================= VERIFY =================\r\n verify(token: string, options?: { audience?: string | string[] }) {\r\n try {\r\n const verifyOptions: jwt.VerifyOptions = {\r\n algorithms: [this.algorithm]\r\n };\r\n\r\n if (this.issuer) verifyOptions.issuer = this.issuer;\r\n\r\n const audience = normalizeAudience(options?.audience ?? this.audience);\r\n if (audience) verifyOptions.audience = audience;\r\n\r\n return jwt.verify(token, this.secret, verifyOptions);\r\n } catch (err: any) {\r\n logger.error(\"JWT verification failed\", {\r\n adapter: \"jwt\",\r\n operation: \"verify\",\r\n reason: err?.message\r\n });\r\n\r\n if (err?.name === \"TokenExpiredError\") {\r\n throw new AdapterError(\"JWT token has expired\");\r\n }\r\n\r\n if (err?.name === \"JsonWebTokenError\") {\r\n throw new AdapterError(\"Invalid JWT token\");\r\n }\r\n\r\n throw new AdapterError(\"JWT verification failed\");\r\n }\r\n }\r\n}\r\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hi-secure",
3
- "version": "1.0.32",
3
+ "version": "1.0.33",
4
4
  "description": "Unified security layer for Express.js: authentication, validation, sanitization, rate limiting and CORS",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -1,106 +1,234 @@
1
- import jwt from "jsonwebtoken";
1
+ // import jwt from "jsonwebtoken";
2
+ // import { randomUUID } from "crypto";
3
+ // import { AdapterError } from "../core/errors/AdapterError";
4
+ // import { logger } from "../logging";
5
+
6
+ // export interface JWTAdapterOptions {
7
+ // secret: string;
8
+ // expiresIn?: string | number;
9
+ // algorithm?: jwt.Algorithm;
10
+ // issuer?: string;
11
+ // audience?: string | string[];
12
+ // }
13
+
14
+ // export interface SignOptions {
15
+ // expiresIn?: string | number;
16
+ // jti?: string;
17
+ // subject?: string;
18
+ // issuer?: string;
19
+ // audience?: string | string[];
20
+ // }
21
+
22
+ // export class JWTAdapter {
23
+ // private secret: string;
24
+ // private expiresIn?: string | number;
25
+ // private algorithm: jwt.Algorithm;
26
+ // private issuer?: string;
27
+ // private audience?: string | string[];
28
+
29
+ // constructor(options: JWTAdapterOptions) {
30
+ // if (!options.secret) {
31
+ // throw new AdapterError("JWT secret is required");
32
+ // }
33
+
34
+ // if (options.secret.length < 32) {
35
+ // logger.warn("Weak JWT secret detected", {
36
+ // adapter: "jwt",
37
+ // operation: "init",
38
+ // secretLength: options.secret.length
39
+ // });
40
+ // }
41
+
42
+ // this.secret = options.secret;
43
+ // this.expiresIn = options.expiresIn;
44
+ // this.algorithm = options.algorithm || "HS256";
45
+ // this.issuer = options.issuer;
46
+ // this.audience = options.audience;
47
+ // }
48
+
49
+ // sign(payload: object, options?: SignOptions) {
50
+ // try {
51
+ // const jwtOptions: jwt.SignOptions = {
52
+ // algorithm: this.algorithm,
53
+ // issuer: options?.issuer || this.issuer,
54
+ // audience: options?.audience || this.audience,
55
+ // jwtid: options?.jti || randomUUID(),
56
+ // subject: options?.subject
57
+ // };
58
+
59
+ // if (options?.expiresIn !== undefined) {
60
+ // jwtOptions.expiresIn = options.expiresIn as any;
61
+ // } else if (this.expiresIn !== undefined) {
62
+ // jwtOptions.expiresIn = this.expiresIn as any;
63
+ // }
64
+
65
+ // return jwt.sign(payload, this.secret, jwtOptions);
66
+
67
+ // } catch (err: any) {
68
+ // logger.error("JWT signing failed", {
69
+ // adapter: "jwt",
70
+ // operation: "sign",
71
+ // reason: err?.message
72
+ // });
73
+
74
+ // throw new AdapterError("JWT sign failed");
75
+ // }
76
+ // }
77
+
78
+ // verify(token: string, options?: { audience?: string | string[] }) {
79
+ // try {
80
+ // const verifyOptions: jwt.VerifyOptions = {
81
+ // algorithms: [this.algorithm],
82
+ // issuer: this.issuer,
83
+ // audience: (options?.audience || this.audience) as string
84
+ // };
85
+
86
+ // return jwt.verify(token, this.secret, verifyOptions);
87
+
88
+ // } catch (err: any) {
89
+ // logger.error("JWT verification failed", {
90
+ // adapter: "jwt",
91
+ // operation: "verify",
92
+ // reason: err?.message
93
+ // });
94
+
95
+ // if (err?.name === "TokenExpiredError") {
96
+ // throw new AdapterError("JWT token has expired");
97
+ // }
98
+
99
+ // if (err?.name === "JsonWebTokenError") {
100
+ // throw new AdapterError("Invalid JWT token");
101
+ // }
102
+
103
+ // throw new AdapterError("JWT verification failed");
104
+ // }
105
+ // }
106
+ // }
107
+
108
+
109
+
110
+ import jwt, { SignOptions as JwtSignOptions } from "jsonwebtoken";
2
111
  import { randomUUID } from "crypto";
3
112
  import { AdapterError } from "../core/errors/AdapterError";
4
113
  import { logger } from "../logging";
5
114
 
115
+ type ExpiresIn = JwtSignOptions["expiresIn"]; // ✅ important
116
+
6
117
  export interface JWTAdapterOptions {
7
- secret: string;
8
- expiresIn?: string | number;
9
- algorithm?: jwt.Algorithm;
10
- issuer?: string;
11
- audience?: string | string[];
118
+ secret: string;
119
+ expiresIn?: string | number;
120
+ algorithm?: jwt.Algorithm;
121
+ issuer?: string;
122
+ audience?: string | string[];
12
123
  }
13
124
 
14
125
  export interface SignOptions {
15
- expiresIn?: string | number;
16
- jti?: string;
17
- subject?: string;
18
- issuer?: string;
19
- audience?: string | string[];
126
+ expiresIn?: string | number;
127
+ jti?: string;
128
+ subject?: string;
129
+ issuer?: string;
130
+ audience?: string | string[];
131
+ }
132
+
133
+ function normalizeAudience(
134
+ aud?: string | string[]
135
+ ): string | [string, ...string[]] | undefined {
136
+ if (!aud) return undefined;
137
+ if (typeof aud === "string") return aud;
138
+ if (aud.length > 0) return aud as [string, ...string[]];
139
+ return undefined;
20
140
  }
21
141
 
22
142
  export class JWTAdapter {
23
- private secret: string;
24
- private expiresIn?: string | number;
25
- private algorithm: jwt.Algorithm;
26
- private issuer?: string;
27
- private audience?: string | string[];
28
-
29
- constructor(options: JWTAdapterOptions) {
30
- if (!options.secret) {
31
- throw new AdapterError("JWT secret is required");
32
- }
33
-
34
- if (options.secret.length < 32) {
35
- logger.warn("Weak JWT secret detected", {
36
- adapter: "jwt",
37
- operation: "init",
38
- secretLength: options.secret.length
39
- });
40
- }
41
-
42
- this.secret = options.secret;
43
- this.expiresIn = options.expiresIn;
44
- this.algorithm = options.algorithm || "HS256";
45
- this.issuer = options.issuer;
46
- this.audience = options.audience;
143
+ private secret: string;
144
+ private expiresIn?: ExpiresIn;
145
+ private algorithm: jwt.Algorithm;
146
+ private issuer?: string;
147
+ private audience?: string | string[];
148
+
149
+ constructor(options: JWTAdapterOptions) {
150
+ if (!options.secret) {
151
+ throw new AdapterError("JWT secret is required");
47
152
  }
48
153
 
49
- sign(payload: object, options?: SignOptions) {
50
- try {
51
- const jwtOptions: jwt.SignOptions = {
52
- algorithm: this.algorithm,
53
- issuer: options?.issuer || this.issuer,
54
- audience: options?.audience || this.audience,
55
- jwtid: options?.jti || randomUUID(),
56
- subject: options?.subject
57
- };
58
-
59
- if (options?.expiresIn !== undefined) {
60
- jwtOptions.expiresIn = options.expiresIn as any;
61
- } else if (this.expiresIn !== undefined) {
62
- jwtOptions.expiresIn = this.expiresIn as any;
63
- }
64
-
65
- return jwt.sign(payload, this.secret, jwtOptions);
66
-
67
- } catch (err: any) {
68
- logger.error("JWT signing failed", {
69
- adapter: "jwt",
70
- operation: "sign",
71
- reason: err?.message
72
- });
73
-
74
- throw new AdapterError("JWT sign failed");
75
- }
154
+ if (options.secret.length < 32) {
155
+ logger.warn("Weak JWT secret detected", {
156
+ adapter: "jwt",
157
+ secretLength: options.secret.length
158
+ });
76
159
  }
77
160
 
78
- verify(token: string, options?: { audience?: string | string[] }) {
79
- try {
80
- const verifyOptions: jwt.VerifyOptions = {
81
- algorithms: [this.algorithm],
82
- issuer: this.issuer,
83
- audience: (options?.audience || this.audience) as string
84
- };
85
-
86
- return jwt.verify(token, this.secret, verifyOptions);
87
-
88
- } catch (err: any) {
89
- logger.error("JWT verification failed", {
90
- adapter: "jwt",
91
- operation: "verify",
92
- reason: err?.message
93
- });
94
-
95
- if (err?.name === "TokenExpiredError") {
96
- throw new AdapterError("JWT token has expired");
97
- }
98
-
99
- if (err?.name === "JsonWebTokenError") {
100
- throw new AdapterError("Invalid JWT token");
101
- }
102
-
103
- throw new AdapterError("JWT verification failed");
104
- }
161
+ this.secret = options.secret;
162
+ this.algorithm = options.algorithm ?? "HS256";
163
+ this.issuer = options.issuer;
164
+ this.audience = options.audience;
165
+ this.expiresIn = options.expiresIn as ExpiresIn;
166
+ }
167
+
168
+ // ================= SIGN =================
169
+ sign(payload: object, options?: SignOptions) {
170
+ try {
171
+ const jwtOptions: jwt.SignOptions = {
172
+ algorithm: this.algorithm,
173
+ jwtid: options?.jti ?? randomUUID(),
174
+ subject: options?.subject
175
+ };
176
+
177
+ const issuer = options?.issuer ?? this.issuer;
178
+ if (issuer) jwtOptions.issuer = issuer;
179
+
180
+ const audience = normalizeAudience(options?.audience ?? this.audience);
181
+ if (audience) jwtOptions.audience = audience;
182
+
183
+ const expires =
184
+ options?.expiresIn !== undefined
185
+ ? (options.expiresIn as ExpiresIn)
186
+ : this.expiresIn;
187
+
188
+ if (expires !== undefined) {
189
+ jwtOptions.expiresIn = expires;
190
+ }
191
+
192
+ return jwt.sign(payload, this.secret, jwtOptions);
193
+ } catch (err: any) {
194
+ logger.error("JWT signing failed", {
195
+ adapter: "jwt",
196
+ operation: "sign",
197
+ reason: err?.message
198
+ });
199
+ throw new AdapterError("JWT sign failed");
200
+ }
201
+ }
202
+
203
+ // ================= VERIFY =================
204
+ verify(token: string, options?: { audience?: string | string[] }) {
205
+ try {
206
+ const verifyOptions: jwt.VerifyOptions = {
207
+ algorithms: [this.algorithm]
208
+ };
209
+
210
+ if (this.issuer) verifyOptions.issuer = this.issuer;
211
+
212
+ const audience = normalizeAudience(options?.audience ?? this.audience);
213
+ if (audience) verifyOptions.audience = audience;
214
+
215
+ return jwt.verify(token, this.secret, verifyOptions);
216
+ } catch (err: any) {
217
+ logger.error("JWT verification failed", {
218
+ adapter: "jwt",
219
+ operation: "verify",
220
+ reason: err?.message
221
+ });
222
+
223
+ if (err?.name === "TokenExpiredError") {
224
+ throw new AdapterError("JWT token has expired");
225
+ }
226
+
227
+ if (err?.name === "JsonWebTokenError") {
228
+ throw new AdapterError("Invalid JWT token");
229
+ }
230
+
231
+ throw new AdapterError("JWT verification failed");
105
232
  }
233
+ }
106
234
  }