jose 5.2.3 → 5.3.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.
@@ -99,13 +99,11 @@ export class FlattenedEncrypt {
99
99
  this._unprotectedHeader = { ...this._unprotectedHeader, ...parameters };
100
100
  }
101
101
  }
102
+ else if (!this._protectedHeader) {
103
+ this.setProtectedHeader(parameters);
104
+ }
102
105
  else {
103
- if (!this._protectedHeader) {
104
- this.setProtectedHeader(parameters);
105
- }
106
- else {
107
- this._protectedHeader = { ...this._protectedHeader, ...parameters };
108
- }
106
+ this._protectedHeader = { ...this._protectedHeader, ...parameters };
109
107
  }
110
108
  }
111
109
  }
@@ -14,7 +14,7 @@ function getKtyFromAlg(alg) {
14
14
  throw new JOSENotSupported('Unsupported "alg" value for a JSON Web Key Set');
15
15
  }
16
16
  }
17
- export function isJWKSLike(jwks) {
17
+ function isJWKSLike(jwks) {
18
18
  return (jwks &&
19
19
  typeof jwks === 'object' &&
20
20
  Array.isArray(jwks.keys) &&
@@ -108,5 +108,14 @@ async function importWithAlgCache(cache, jwk, alg) {
108
108
  }
109
109
  export function createLocalJWKSet(jwks) {
110
110
  const set = new LocalJWKSet(jwks);
111
- return async (protectedHeader, token) => set.getKey(protectedHeader, token);
111
+ const localJWKSet = async (protectedHeader, token) => set.getKey(protectedHeader, token);
112
+ Object.defineProperties(localJWKSet, {
113
+ jwks: {
114
+ value: () => clone(set._jwks),
115
+ enumerable: true,
116
+ configurable: false,
117
+ writable: false,
118
+ },
119
+ });
120
+ return localJWKSet;
112
121
  }
@@ -1,6 +1,6 @@
1
1
  import fetchJwks from '../runtime/fetch_jwks.js';
2
- import { JWKSInvalid, JWKSNoMatchingKey } from '../util/errors.js';
3
- import { isJWKSLike, LocalJWKSet } from './local.js';
2
+ import { JWKSNoMatchingKey } from '../util/errors.js';
3
+ import { createLocalJWKSet } from './local.js';
4
4
  function isCloudflareWorkers() {
5
5
  return (typeof WebSocketPair !== 'undefined' ||
6
6
  (typeof navigator !== 'undefined' && navigator.userAgent === 'Cloudflare-Workers') ||
@@ -9,13 +9,11 @@ function isCloudflareWorkers() {
9
9
  let USER_AGENT;
10
10
  if (typeof navigator === 'undefined' || !navigator.userAgent?.startsWith?.('Mozilla/5.0 ')) {
11
11
  const NAME = 'jose';
12
- const VERSION = 'v5.2.3';
12
+ const VERSION = 'v5.3.0';
13
13
  USER_AGENT = `${NAME}/${VERSION}`;
14
14
  }
15
- class RemoteJWKSet extends LocalJWKSet {
15
+ class RemoteJWKSet {
16
16
  constructor(url, options) {
17
- super({ keys: [] });
18
- this._jwks = undefined;
19
17
  if (!(url instanceof URL)) {
20
18
  throw new TypeError('url must be an instance of URL');
21
19
  }
@@ -38,17 +36,17 @@ class RemoteJWKSet extends LocalJWKSet {
38
36
  : false;
39
37
  }
40
38
  async getKey(protectedHeader, token) {
41
- if (!this._jwks || !this.fresh()) {
39
+ if (!this._local || !this.fresh()) {
42
40
  await this.reload();
43
41
  }
44
42
  try {
45
- return await super.getKey(protectedHeader, token);
43
+ return await this._local(protectedHeader, token);
46
44
  }
47
45
  catch (err) {
48
46
  if (err instanceof JWKSNoMatchingKey) {
49
47
  if (this.coolingDown() === false) {
50
48
  await this.reload();
51
- return super.getKey(protectedHeader, token);
49
+ return this._local(protectedHeader, token);
52
50
  }
53
51
  }
54
52
  throw err;
@@ -65,10 +63,7 @@ class RemoteJWKSet extends LocalJWKSet {
65
63
  }
66
64
  this._pendingFetch || (this._pendingFetch = fetchJwks(this._url, this._timeoutDuration, this._options)
67
65
  .then((json) => {
68
- if (!isJWKSLike(json)) {
69
- throw new JWKSInvalid('JSON Web Key Set malformed');
70
- }
71
- this._jwks = { keys: json.keys };
66
+ this._local = createLocalJWKSet(json);
72
67
  this._jwksTimestamp = Date.now();
73
68
  this._pendingFetch = undefined;
74
69
  })
@@ -81,5 +76,35 @@ class RemoteJWKSet extends LocalJWKSet {
81
76
  }
82
77
  export function createRemoteJWKSet(url, options) {
83
78
  const set = new RemoteJWKSet(url, options);
84
- return async (protectedHeader, token) => set.getKey(protectedHeader, token);
79
+ const remoteJWKSet = async (protectedHeader, token) => set.getKey(protectedHeader, token);
80
+ Object.defineProperties(remoteJWKSet, {
81
+ coolingDown: {
82
+ get: () => set.coolingDown(),
83
+ enumerable: true,
84
+ configurable: false,
85
+ },
86
+ fresh: {
87
+ get: () => set.fresh(),
88
+ enumerable: true,
89
+ configurable: false,
90
+ },
91
+ reload: {
92
+ value: () => set.reload(),
93
+ enumerable: true,
94
+ configurable: false,
95
+ writable: false,
96
+ },
97
+ reloading: {
98
+ get: () => !!set._pendingFetch,
99
+ enumerable: true,
100
+ configurable: false,
101
+ },
102
+ jwks: {
103
+ value: () => set._local?.jwks(),
104
+ enumerable: true,
105
+ configurable: false,
106
+ writable: false,
107
+ },
108
+ });
109
+ return remoteJWKSet;
85
110
  }
@@ -110,13 +110,11 @@ class FlattenedEncrypt {
110
110
  this._unprotectedHeader = { ...this._unprotectedHeader, ...parameters };
111
111
  }
112
112
  }
113
+ else if (!this._protectedHeader) {
114
+ this.setProtectedHeader(parameters);
115
+ }
113
116
  else {
114
- if (!this._protectedHeader) {
115
- this.setProtectedHeader(parameters);
116
- }
117
- else {
118
- this._protectedHeader = { ...this._protectedHeader, ...parameters };
119
- }
117
+ this._protectedHeader = { ...this._protectedHeader, ...parameters };
120
118
  }
121
119
  }
122
120
  }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createLocalJWKSet = exports.LocalJWKSet = exports.isJWKSLike = void 0;
3
+ exports.createLocalJWKSet = exports.LocalJWKSet = void 0;
4
4
  const import_js_1 = require("../key/import.js");
5
5
  const errors_js_1 = require("../util/errors.js");
6
6
  const is_object_js_1 = require("../lib/is_object.js");
@@ -23,7 +23,6 @@ function isJWKSLike(jwks) {
23
23
  Array.isArray(jwks.keys) &&
24
24
  jwks.keys.every(isJWKLike));
25
25
  }
26
- exports.isJWKSLike = isJWKSLike;
27
26
  function isJWKLike(key) {
28
27
  return (0, is_object_js_1.default)(key);
29
28
  }
@@ -114,6 +113,15 @@ async function importWithAlgCache(cache, jwk, alg) {
114
113
  }
115
114
  function createLocalJWKSet(jwks) {
116
115
  const set = new LocalJWKSet(jwks);
117
- return async (protectedHeader, token) => set.getKey(protectedHeader, token);
116
+ const localJWKSet = async (protectedHeader, token) => set.getKey(protectedHeader, token);
117
+ Object.defineProperties(localJWKSet, {
118
+ jwks: {
119
+ value: () => clone(set._jwks),
120
+ enumerable: true,
121
+ configurable: false,
122
+ writable: false,
123
+ },
124
+ });
125
+ return localJWKSet;
118
126
  }
119
127
  exports.createLocalJWKSet = createLocalJWKSet;
@@ -12,10 +12,10 @@ function isCloudflareWorkers() {
12
12
  let USER_AGENT;
13
13
  if (typeof navigator === 'undefined' || !navigator.userAgent?.startsWith?.('Mozilla/5.0 ')) {
14
14
  const NAME = 'jose';
15
- const VERSION = 'v5.2.3';
15
+ const VERSION = 'v5.3.0';
16
16
  USER_AGENT = `${NAME}/${VERSION}`;
17
17
  }
18
- class RemoteJWKSet extends local_js_1.LocalJWKSet {
18
+ class RemoteJWKSet {
19
19
  _url;
20
20
  _timeoutDuration;
21
21
  _cooldownDuration;
@@ -23,9 +23,8 @@ class RemoteJWKSet extends local_js_1.LocalJWKSet {
23
23
  _jwksTimestamp;
24
24
  _pendingFetch;
25
25
  _options;
26
+ _local;
26
27
  constructor(url, options) {
27
- super({ keys: [] });
28
- this._jwks = undefined;
29
28
  if (!(url instanceof URL)) {
30
29
  throw new TypeError('url must be an instance of URL');
31
30
  }
@@ -48,17 +47,17 @@ class RemoteJWKSet extends local_js_1.LocalJWKSet {
48
47
  : false;
49
48
  }
50
49
  async getKey(protectedHeader, token) {
51
- if (!this._jwks || !this.fresh()) {
50
+ if (!this._local || !this.fresh()) {
52
51
  await this.reload();
53
52
  }
54
53
  try {
55
- return await super.getKey(protectedHeader, token);
54
+ return await this._local(protectedHeader, token);
56
55
  }
57
56
  catch (err) {
58
57
  if (err instanceof errors_js_1.JWKSNoMatchingKey) {
59
58
  if (this.coolingDown() === false) {
60
59
  await this.reload();
61
- return super.getKey(protectedHeader, token);
60
+ return this._local(protectedHeader, token);
62
61
  }
63
62
  }
64
63
  throw err;
@@ -75,10 +74,7 @@ class RemoteJWKSet extends local_js_1.LocalJWKSet {
75
74
  }
76
75
  this._pendingFetch ||= (0, fetch_jwks_js_1.default)(this._url, this._timeoutDuration, this._options)
77
76
  .then((json) => {
78
- if (!(0, local_js_1.isJWKSLike)(json)) {
79
- throw new errors_js_1.JWKSInvalid('JSON Web Key Set malformed');
80
- }
81
- this._jwks = { keys: json.keys };
77
+ this._local = (0, local_js_1.createLocalJWKSet)(json);
82
78
  this._jwksTimestamp = Date.now();
83
79
  this._pendingFetch = undefined;
84
80
  })
@@ -91,6 +87,36 @@ class RemoteJWKSet extends local_js_1.LocalJWKSet {
91
87
  }
92
88
  function createRemoteJWKSet(url, options) {
93
89
  const set = new RemoteJWKSet(url, options);
94
- return async (protectedHeader, token) => set.getKey(protectedHeader, token);
90
+ const remoteJWKSet = async (protectedHeader, token) => set.getKey(protectedHeader, token);
91
+ Object.defineProperties(remoteJWKSet, {
92
+ coolingDown: {
93
+ get: () => set.coolingDown(),
94
+ enumerable: true,
95
+ configurable: false,
96
+ },
97
+ fresh: {
98
+ get: () => set.fresh(),
99
+ enumerable: true,
100
+ configurable: false,
101
+ },
102
+ reload: {
103
+ value: () => set.reload(),
104
+ enumerable: true,
105
+ configurable: false,
106
+ writable: false,
107
+ },
108
+ reloading: {
109
+ get: () => !!set._pendingFetch,
110
+ enumerable: true,
111
+ configurable: false,
112
+ },
113
+ jwks: {
114
+ value: () => set._local?.jwks(),
115
+ enumerable: true,
116
+ configurable: false,
117
+ writable: false,
118
+ },
119
+ });
120
+ return remoteJWKSet;
95
121
  }
96
122
  exports.createRemoteJWKSet = createRemoteJWKSet;
@@ -75,7 +75,7 @@ async function decryptKeyManagement(alg, key, encryptedKey, joseHeader, options)
75
75
  throw new errors_js_1.JWEInvalid('JWE Encrypted Key missing');
76
76
  if (typeof joseHeader.p2c !== 'number')
77
77
  throw new errors_js_1.JWEInvalid(`JOSE Header "p2c" (PBES2 Count) missing or invalid`);
78
- const p2cLimit = options?.maxPBES2Count || 10000;
78
+ const p2cLimit = options?.maxPBES2Count || 10_000;
79
79
  if (joseHeader.p2c > p2cLimit)
80
80
  throw new errors_js_1.JWEInvalid(`JOSE Header "p2c" (PBES2 Count) out is of acceptable bounds`);
81
81
  if (typeof joseHeader.p2s !== 'string')
@@ -107,13 +107,11 @@ export class FlattenedEncrypt {
107
107
  this._unprotectedHeader = { ...this._unprotectedHeader, ...parameters };
108
108
  }
109
109
  }
110
+ else if (!this._protectedHeader) {
111
+ this.setProtectedHeader(parameters);
112
+ }
110
113
  else {
111
- if (!this._protectedHeader) {
112
- this.setProtectedHeader(parameters);
113
- }
114
- else {
115
- this._protectedHeader = { ...this._protectedHeader, ...parameters };
116
- }
114
+ this._protectedHeader = { ...this._protectedHeader, ...parameters };
117
115
  }
118
116
  }
119
117
  }
@@ -14,7 +14,7 @@ function getKtyFromAlg(alg) {
14
14
  throw new JOSENotSupported('Unsupported "alg" value for a JSON Web Key Set');
15
15
  }
16
16
  }
17
- export function isJWKSLike(jwks) {
17
+ function isJWKSLike(jwks) {
18
18
  return (jwks &&
19
19
  typeof jwks === 'object' &&
20
20
  Array.isArray(jwks.keys) &&
@@ -109,5 +109,14 @@ async function importWithAlgCache(cache, jwk, alg) {
109
109
  }
110
110
  export function createLocalJWKSet(jwks) {
111
111
  const set = new LocalJWKSet(jwks);
112
- return async (protectedHeader, token) => set.getKey(protectedHeader, token);
112
+ const localJWKSet = async (protectedHeader, token) => set.getKey(protectedHeader, token);
113
+ Object.defineProperties(localJWKSet, {
114
+ jwks: {
115
+ value: () => clone(set._jwks),
116
+ enumerable: true,
117
+ configurable: false,
118
+ writable: false,
119
+ },
120
+ });
121
+ return localJWKSet;
113
122
  }
@@ -1,6 +1,6 @@
1
1
  import fetchJwks from '../runtime/fetch_jwks.js';
2
- import { JWKSInvalid, JWKSNoMatchingKey } from '../util/errors.js';
3
- import { isJWKSLike, LocalJWKSet } from './local.js';
2
+ import { JWKSNoMatchingKey } from '../util/errors.js';
3
+ import { createLocalJWKSet } from './local.js';
4
4
  function isCloudflareWorkers() {
5
5
  return (typeof WebSocketPair !== 'undefined' ||
6
6
  (typeof navigator !== 'undefined' && navigator.userAgent === 'Cloudflare-Workers') ||
@@ -9,10 +9,10 @@ function isCloudflareWorkers() {
9
9
  let USER_AGENT;
10
10
  if (typeof navigator === 'undefined' || !navigator.userAgent?.startsWith?.('Mozilla/5.0 ')) {
11
11
  const NAME = 'jose';
12
- const VERSION = 'v5.2.3';
12
+ const VERSION = 'v5.3.0';
13
13
  USER_AGENT = `${NAME}/${VERSION}`;
14
14
  }
15
- class RemoteJWKSet extends LocalJWKSet {
15
+ class RemoteJWKSet {
16
16
  _url;
17
17
  _timeoutDuration;
18
18
  _cooldownDuration;
@@ -20,9 +20,8 @@ class RemoteJWKSet extends LocalJWKSet {
20
20
  _jwksTimestamp;
21
21
  _pendingFetch;
22
22
  _options;
23
+ _local;
23
24
  constructor(url, options) {
24
- super({ keys: [] });
25
- this._jwks = undefined;
26
25
  if (!(url instanceof URL)) {
27
26
  throw new TypeError('url must be an instance of URL');
28
27
  }
@@ -45,17 +44,17 @@ class RemoteJWKSet extends LocalJWKSet {
45
44
  : false;
46
45
  }
47
46
  async getKey(protectedHeader, token) {
48
- if (!this._jwks || !this.fresh()) {
47
+ if (!this._local || !this.fresh()) {
49
48
  await this.reload();
50
49
  }
51
50
  try {
52
- return await super.getKey(protectedHeader, token);
51
+ return await this._local(protectedHeader, token);
53
52
  }
54
53
  catch (err) {
55
54
  if (err instanceof JWKSNoMatchingKey) {
56
55
  if (this.coolingDown() === false) {
57
56
  await this.reload();
58
- return super.getKey(protectedHeader, token);
57
+ return this._local(protectedHeader, token);
59
58
  }
60
59
  }
61
60
  throw err;
@@ -72,10 +71,7 @@ class RemoteJWKSet extends LocalJWKSet {
72
71
  }
73
72
  this._pendingFetch ||= fetchJwks(this._url, this._timeoutDuration, this._options)
74
73
  .then((json) => {
75
- if (!isJWKSLike(json)) {
76
- throw new JWKSInvalid('JSON Web Key Set malformed');
77
- }
78
- this._jwks = { keys: json.keys };
74
+ this._local = createLocalJWKSet(json);
79
75
  this._jwksTimestamp = Date.now();
80
76
  this._pendingFetch = undefined;
81
77
  })
@@ -88,5 +84,35 @@ class RemoteJWKSet extends LocalJWKSet {
88
84
  }
89
85
  export function createRemoteJWKSet(url, options) {
90
86
  const set = new RemoteJWKSet(url, options);
91
- return async (protectedHeader, token) => set.getKey(protectedHeader, token);
87
+ const remoteJWKSet = async (protectedHeader, token) => set.getKey(protectedHeader, token);
88
+ Object.defineProperties(remoteJWKSet, {
89
+ coolingDown: {
90
+ get: () => set.coolingDown(),
91
+ enumerable: true,
92
+ configurable: false,
93
+ },
94
+ fresh: {
95
+ get: () => set.fresh(),
96
+ enumerable: true,
97
+ configurable: false,
98
+ },
99
+ reload: {
100
+ value: () => set.reload(),
101
+ enumerable: true,
102
+ configurable: false,
103
+ writable: false,
104
+ },
105
+ reloading: {
106
+ get: () => !!set._pendingFetch,
107
+ enumerable: true,
108
+ configurable: false,
109
+ },
110
+ jwks: {
111
+ value: () => set._local?.jwks(),
112
+ enumerable: true,
113
+ configurable: false,
114
+ writable: false,
115
+ },
116
+ });
117
+ return remoteJWKSet;
92
118
  }
@@ -73,7 +73,7 @@ async function decryptKeyManagement(alg, key, encryptedKey, joseHeader, options)
73
73
  throw new JWEInvalid('JWE Encrypted Key missing');
74
74
  if (typeof joseHeader.p2c !== 'number')
75
75
  throw new JWEInvalid(`JOSE Header "p2c" (PBES2 Count) missing or invalid`);
76
- const p2cLimit = options?.maxPBES2Count || 10000;
76
+ const p2cLimit = options?.maxPBES2Count || 10_000;
77
77
  if (joseHeader.p2c > p2cLimit)
78
78
  throw new JWEInvalid(`JOSE Header "p2c" (PBES2 Count) out is of acceptable bounds`);
79
79
  if (typeof joseHeader.p2s !== 'string')
@@ -1,9 +1,7 @@
1
1
  import type { KeyLike, JWSHeaderParameters, JSONWebKeySet, FlattenedJWSInput } from '../types';
2
2
  /** @private */
3
- export declare function isJWKSLike(jwks: unknown): jwks is JSONWebKeySet;
4
- /** @private */
5
3
  export declare class LocalJWKSet<KeyLikeType extends KeyLike = KeyLike> {
6
- protected _jwks?: JSONWebKeySet;
4
+ private _jwks?;
7
5
  private _cached;
8
6
  constructor(jwks: unknown);
9
7
  getKey(protectedHeader?: JWSHeaderParameters, token?: FlattenedJWSInput): Promise<KeyLikeType>;
@@ -1,4 +1,4 @@
1
- import type { KeyLike, JWSHeaderParameters, FlattenedJWSInput } from '../types';
1
+ import type { KeyLike, JWSHeaderParameters, FlattenedJWSInput, JSONWebKeySet } from '../types';
2
2
  /** Options for the remote JSON Web Key Set. */
3
3
  export interface RemoteJWKSetOptions {
4
4
  /**
@@ -53,4 +53,16 @@ export interface RemoteJWKSetOptions {
53
53
  * @param url URL to fetch the JSON Web Key Set from.
54
54
  * @param options Options for the remote JSON Web Key Set.
55
55
  */
56
- export declare function createRemoteJWKSet<KeyLikeType extends KeyLike = KeyLike>(url: URL, options?: RemoteJWKSetOptions): (protectedHeader?: JWSHeaderParameters, token?: FlattenedJWSInput) => Promise<KeyLikeType>;
56
+ export declare function createRemoteJWKSet<KeyLikeType extends KeyLike = KeyLike>(url: URL, options?: RemoteJWKSetOptions): {
57
+ (protectedHeader?: JWSHeaderParameters, token?: FlattenedJWSInput): Promise<KeyLikeType>;
58
+ /** @ignore */
59
+ coolingDown: boolean;
60
+ /** @ignore */
61
+ fresh: boolean;
62
+ /** @ignore */
63
+ reloading: boolean;
64
+ /** @ignore */
65
+ reload: () => Promise<void>;
66
+ /** @ignore */
67
+ jwks: () => JSONWebKeySet | undefined;
68
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jose",
3
- "version": "5.2.3",
3
+ "version": "5.3.0",
4
4
  "description": "JWA, JWS, JWE, JWT, JWK, JWKS for Node.js, Browser, Cloudflare Workers, Deno, Bun, and other Web-interoperable runtimes",
5
5
  "keywords": [
6
6
  "browser",
@@ -65,6 +65,7 @@
65
65
  "deno": "./dist/browser/index.js",
66
66
  "browser": "./dist/browser/index.js",
67
67
  "worker": "./dist/browser/index.js",
68
+ "workerd": "./dist/browser/index.js",
68
69
  "import": "./dist/node/esm/index.js",
69
70
  "require": "./dist/node/cjs/index.js"
70
71
  },
@@ -74,6 +75,7 @@
74
75
  "deno": "./dist/browser/util/errors.js",
75
76
  "browser": "./dist/browser/util/errors.js",
76
77
  "worker": "./dist/browser/util/errors.js",
78
+ "workerd": "./dist/browser/util/errors.js",
77
79
  "import": "./dist/node/esm/util/errors.js",
78
80
  "require": "./dist/node/cjs/util/errors.js"
79
81
  },
@@ -83,6 +85,7 @@
83
85
  "deno": "./dist/browser/util/base64url.js",
84
86
  "browser": "./dist/browser/util/base64url.js",
85
87
  "worker": "./dist/browser/util/base64url.js",
88
+ "workerd": "./dist/browser/util/base64url.js",
86
89
  "import": "./dist/node/esm/util/base64url.js",
87
90
  "require": "./dist/node/cjs/util/base64url.js"
88
91
  },