@rapidrest/core 1.15.0 → 2.0.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.
Files changed (53) hide show
  1. package/dist/lib/AlertUtils.js +53 -37
  2. package/dist/lib/AlertUtils.js.map +1 -1
  3. package/dist/lib/ApiError.js +8 -1
  4. package/dist/lib/ApiError.js.map +1 -1
  5. package/dist/lib/CacheUtils.js +23 -0
  6. package/dist/lib/CacheUtils.js.map +1 -0
  7. package/dist/lib/ClassLoader.js +48 -55
  8. package/dist/lib/ClassLoader.js.map +1 -1
  9. package/dist/lib/FileUtils.js +120 -45
  10. package/dist/lib/FileUtils.js.map +1 -1
  11. package/dist/lib/JWTUtils.js +200 -165
  12. package/dist/lib/JWTUtils.js.map +1 -1
  13. package/dist/lib/Logger.js +32 -3
  14. package/dist/lib/Logger.js.map +1 -1
  15. package/dist/lib/MemoryStore.js +8 -6
  16. package/dist/lib/MemoryStore.js.map +1 -1
  17. package/dist/lib/MessagingUtils.js +69 -40
  18. package/dist/lib/MessagingUtils.js.map +1 -1
  19. package/dist/lib/NotificationsUtils.js +26 -8
  20. package/dist/lib/NotificationsUtils.js.map +1 -1
  21. package/dist/lib/OASUtils.js +55 -24
  22. package/dist/lib/OASUtils.js.map +1 -1
  23. package/dist/lib/ObjectFactory.js +144 -67
  24. package/dist/lib/ObjectFactory.js.map +1 -1
  25. package/dist/lib/ObjectUtils.js +18 -5
  26. package/dist/lib/ObjectUtils.js.map +1 -1
  27. package/dist/lib/StringUtils.js +55 -28
  28. package/dist/lib/StringUtils.js.map +1 -1
  29. package/dist/lib/TelemetryUtils.js +30 -4
  30. package/dist/lib/TelemetryUtils.js.map +1 -1
  31. package/dist/lib/UserUtils.js +4 -5
  32. package/dist/lib/UserUtils.js.map +1 -1
  33. package/dist/lib/ValidationUtils.js +10 -3
  34. package/dist/lib/ValidationUtils.js.map +1 -1
  35. package/dist/lib/index.js +1 -0
  36. package/dist/lib/index.js.map +1 -1
  37. package/dist/lib/threads/ThreadPool.js +131 -55
  38. package/dist/lib/threads/ThreadPool.js.map +1 -1
  39. package/dist/types/AlertUtils.d.ts +4 -0
  40. package/dist/types/CacheUtils.d.ts +14 -0
  41. package/dist/types/ClassLoader.d.ts +10 -0
  42. package/dist/types/FileUtils.d.ts +20 -7
  43. package/dist/types/JWTUtils.d.ts +69 -24
  44. package/dist/types/MessagingUtils.d.ts +5 -1
  45. package/dist/types/NotificationsUtils.d.ts +22 -0
  46. package/dist/types/ObjectFactory.d.ts +25 -1
  47. package/dist/types/ObjectUtils.d.ts +4 -0
  48. package/dist/types/StringUtils.d.ts +8 -0
  49. package/dist/types/TelemetryUtils.d.ts +10 -0
  50. package/dist/types/ValidationUtils.d.ts +1 -1
  51. package/dist/types/index.d.ts +1 -0
  52. package/dist/types/threads/ThreadPool.d.ts +30 -1
  53. package/package.json +1 -1
@@ -19,50 +19,83 @@ export var JWTUtilsCompressionMethods;
19
19
  */
20
20
  export class JWTUtils {
21
21
  /**
22
- * Throws if `config.secret` looks like an asymmetric (RSA/EC) key but `config.options.algorithms` was not
23
- * explicitly restricted. Signing/verifying with an asymmetric key while leaving `algorithms` unset opens the
24
- * door to algorithm-confusion attacks (e.g. an attacker forging an HS256 token using the public key as the
25
- * HMAC secret). HMAC secrets (plain strings/buffers that aren't PEM-encoded) are unaffected.
22
+ * Returns `true` if `secret` is a form that is only ever usable as a genuine HMAC secret - a plain
23
+ * string/Buffer that isn't PEM-encoded, or a `KeyObject` of type `"secret"`. Anything else (a PEM
24
+ * string/Buffer, an asymmetric `KeyObject`, a `{ key, passphrase }` wrapper, a `GetPublicKeyOrSecret`
25
+ * callback, a JWK-shaped object, etc.) is *not* considered safe, since it may resolve to a non-secret
26
+ * (public) value that an attacker could use to forge an HS256/384/512 token.
27
+ */
28
+ static isKnownSafeHmacSecret(secret) {
29
+ const pemPattern = /-----BEGIN [A-Z ]*(PRIVATE|PUBLIC) KEY-----/;
30
+ if (typeof secret === "string") {
31
+ return !pemPattern.test(secret);
32
+ }
33
+ // `fs.readFileSync()` - the idiomatic way to load a key file - returns a Buffer, not a string, so both
34
+ // representations must be checked here.
35
+ if (Buffer.isBuffer(secret)) {
36
+ return !pemPattern.test(secret.toString("utf8"));
37
+ }
38
+ if (secret instanceof KeyObject) {
39
+ return secret.type === "secret";
40
+ }
41
+ return false;
42
+ }
43
+ /**
44
+ * Throws unless `config.secret` is a known-safe plain HMAC secret. Any other secret shape is treated
45
+ * conservatively as potentially asymmetric (fail closed, rather than only matching a fixed allowlist of
46
+ * asymmetric shapes seen so far) and requires `config.options.algorithms` to be explicitly set to a list
47
+ * that does not itself include an HMAC algorithm. Without this, signing/verifying with e.g. an RSA key
48
+ * while leaving `algorithms` unset - or restricting it to `["RS256", "HS256"]` - opens the door to
49
+ * algorithm-confusion attacks: an attacker holding only the public half of the key pair can forge a token
50
+ * by signing it with HS256 using that public value as the HMAC secret.
26
51
  *
27
52
  * @param config The JWT configuration to validate.
28
53
  */
29
54
  static assertSafeAlgorithm(config) {
30
55
  const secret = config.secret;
31
- const pemPattern = /-----BEGIN [A-Z ]*(PRIVATE|PUBLIC) KEY-----/;
32
- // `fs.readFileSync()` - the idiomatic way to load a key file - returns a Buffer, not a string, so both
33
- // representations must be checked or the guard below is trivially bypassed.
34
- const isPemLike = (typeof secret === "string" && pemPattern.test(secret)) ||
35
- (Buffer.isBuffer(secret) && pemPattern.test(secret.toString("utf8")));
36
- // `jwt.Secret` also allows a `KeyObject` (e.g. from `crypto.createPrivateKey()`) or a
37
- // `{ key, passphrase }` encrypted-PEM wrapper, neither of which are strings/Buffers - both must be
38
- // detected too or this guard is trivially bypassed by using either form.
39
- const isAsymmetricKeyObject = secret instanceof KeyObject && secret.type !== "secret";
40
- const isPassphraseWrappedKey = !!secret && typeof secret === "object" && !Buffer.isBuffer(secret) && "key" in secret && "passphrase" in secret;
41
- const looksAsymmetric = isPemLike || isAsymmetricKeyObject || isPassphraseWrappedKey;
42
- if (looksAsymmetric && (!config.options?.algorithms || config.options.algorithms.length === 0)) {
56
+ if (JWTUtils.isKnownSafeHmacSecret(secret)) {
57
+ return;
58
+ }
59
+ const algorithms = config.options?.algorithms;
60
+ if (!algorithms || algorithms.length === 0) {
43
61
  throw new Error("config.secret appears to be an asymmetric key. config.options.algorithms must be explicitly set " +
44
62
  "(e.g. ['RS256']) to prevent algorithm-confusion attacks.");
45
63
  }
64
+ if (algorithms.some((alg) => JWTUtils.HMAC_ALGORITHMS.has(alg))) {
65
+ throw new Error("config.options.algorithms includes an HMAC algorithm (HS256/HS384/HS512) alongside a " +
66
+ "non-HMAC secret. This would allow an attacker holding the public half of the key to forge " +
67
+ "tokens via algorithm confusion. Remove HMAC algorithms from config.options.algorithms.");
68
+ }
46
69
  }
47
70
  /**
48
- * Generates a new JWT token for the given config and user object. The user object must be a valid RapidREST
49
- * user.
50
- *
51
- * @param config The JWT configuration to use when generating the token.
52
- * @param user The user to encode into the token's payload.
71
+ * Returns the key length, in bytes, required by `algorithm` (e.g. 32 for `aes-256-cbc`, 24 for
72
+ * `aes-192-cbc`), so the scrypt-derived key `deriveKey`/`deriveKeySync` produce always matches whatever
73
+ * cipher `passwordOptions.algorithm` actually names, instead of a length hard-coded for one specific
74
+ * algorithm. Throws a clear error for an algorithm Node's `crypto` module doesn't recognize, rather than
75
+ * letting `createCipheriv`/`createDecipheriv` fail later with an opaque "Invalid key length".
53
76
  */
54
- static deriveKey(password, salt) {
55
- return new Promise((resolve, reject) => crypto.scrypt(password, salt, 24, (err, key) => (err ? reject(err) : resolve(key))));
77
+ static resolveKeyLength(algorithm) {
78
+ const info = crypto.getCipherInfo(algorithm);
79
+ if (!info?.keyLength) {
80
+ throw new Error(`Unknown or unsupported cipher algorithm: "${algorithm}".`);
81
+ }
82
+ return info.keyLength;
56
83
  }
57
84
  /**
58
- * Generates a new JWT token for the given config and user object. The user object must be a valid RapidREST
59
- * user.
60
- *
61
- * @param config The JWT configuration to use when generating the token.
62
- * @param user The user to encode into the token's payload.
85
+ * Derives a symmetric encryption key from `password`/`salt` for use with `algorithm`.
86
+ */
87
+ static deriveKey(password, salt, algorithm) {
88
+ const keyLength = JWTUtils.resolveKeyLength(algorithm);
89
+ return new Promise((resolve, reject) => crypto.scrypt(password, salt, keyLength, (err, key) => (err ? reject(err) : resolve(key))));
90
+ }
91
+ /**
92
+ * Synchronous counterpart to `deriveKey()`. **Blocks the event loop** for the duration of the scrypt
93
+ * derivation (deliberately CPU-expensive, typically tens of milliseconds) - `createTokenSync`/
94
+ * `decodeTokenSync` should therefore be avoided on a request-handling path when password-based payload
95
+ * encryption is configured; prefer `createToken`/`decodeToken` there.
63
96
  */
64
- static deriveKeySync(password, salt) {
65
- return crypto.scryptSync(password, salt, 24);
97
+ static deriveKeySync(password, salt, algorithm) {
98
+ return crypto.scryptSync(password, salt, JWTUtils.resolveKeyLength(algorithm));
66
99
  }
67
100
  /**
68
101
  * Encrypts `plaintext` for `publicKey` using hybrid encryption: `plaintext` is encrypted with a fresh
@@ -84,14 +117,19 @@ export class JWTUtils {
84
117
  return [wrappedKey.toString("base64"), iv.toString("base64"), authTag.toString("base64"), ciphertext].join(".");
85
118
  }
86
119
  /**
87
- * Returns `true` if `algorithm` is an AEAD cipher (GCM/CCM/OCB/ChaCha20-Poly1305), which produces an
88
- * authentication tag that must be captured on encryption and supplied back on decryption via
89
- * `getAuthTag()`/`setAuthTag()`.
90
- *
91
- * @param algorithm The cipher algorithm name (e.g. `aes-256-gcm`).
120
+ * Returns the base64-encoded authentication tag for `cipher` if it's an AEAD cipher, otherwise `""`. Rather
121
+ * than pattern-matching the algorithm name (which only recognizes a fixed list of known AEAD naming
122
+ * conventions), this asks the cipher itself via `getAuthTag()`, which throws for any non-AEAD cipher - so
123
+ * any AEAD cipher/alias supported by the current Node/OpenSSL build is handled correctly, including ones
124
+ * not known when this was last updated.
92
125
  */
93
- static isAEADCipher(algorithm) {
94
- return /-(gcm|ccm|ocb)$/i.test(algorithm) || /chacha20-poly1305/i.test(algorithm);
126
+ static getAuthTagIfAEAD(cipher) {
127
+ try {
128
+ return cipher.getAuthTag().toString("base64");
129
+ }
130
+ catch {
131
+ return "";
132
+ }
95
133
  }
96
134
  /**
97
135
  * Decrypts data produced by `hybridEncrypt`.
@@ -100,7 +138,14 @@ export class JWTUtils {
100
138
  * @param encoded The encrypted data, as produced by `hybridEncrypt`.
101
139
  */
102
140
  static hybridDecrypt(privateKey, encoded) {
103
- const [wrappedKeyB64, ivB64, authTagB64, ciphertext] = encoded.split(".");
141
+ const parts = encoded.split(".");
142
+ // Mirrors the length check `finishPasswordDecryption`'s caller performs for the password-based format:
143
+ // without it, a malformed `profile` (e.g. from an outdated/different format) throws an untyped
144
+ // `TypeError` out of `Buffer.from(undefined, ...)` below instead of a clear, identifiable error.
145
+ if (parts.length !== 4) {
146
+ throw new Error("Encrypted profile uses an unrecognized or outdated format and cannot be decoded.");
147
+ }
148
+ const [wrappedKeyB64, ivB64, authTagB64, ciphertext] = parts;
104
149
  const aesKey = crypto.privateDecrypt(privateKey, Buffer.from(wrappedKeyB64, "base64"));
105
150
  const iv = Buffer.from(ivB64, "base64");
106
151
  const authTag = Buffer.from(authTagB64, "base64");
@@ -110,18 +155,23 @@ export class JWTUtils {
110
155
  decrypted += decipher.final("utf8");
111
156
  return decrypted;
112
157
  }
113
- static async createToken(config, user, data) {
114
- // Validate the required config options
158
+ /**
159
+ * Builds the signable payload shared by `createToken`/`createTokenSync`: validates `config`/`user`, spreads
160
+ * `data`, compresses the profile if requested, and - for public-key encryption only, which has no async
161
+ * dependency - encrypts it. Password-based encryption is left for the caller to finish via
162
+ * `finishPasswordEncryption()`, since deriving the key is the one step that differs between the sync and
163
+ * async entry points.
164
+ */
165
+ static preparePayload(config, user, data) {
115
166
  if (!config.secret) {
116
167
  throw new Error("Invalid configuration provided.");
117
168
  }
118
- // Validate the user object
119
169
  if (!user || !user.uid) {
120
170
  throw new Error("Invalid or null user object provided.");
121
171
  }
122
172
  // `data` is spread before `profile` so that a `profile` key present in caller-supplied `data` can never
123
173
  // silently override the authoritative, server-derived user profile before signing.
124
- let payload = { ...data, profile: JSON.stringify(user) };
174
+ const payload = { ...data, profile: JSON.stringify(user) };
125
175
  // Compress the profile if desired. Done *before* encryption so encryption (and, for RSA, its fixed
126
176
  // plaintext-size limit) operates on the smaller compressed representation rather than the raw JSON.
127
177
  if (config.payload && config.payload.compress) {
@@ -131,101 +181,77 @@ export class JWTUtils {
131
181
  payload.compression = "zlib";
132
182
  }
133
183
  }
134
- // Encrypt the profile if desired
184
+ let passwordOptions;
135
185
  if (config.payload && config.payload.encrypt) {
136
186
  const payloadOptions = config.payload;
137
187
  if (payloadOptions.public_key) {
138
188
  const keyOptions = payloadOptions;
139
189
  payload.profile = JWTUtils.hybridEncrypt(keyOptions.public_key, payload.profile);
190
+ payload.encryption = true;
140
191
  }
141
192
  else {
142
- const pwOtions = payloadOptions;
143
- const iv = Buffer.from(pwOtions.iv);
144
- const salt = crypto.randomBytes(16);
145
- const key = await JWTUtils.deriveKey(pwOtions.password, salt);
146
- const cipher = crypto.createCipheriv(pwOtions.algorithm, key, iv);
147
- let encrypted = cipher.update(payload.profile, "utf8", "base64");
148
- encrypted += cipher.final("base64");
149
- // AEAD ciphers (e.g. aes-256-gcm) require the auth tag to be captured here and verified on
150
- // decrypt via setAuthTag(), otherwise decodeToken() throws "Unsupported state or unable to
151
- // authenticate data" on every token.
152
- const authTag = JWTUtils.isAEADCipher(pwOtions.algorithm)
153
- ? cipher.getAuthTag().toString("base64")
154
- : "";
155
- payload.profile = salt.toString("base64") + ":" + authTag + ":" + encrypted;
193
+ passwordOptions = payloadOptions;
156
194
  }
157
- payload.encryption = true;
195
+ }
196
+ return { payload, passwordOptions };
197
+ }
198
+ /** Finishes password-based payload encryption once `key` has been derived (sync or async). */
199
+ static finishPasswordEncryption(payload, passwordOptions, key, salt) {
200
+ const iv = Buffer.from(passwordOptions.iv);
201
+ const cipher = crypto.createCipheriv(passwordOptions.algorithm, key, iv);
202
+ let encrypted = cipher.update(payload.profile, "utf8", "base64");
203
+ encrypted += cipher.final("base64");
204
+ // AEAD ciphers (e.g. aes-256-gcm) require the auth tag to be captured here and verified on decrypt via
205
+ // setAuthTag(), otherwise decoding throws "Unsupported state or unable to authenticate data" on every
206
+ // token. `final()` must be called before `getAuthTag()` - the tag isn't available until encryption
207
+ // has finished.
208
+ const authTag = JWTUtils.getAuthTagIfAEAD(cipher);
209
+ payload.profile = salt.toString("base64") + ":" + authTag + ":" + encrypted;
210
+ payload.encryption = true;
211
+ }
212
+ static async createToken(config, user, data) {
213
+ const { payload, passwordOptions } = JWTUtils.preparePayload(config, user, data);
214
+ if (passwordOptions) {
215
+ const salt = crypto.randomBytes(16);
216
+ const key = await JWTUtils.deriveKey(passwordOptions.password, salt, passwordOptions.algorithm);
217
+ JWTUtils.finishPasswordEncryption(payload, passwordOptions, key, salt);
158
218
  }
159
219
  JWTUtils.assertSafeAlgorithm(config);
160
220
  return jwt.sign(payload, config.secret, config.options);
161
221
  }
222
+ /**
223
+ * Synchronous counterpart to `createToken()`. **Blocks the event loop** while deriving the encryption key
224
+ * when password-based payload encryption is configured (see `deriveKeySync`) - prefer `createToken()` on a
225
+ * request-handling path in that case.
226
+ */
162
227
  static createTokenSync(config, user, data) {
163
- // Validate the required config options
164
- if (!config.secret) {
165
- throw new Error("Invalid configuration provided.");
166
- }
167
- // Validate the user object
168
- if (!user || !user.uid) {
169
- throw new Error("Invalid or null user object provided.");
170
- }
171
- // `data` is spread before `profile` so that a `profile` key present in caller-supplied `data` can never
172
- // silently override the authoritative, server-derived user profile before signing.
173
- let payload = { ...data, profile: JSON.stringify(user) };
174
- // Compress the profile if desired. Done *before* encryption so encryption (and, for RSA, its fixed
175
- // plaintext-size limit) operates on the smaller compressed representation rather than the raw JSON.
176
- if (config.payload && config.payload.compress) {
177
- if (config.payload.compress === JWTUtilsCompressionMethods.ZLIB) {
178
- const buf = Buffer.from(payload.profile, "utf-8");
179
- payload.profile = zlib.gzipSync(buf).toString("base64");
180
- payload.compression = "zlib";
181
- }
182
- }
183
- // Encrypt the profile if desired
184
- if (config.payload && config.payload.encrypt) {
185
- const payloadOptions = config.payload;
186
- if (payloadOptions.public_key) {
187
- const keyOptions = payloadOptions;
188
- payload.profile = JWTUtils.hybridEncrypt(keyOptions.public_key, payload.profile);
189
- }
190
- else {
191
- const pwOtions = payloadOptions;
192
- const iv = Buffer.from(pwOtions.iv);
193
- const salt = crypto.randomBytes(16);
194
- const key = JWTUtils.deriveKeySync(pwOtions.password, salt);
195
- const cipher = crypto.createCipheriv(pwOtions.algorithm, key, iv);
196
- let encrypted = cipher.update(payload.profile, "utf8", "base64");
197
- encrypted += cipher.final("base64");
198
- // AEAD ciphers (e.g. aes-256-gcm) require the auth tag to be captured here and verified on
199
- // decrypt via setAuthTag(), otherwise decodeTokenSync() throws "Unsupported state or unable to
200
- // authenticate data" on every token.
201
- const authTag = JWTUtils.isAEADCipher(pwOtions.algorithm)
202
- ? cipher.getAuthTag().toString("base64")
203
- : "";
204
- payload.profile = salt.toString("base64") + ":" + authTag + ":" + encrypted;
205
- }
206
- payload.encryption = true;
228
+ const { payload, passwordOptions } = JWTUtils.preparePayload(config, user, data);
229
+ if (passwordOptions) {
230
+ const salt = crypto.randomBytes(16);
231
+ const key = JWTUtils.deriveKeySync(passwordOptions.password, salt, passwordOptions.algorithm);
232
+ JWTUtils.finishPasswordEncryption(payload, passwordOptions, key, salt);
207
233
  }
208
234
  JWTUtils.assertSafeAlgorithm(config);
209
235
  return jwt.sign(payload, config.secret, config.options);
210
236
  }
211
237
  /**
212
- * Decodes the given JWT authentication token using the provided configuration. If the token is not valid an
213
- * error is thrown with the reason. Returns the encoded user object payload upon success.
214
- *
215
- * @param config The JWT configuration to use when validating the token.
216
- * @param token The JWT token to validate.
217
- * @returns The data encoded in the token's payload.
238
+ * Verifies `token` and prepares its payload for `decodeToken`/`decodeTokenSync`: validates the signature/
239
+ * shape, and - for private-key decryption only, which has no async dependency - decrypts it in place.
240
+ * Password-based decryption is left for the caller to finish via `finishPasswordDecryption()`, since
241
+ * deriving the key is the one step that differs between the sync and async entry points.
218
242
  */
219
- static async decodeToken(config, token) {
243
+ static preDecode(config, token) {
220
244
  JWTUtils.assertSafeAlgorithm(config);
221
- // Decode the token
222
- let payload = jwt.verify(token, config.secret, config.options);
223
- // Validate the payload
245
+ const payload = jwt.verify(token, config.secret, config.options);
224
246
  if (!payload || !payload.profile) {
225
247
  throw new Error("Token is invalid or missing data.");
226
248
  }
249
+ let passwordOptions;
250
+ let salt;
251
+ let authTagB64;
252
+ let encryptedProfile;
227
253
  // Decrypt the payload if desired. Must happen before decompression since compression is applied *before*
228
- // encryption when the token is created (see createToken), so decryption must be undone first.
254
+ // encryption when the token is created, so decryption must be undone first.
229
255
  if (payload.encryption && config.payload && config.payload.encrypt) {
230
256
  const payloadOptions = config.payload;
231
257
  if (payloadOptions.private_key) {
@@ -233,26 +259,46 @@ export class JWTUtils {
233
259
  payload.profile = JWTUtils.hybridDecrypt(keyOptions.private_key, payload.profile);
234
260
  }
235
261
  else {
236
- const pwOtions = payloadOptions;
237
- const iv = Buffer.from(pwOtions.iv);
238
- const [saltB64, authTagB64, profile] = payload.profile.split(":");
239
- const salt = Buffer.from(saltB64, "base64");
240
- const key = await JWTUtils.deriveKey(pwOtions.password, salt);
241
- const decipher = crypto.createDecipheriv(pwOtions.algorithm, key, iv);
242
- if (authTagB64) {
243
- decipher.setAuthTag(Buffer.from(authTagB64, "base64"));
262
+ passwordOptions = payloadOptions;
263
+ const parts = payload.profile.split(":");
264
+ // The current format is `<salt>:<authTag>:<ciphertext>` (3 parts). A 2-part `<salt>:<ciphertext>`
265
+ // payload is the pre-AEAD-auth-tag format from before this method required an auth tag; without
266
+ // this check, `encryptedProfile` would silently come back `undefined` and decryption would be
267
+ // skipped, surfacing as an opaque JSON.parse SyntaxError in finalizePayload() instead of a clear
268
+ // error identifying the actual problem.
269
+ if (parts.length !== 3) {
270
+ throw new Error("Token payload uses an unrecognized or outdated encrypted format and cannot be decoded.");
244
271
  }
245
- let decrypted = decipher.update(profile, "base64", "utf8");
246
- decrypted += decipher.final("utf8");
247
- payload.profile = decrypted;
272
+ const [saltB64, tagB64, profile] = parts;
273
+ salt = Buffer.from(saltB64, "base64");
274
+ authTagB64 = tagB64;
275
+ encryptedProfile = profile;
248
276
  }
249
277
  }
250
- // Decompress the payload if desired
278
+ return { payload, passwordOptions, salt, authTagB64, encryptedProfile };
279
+ }
280
+ /** Finishes password-based payload decryption once `key` has been derived (sync or async). */
281
+ static finishPasswordDecryption(payload, passwordOptions, key, encryptedProfile, authTagB64) {
282
+ const iv = Buffer.from(passwordOptions.iv);
283
+ const decipher = crypto.createDecipheriv(passwordOptions.algorithm, key, iv);
284
+ if (authTagB64) {
285
+ decipher.setAuthTag(Buffer.from(authTagB64, "base64"));
286
+ }
287
+ let decrypted = decipher.update(encryptedProfile, "base64", "utf8");
288
+ decrypted += decipher.final("utf8");
289
+ payload.profile = decrypted;
290
+ }
291
+ /** Decompresses (if applicable) and parses the final payload profile shared by both decode entry points. */
292
+ static finalizePayload(payload) {
251
293
  if (payload.compression === JWTUtilsCompressionMethods.ZLIB) {
252
294
  const buf = Buffer.from(payload.profile, "base64");
253
- payload.profile = zlib.gunzipSync(buf).toString("utf-8");
295
+ // Cap decompressed size against a decompression bomb (a small compressed payload expanding to consume
296
+ // excessive memory). Requires a validly-signed token, but costs nothing to bound given every other
297
+ // cache/store in this codebase is similarly size-limited.
298
+ payload.profile = zlib
299
+ .gunzipSync(buf, { maxOutputLength: JWTUtils.MAX_DECOMPRESSED_PROFILE_BYTES })
300
+ .toString("utf-8");
254
301
  }
255
- // Make sure the profile is an parsed
256
302
  payload.profile = JSON.parse(payload.profile);
257
303
  return payload;
258
304
  }
@@ -264,46 +310,35 @@ export class JWTUtils {
264
310
  * @param token The JWT token to validate.
265
311
  * @returns The data encoded in the token's payload.
266
312
  */
267
- static decodeTokenSync(config, token) {
268
- JWTUtils.assertSafeAlgorithm(config);
269
- // Decode the token
270
- let payload = jwt.verify(token, config.secret, config.options);
271
- // Validate the payload
272
- if (!payload || !payload.profile) {
273
- throw new Error("Token is invalid or missing data.");
274
- }
275
- // Decrypt the payload if desired. Must happen before decompression since compression is applied *before*
276
- // encryption when the token is created (see createTokenSync), so decryption must be undone first.
277
- if (payload.encryption && config.payload && config.payload.encrypt) {
278
- const payloadOptions = config.payload;
279
- if (payloadOptions.private_key) {
280
- const keyOptions = payloadOptions;
281
- payload.profile = JWTUtils.hybridDecrypt(keyOptions.private_key, payload.profile);
282
- }
283
- else {
284
- const pwOtions = payloadOptions;
285
- const iv = Buffer.from(pwOtions.iv);
286
- const [saltB64, authTagB64, profile] = payload.profile.split(":");
287
- const salt = Buffer.from(saltB64, "base64");
288
- const key = JWTUtils.deriveKeySync(pwOtions.password, salt);
289
- const decipher = crypto.createDecipheriv(pwOtions.algorithm, key, iv);
290
- if (authTagB64) {
291
- decipher.setAuthTag(Buffer.from(authTagB64, "base64"));
292
- }
293
- let decrypted = decipher.update(profile, "base64", "utf8");
294
- decrypted += decipher.final("utf8");
295
- payload.profile = decrypted;
296
- }
313
+ static async decodeToken(config, token) {
314
+ const { payload, passwordOptions, salt, authTagB64, encryptedProfile } = JWTUtils.preDecode(config, token);
315
+ if (passwordOptions && salt && encryptedProfile !== undefined) {
316
+ const key = await JWTUtils.deriveKey(passwordOptions.password, salt, passwordOptions.algorithm);
317
+ JWTUtils.finishPasswordDecryption(payload, passwordOptions, key, encryptedProfile, authTagB64);
297
318
  }
298
- // Decompress the payload if desired
299
- if (payload.compression === JWTUtilsCompressionMethods.ZLIB) {
300
- const buf = Buffer.from(payload.profile, "base64");
301
- payload.profile = zlib.gunzipSync(buf).toString("utf-8");
319
+ return JWTUtils.finalizePayload(payload);
320
+ }
321
+ /**
322
+ * Synchronous counterpart to `decodeToken()`. **Blocks the event loop** while deriving the decryption key
323
+ * when password-based payload encryption is configured (see `deriveKeySync`) - prefer `decodeToken()` on a
324
+ * request-handling path in that case.
325
+ *
326
+ * @param config The JWT configuration to use when validating the token.
327
+ * @param token The JWT token to validate.
328
+ * @returns The data encoded in the token's payload.
329
+ */
330
+ static decodeTokenSync(config, token) {
331
+ const { payload, passwordOptions, salt, authTagB64, encryptedProfile } = JWTUtils.preDecode(config, token);
332
+ if (passwordOptions && salt && encryptedProfile !== undefined) {
333
+ const key = JWTUtils.deriveKeySync(passwordOptions.password, salt, passwordOptions.algorithm);
334
+ JWTUtils.finishPasswordDecryption(payload, passwordOptions, key, encryptedProfile, authTagB64);
302
335
  }
303
- // Make sure the profile is an parsed
304
- payload.profile = JSON.parse(payload.profile);
305
- return payload;
336
+ return JWTUtils.finalizePayload(payload);
306
337
  }
307
338
  }
308
- JWTUtils._parsedKeyCache = new Map();
339
+ /** HMAC algorithm names that must never be permitted alongside a non-HMAC secret (see `assertSafeAlgorithm`). */
340
+ JWTUtils.HMAC_ALGORITHMS = new Set(["HS256", "HS384", "HS512"]);
341
+ /** Maximum size, in bytes, a compressed profile is allowed to decompress to (see `finalizePayload`). Guards
342
+ * against a decompression bomb - a small compressed payload expanding to consume excessive memory. */
343
+ JWTUtils.MAX_DECOMPRESSED_PROFILE_BYTES = 10 * 1024 * 1024;
309
344
  //# sourceMappingURL=JWTUtils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"JWTUtils.js","sourceRoot":"","sources":["../../src/JWTUtils.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,kDAAkD;AAClD,+EAA+E;AAC/E,OAAO,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAC3C,OAAO,GAAG,MAAM,cAAc,CAAC;AAC/B,OAAO,IAAI,MAAM,MAAM,CAAC;AAmDxB;;GAEG;AACH,MAAM,CAAN,IAAY,0BAGX;AAHD,WAAY,0BAA0B;IAClC,wCAAwC;IACxC,2CAAa,CAAA;AACjB,CAAC,EAHW,0BAA0B,KAA1B,0BAA0B,QAGrC;AAkFD;;;;GAIG;AACH,MAAM,OAAO,QAAQ;IAGjB;;;;;;;OAOG;IACK,MAAM,CAAC,mBAAmB,CAAC,MAAsB;QACrD,MAAM,MAAM,GAAQ,MAAM,CAAC,MAAM,CAAC;QAClC,MAAM,UAAU,GAAG,6CAA6C,CAAC;QACjE,uGAAuG;QACvG,4EAA4E;QAC5E,MAAM,SAAS,GACX,CAAC,OAAO,MAAM,KAAK,QAAQ,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACvD,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC1E,sFAAsF;QACtF,mGAAmG;QACnG,yEAAyE;QACzE,MAAM,qBAAqB,GAAG,MAAM,YAAY,SAAS,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC;QACtF,MAAM,sBAAsB,GACxB,CAAC,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,KAAK,IAAI,MAAM,IAAI,YAAY,IAAI,MAAM,CAAC;QACpH,MAAM,eAAe,GAAG,SAAS,IAAI,qBAAqB,IAAI,sBAAsB,CAAC;QACrF,IAAI,eAAe,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,UAAU,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC;YAC7F,MAAM,IAAI,KAAK,CACX,kGAAkG;gBAC9F,0DAA0D,CACjE,CAAC;QACN,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACK,MAAM,CAAC,SAAS,CAAC,QAAgB,EAAE,IAAY;QACnD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CACnC,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CACtF,CAAC;IACN,CAAC;IAED;;;;;;OAMG;IACK,MAAM,CAAC,aAAa,CAAC,QAAgB,EAAE,IAAY;QACvD,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;IACjD,CAAC;IAED;;;;;;;;OAQG;IACK,MAAM,CAAC,aAAa,CAAC,SAAiB,EAAE,SAAiB;QAC7D,MAAM,MAAM,GAAW,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QAC9C,MAAM,EAAE,GAAW,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QAC1C,MAAM,MAAM,GAAG,MAAM,CAAC,cAAc,CAAC,aAAa,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;QAChE,IAAI,UAAU,GAAW,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;QACpE,UAAU,IAAI,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACrC,MAAM,OAAO,GAAW,MAAM,CAAC,UAAU,EAAE,CAAC;QAC5C,MAAM,UAAU,GAAW,MAAM,CAAC,aAAa,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QACnE,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC,CAAC,IAAI,CACtG,GAAG,CACN,CAAC;IACN,CAAC;IAED;;;;;;OAMG;IACK,MAAM,CAAC,YAAY,CAAC,SAAiB;QACzC,OAAO,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,oBAAoB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACtF,CAAC;IAED;;;;;OAKG;IACK,MAAM,CAAC,aAAa,CAAC,UAAkB,EAAE,OAAe;QAC5D,MAAM,CAAC,aAAa,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC1E,MAAM,MAAM,GAAW,MAAM,CAAC,cAAc,CAAC,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC,CAAC;QAC/F,MAAM,EAAE,GAAW,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QAChD,MAAM,OAAO,GAAW,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAC1D,MAAM,QAAQ,GAAG,MAAM,CAAC,gBAAgB,CAAC,aAAa,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;QACpE,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAC7B,IAAI,SAAS,GAAW,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;QACtE,SAAS,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACpC,OAAO,SAAS,CAAC;IACrB,CAAC;IAEM,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,MAAsB,EAAE,IAAa,EAAE,IAAU;QAC7E,uCAAuC;QACvC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;QACvD,CAAC;QAED,2BAA2B;QAC3B,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAC7D,CAAC;QAED,wGAAwG;QACxG,mFAAmF;QACnF,IAAI,OAAO,GAAQ,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;QAE9D,mGAAmG;QACnG,oGAAoG;QACpG,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YAC5C,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,KAAK,0BAA0B,CAAC,IAAI,EAAE,CAAC;gBAC9D,MAAM,GAAG,GAAW,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBAC1D,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;gBACxD,OAAO,CAAC,WAAW,GAAG,MAAM,CAAC;YACjC,CAAC;QACL,CAAC;QAED,iCAAiC;QACjC,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YAC3C,MAAM,cAAc,GAAQ,MAAM,CAAC,OAAO,CAAC;YAC3C,IAAI,cAAc,CAAC,UAAU,EAAE,CAAC;gBAC5B,MAAM,UAAU,GAA8B,cAA2C,CAAC;gBAC1F,OAAO,CAAC,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,UAAU,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;YACrF,CAAC;iBAAM,CAAC;gBACJ,MAAM,QAAQ,GAAmC,cAAgD,CAAC;gBAClG,MAAM,EAAE,GAAW,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;gBAC5C,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;gBACpC,MAAM,GAAG,GAAW,MAAM,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;gBACtE,MAAM,MAAM,GAAG,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;gBAElE,IAAI,SAAS,GAAW,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;gBACzE,SAAS,IAAI,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;gBACpC,2FAA2F;gBAC3F,2FAA2F;gBAC3F,qCAAqC;gBACrC,MAAM,OAAO,GAAW,QAAQ,CAAC,YAAY,CAAC,QAAQ,CAAC,SAAS,CAAC;oBAC7D,CAAC,CAAE,MAA2B,CAAC,UAAU,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC;oBAC9D,CAAC,CAAC,EAAE,CAAC;gBACT,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,GAAG,GAAG,OAAO,GAAG,GAAG,GAAG,SAAS,CAAC;YAChF,CAAC;YACD,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;QAC9B,CAAC;QAED,QAAQ,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC;QACrC,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,OAAsC,CAAC,CAAC;IAC3F,CAAC;IAEM,MAAM,CAAC,eAAe,CAAC,MAAsB,EAAE,IAAa,EAAE,IAAU;QAC3E,uCAAuC;QACvC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;QACvD,CAAC;QAED,2BAA2B;QAC3B,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAC7D,CAAC;QAED,wGAAwG;QACxG,mFAAmF;QACnF,IAAI,OAAO,GAAQ,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;QAE9D,mGAAmG;QACnG,oGAAoG;QACpG,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YAC5C,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,KAAK,0BAA0B,CAAC,IAAI,EAAE,CAAC;gBAC9D,MAAM,GAAG,GAAW,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBAC1D,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;gBACxD,OAAO,CAAC,WAAW,GAAG,MAAM,CAAC;YACjC,CAAC;QACL,CAAC;QAED,iCAAiC;QACjC,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YAC3C,MAAM,cAAc,GAAQ,MAAM,CAAC,OAAO,CAAC;YAC3C,IAAI,cAAc,CAAC,UAAU,EAAE,CAAC;gBAC5B,MAAM,UAAU,GAA8B,cAA2C,CAAC;gBAC1F,OAAO,CAAC,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,UAAU,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;YACrF,CAAC;iBAAM,CAAC;gBACJ,MAAM,QAAQ,GAAmC,cAAgD,CAAC;gBAClG,MAAM,EAAE,GAAW,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;gBAC5C,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;gBACpC,MAAM,GAAG,GAAW,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;gBACpE,MAAM,MAAM,GAAG,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;gBAElE,IAAI,SAAS,GAAW,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;gBACzE,SAAS,IAAI,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;gBACpC,2FAA2F;gBAC3F,+FAA+F;gBAC/F,qCAAqC;gBACrC,MAAM,OAAO,GAAW,QAAQ,CAAC,YAAY,CAAC,QAAQ,CAAC,SAAS,CAAC;oBAC7D,CAAC,CAAE,MAA2B,CAAC,UAAU,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC;oBAC9D,CAAC,CAAC,EAAE,CAAC;gBACT,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,GAAG,GAAG,OAAO,GAAG,GAAG,GAAG,SAAS,CAAC;YAChF,CAAC;YACD,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;QAC9B,CAAC;QAED,QAAQ,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC;QACrC,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,OAAsC,CAAC,CAAC;IAC3F,CAAC;IAED;;;;;;;OAOG;IACI,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,MAAsB,EAAE,KAAa;QACjE,QAAQ,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC;QACrC,mBAAmB;QACnB,IAAI,OAAO,GAAQ,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QAEpE,uBAAuB;QACvB,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;QACzD,CAAC;QAED,yGAAyG;QACzG,8FAA8F;QAC9F,IAAI,OAAO,CAAC,UAAU,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YACjE,MAAM,cAAc,GAAQ,MAAM,CAAC,OAAO,CAAC;YAC3C,IAAI,cAAc,CAAC,WAAW,EAAE,CAAC;gBAC7B,MAAM,UAAU,GAA8B,cAA2C,CAAC;gBAC1F,OAAO,CAAC,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,WAAW,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;YACtF,CAAC;iBAAM,CAAC;gBACJ,MAAM,QAAQ,GAAmC,cAAgD,CAAC;gBAClG,MAAM,EAAE,GAAW,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;gBAC5C,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAClE,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;gBAC5C,MAAM,GAAG,GAAW,MAAM,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;gBACtE,MAAM,QAAQ,GAAG,MAAM,CAAC,gBAAgB,CAAC,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;gBACtE,IAAI,UAAU,EAAE,CAAC;oBACZ,QAA+B,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC;gBACnF,CAAC;gBAED,IAAI,SAAS,GAAW,QAAQ,CAAC,MAAM,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;gBACnE,SAAS,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;gBACpC,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC;YAChC,CAAC;QACL,CAAC;QAED,oCAAoC;QACpC,IAAI,OAAO,CAAC,WAAW,KAAK,0BAA0B,CAAC,IAAI,EAAE,CAAC;YAC1D,MAAM,GAAG,GAAW,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,OAAiB,EAAE,QAAQ,CAAC,CAAC;YACrE,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC7D,CAAC;QAED,qCAAqC;QACrC,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAE9C,OAAO,OAAO,CAAC;IACnB,CAAC;IAED;;;;;;;OAOG;IACI,MAAM,CAAC,eAAe,CAAC,MAAsB,EAAE,KAAa;QAC/D,QAAQ,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC;QACrC,mBAAmB;QACnB,IAAI,OAAO,GAAQ,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QAEpE,uBAAuB;QACvB,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;QACzD,CAAC;QAED,yGAAyG;QACzG,kGAAkG;QAClG,IAAI,OAAO,CAAC,UAAU,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YACjE,MAAM,cAAc,GAAQ,MAAM,CAAC,OAAO,CAAC;YAC3C,IAAI,cAAc,CAAC,WAAW,EAAE,CAAC;gBAC7B,MAAM,UAAU,GAA8B,cAA2C,CAAC;gBAC1F,OAAO,CAAC,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,WAAW,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;YACtF,CAAC;iBAAM,CAAC;gBACJ,MAAM,QAAQ,GAAmC,cAAgD,CAAC;gBAClG,MAAM,EAAE,GAAW,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;gBAC5C,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAClE,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;gBAC5C,MAAM,GAAG,GAAW,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;gBACpE,MAAM,QAAQ,GAAG,MAAM,CAAC,gBAAgB,CAAC,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;gBACtE,IAAI,UAAU,EAAE,CAAC;oBACZ,QAA+B,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC;gBACnF,CAAC;gBAED,IAAI,SAAS,GAAW,QAAQ,CAAC,MAAM,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;gBACnE,SAAS,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;gBACpC,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC;YAChC,CAAC;QACL,CAAC;QAED,oCAAoC;QACpC,IAAI,OAAO,CAAC,WAAW,KAAK,0BAA0B,CAAC,IAAI,EAAE,CAAC;YAC1D,MAAM,GAAG,GAAW,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,OAAiB,EAAE,QAAQ,CAAC,CAAC;YACrE,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC7D,CAAC;QAED,qCAAqC;QACrC,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAE9C,OAAO,OAAO,CAAC;IACnB,CAAC;;AApUc,wBAAe,GAAG,IAAI,GAAG,EAAE,CAAC"}
1
+ {"version":3,"file":"JWTUtils.js","sourceRoot":"","sources":["../../src/JWTUtils.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,7 @@
3
3
  ///////////////////////////////////////////////////////////////////////////////
4
4
  import { fileURLToPath } from "url";
5
5
  import winston from "winston";
6
+ import { CacheUtils } from "./CacheUtils.js";
6
7
  const { format, transports } = winston;
7
8
  const { combine, timestamp, printf } = format;
8
9
  export const FILENAME = fileURLToPath(import.meta.url).replace(/\\/g, "/");
@@ -47,6 +48,11 @@ export const source = format((info) => {
47
48
  }
48
49
  return info;
49
50
  });
51
+ /** Maximum number of distinct `${level}:${file}` logger instances to keep cached. Each `file`-bound entry holds
52
+ * open file descriptors via winston's `File` transport, so an unbounded cache would leak descriptors indefinitely
53
+ * for any caller that varies `file` per call (e.g. a per-request or per-session name) instead of reusing a fixed
54
+ * small set of names. */
55
+ const MAX_CACHED_LOGGERS = 100;
50
56
  const _loggerCache = new Map();
51
57
  /**
52
58
  * Creates (or retrieves a cached) logger with the specified level and file name to output logs to.
@@ -57,18 +63,41 @@ const _loggerCache = new Map();
57
63
  export const Logger = function (level = "debug", file = undefined) {
58
64
  const cacheKey = `${level}:${file ?? ""}`;
59
65
  if (_loggerCache.has(cacheKey)) {
60
- return _loggerCache.get(cacheKey);
66
+ const cached = _loggerCache.get(cacheKey);
67
+ // Move to the end of the Map's iteration order so a frequently-reused logger isn't evicted (and its
68
+ // file transport closed, possibly mid-write) ahead of one that's actually gone idle - Map.set() on an
69
+ // already-present key doesn't reorder it by itself.
70
+ _loggerCache.delete(cacheKey);
71
+ _loggerCache.set(cacheKey, cached);
72
+ return cached;
61
73
  }
62
- const transport = [new transports.Console()];
74
+ // `colorize()` wraps `info.level` in ANSI escape codes unconditionally - it doesn't detect whether the
75
+ // destination is a TTY. It must stay Console-only rather than living in the logger-level `format` below:
76
+ // winston applies the logger-level format to every transport that doesn't supply its own override -
77
+ // including the File transports, and any transport a caller adds later via `logger.add()` - so baking
78
+ // colorize() into it would corrupt on-disk logs and any other attached transport with escape sequences that
79
+ // break grep/log shippers/aggregators expecting a plain-text level field. The logger-level format is left as
80
+ // the uncolored base precisely so those other transports still inherit sensible plain-text formatting.
81
+ const base = combine(format.splat(), format.simple(), timestamp(), source(), logFormat);
82
+ const transport = [new transports.Console({ format: combine(format.colorize(), base) })];
63
83
  if (file) {
64
84
  transport.push(new winston.transports.File({ filename: file + "error.log", level: "error" }));
65
85
  transport.push(new winston.transports.File({ filename: file + ".log" }));
66
86
  }
67
87
  const logger = winston.createLogger({
68
88
  level,
69
- format: combine(format.splat(), format.simple(), format.colorize(), timestamp(), source(), logFormat),
89
+ format: base,
70
90
  transports: transport,
71
91
  });
92
+ if (_loggerCache.size >= MAX_CACHED_LOGGERS) {
93
+ // Non-null: the size check above guarantees the cache is non-empty, so `.next()` always yields a real key.
94
+ const oldestKey = _loggerCache.keys().next().value;
95
+ const oldest = _loggerCache.get(oldestKey);
96
+ CacheUtils.evictOldest(_loggerCache);
97
+ // Close the evicted logger's transports so its file descriptors are actually released, not just
98
+ // dropped from the cache while still held open by winston.
99
+ oldest?.close?.();
100
+ }
72
101
  _loggerCache.set(cacheKey, logger);
73
102
  return logger;
74
103
  };
@@ -1 +1 @@
1
- {"version":3,"file":"Logger.js","sourceRoot":"","sources":["../../src/Logger.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Logger.js","sourceRoot":"","sources":["../../src/Logger.ts"],"names":[],"mappings":"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"}