@naturalcycles/nodejs-lib 15.116.2 → 15.116.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -27,8 +27,23 @@ export interface JWTService2Cfg<T extends AnyObject = AnyObject> {
27
27
  * Recommended: ES256
28
28
  * Keys (private/public) should be generated using proper settings
29
29
  * that fit the used Algorithm.
30
+ *
31
+ * Used for Sign, and (unless `verifyAlgorithms` is set) it's also
32
+ * the only algorithm accepted on Verify.
30
33
  */
31
34
  algorithm: JWTAlgorithm;
35
+ /**
36
+ * JWS algorithms accepted on Verify. Defaults to `[algorithm]`.
37
+ *
38
+ * Only needed when one verifier must accept keys of different types
39
+ * (e.g a per-kid key set mixing EC and RSA keys). Keep the list as narrow as possible.
40
+ *
41
+ * The token's `alg` header chooses among these, but only within what the
42
+ * verification key can serve: a token/key algorithm mismatch fails with JWT_INVALID.
43
+ * (All JWTAlgorithms are asymmetric, so the classic algorithm-confusion attacks
44
+ * don't apply regardless.)
45
+ */
46
+ verifyAlgorithms?: JWTAlgorithm[];
32
47
  /**
33
48
  * If provided - payloads are validated against it on every Sign/Verify/Decode.
34
49
  * Can be overridden per-call via `opt.schema`.
@@ -75,7 +75,7 @@ export class JWTService2 {
75
75
  let data;
76
76
  try {
77
77
  const { payload } = await jwtVerify(token, key, {
78
- algorithms: [this.cfg.algorithm],
78
+ algorithms: this.cfg.verifyAlgorithms || [this.cfg.algorithm],
79
79
  ...joseOpt,
80
80
  currentDate: now === undefined ? undefined : new Date(now * 1000),
81
81
  });
@@ -135,6 +135,11 @@ export class JWTService2 {
135
135
  else if (err instanceof errors.JOSEError) {
136
136
  code = 'JWT_INVALID';
137
137
  }
138
+ else if (this.cfg.verifyAlgorithms && err instanceof TypeError) {
139
+ // With multiple verifyAlgorithms, a token/key algorithm mismatch is reachable
140
+ // by untrusted input, and jose reports it as TypeError - treat it as an invalid token
141
+ code = 'JWT_INVALID';
142
+ }
138
143
  else {
139
144
  return err;
140
145
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@naturalcycles/nodejs-lib",
3
3
  "type": "module",
4
- "version": "15.116.2",
4
+ "version": "15.116.3",
5
5
  "dependencies": {
6
6
  "@naturalcycles/js-lib": "^15",
7
7
  "@standard-schema/spec": "^1",
@@ -49,9 +49,25 @@ export interface JWTService2Cfg<T extends AnyObject = AnyObject> {
49
49
  * Recommended: ES256
50
50
  * Keys (private/public) should be generated using proper settings
51
51
  * that fit the used Algorithm.
52
+ *
53
+ * Used for Sign, and (unless `verifyAlgorithms` is set) it's also
54
+ * the only algorithm accepted on Verify.
52
55
  */
53
56
  algorithm: JWTAlgorithm
54
57
 
58
+ /**
59
+ * JWS algorithms accepted on Verify. Defaults to `[algorithm]`.
60
+ *
61
+ * Only needed when one verifier must accept keys of different types
62
+ * (e.g a per-kid key set mixing EC and RSA keys). Keep the list as narrow as possible.
63
+ *
64
+ * The token's `alg` header chooses among these, but only within what the
65
+ * verification key can serve: a token/key algorithm mismatch fails with JWT_INVALID.
66
+ * (All JWTAlgorithms are asymmetric, so the classic algorithm-confusion attacks
67
+ * don't apply regardless.)
68
+ */
69
+ verifyAlgorithms?: JWTAlgorithm[]
70
+
55
71
  /**
56
72
  * If provided - payloads are validated against it on every Sign/Verify/Decode.
57
73
  * Can be overridden per-call via `opt.schema`.
@@ -243,7 +259,7 @@ export class JWTService2<T extends AnyObject = AnyObject> {
243
259
 
244
260
  try {
245
261
  const { payload } = await jwtVerify(token, key, {
246
- algorithms: [this.cfg.algorithm],
262
+ algorithms: this.cfg.verifyAlgorithms || [this.cfg.algorithm],
247
263
  ...joseOpt,
248
264
  currentDate: now === undefined ? undefined : new Date(now * 1000),
249
265
  })
@@ -305,6 +321,10 @@ export class JWTService2<T extends AnyObject = AnyObject> {
305
321
  code = 'JWT_NOT_YET_VALID'
306
322
  } else if (err instanceof errors.JOSEError) {
307
323
  code = 'JWT_INVALID'
324
+ } else if (this.cfg.verifyAlgorithms && err instanceof TypeError) {
325
+ // With multiple verifyAlgorithms, a token/key algorithm mismatch is reachable
326
+ // by untrusted input, and jose reports it as TypeError - treat it as an invalid token
327
+ code = 'JWT_INVALID'
308
328
  } else {
309
329
  return err as Error
310
330
  }