jose 4.6.2 → 4.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -91,10 +91,8 @@ import * as jose from 'https://deno.land/x/jose/index.ts'
91
91
 
92
92
  | Version | Security Fixes 🔑 | Other Bug Fixes 🐞 | New Features ⭐ |
93
93
  | ------- | --------- | -------- | -------- |
94
- | [4.x.x](https://github.com/panva/jose/tree/v4.x) | ✅ | ✅ | ✅ |
95
- | [3.x.x](https://github.com/panva/jose/tree/v3.x) | ✅ | ✅ until 2022-04-30 | ❌ |
96
- | [2.x.x](https://github.com/panva/jose/tree/v2.x) | ✅ | ✅ until 2022-04-30 | ❌ |
97
- | [1.x.x](https://github.com/panva/jose/tree/v1.x) | ✅ | ❌ | ❌ |
94
+ | [v4.x](https://github.com/panva/jose/tree/v4.x) | ✅ | ✅ | ✅ |
95
+ | [v3.x](https://github.com/panva/jose/tree/v3.x), [v2.x](https://github.com/panva/jose/tree/v2.x), [v1.x](https://github.com/panva/jose/tree/v1.x) | ✅ | ❌ | ❌ |
98
96
 
99
97
  #### Semver?
100
98
 
@@ -10,20 +10,25 @@ class RemoteJWKSet extends LocalJWKSet {
10
10
  throw new TypeError('url must be an instance of URL');
11
11
  }
12
12
  this._url = new URL(url.href);
13
- this._options = { agent: options === null || options === void 0 ? void 0 : options.agent };
13
+ this._options = { agent: options === null || options === void 0 ? void 0 : options.agent, headers: options === null || options === void 0 ? void 0 : options.headers };
14
14
  this._timeoutDuration =
15
15
  typeof (options === null || options === void 0 ? void 0 : options.timeoutDuration) === 'number' ? options === null || options === void 0 ? void 0 : options.timeoutDuration : 5000;
16
16
  this._cooldownDuration =
17
17
  typeof (options === null || options === void 0 ? void 0 : options.cooldownDuration) === 'number' ? options === null || options === void 0 ? void 0 : options.cooldownDuration : 30000;
18
+ this._cacheMaxAge = typeof (options === null || options === void 0 ? void 0 : options.cacheMaxAge) === 'number' ? options === null || options === void 0 ? void 0 : options.cacheMaxAge : 600000;
18
19
  }
19
20
  coolingDown() {
20
- if (!this._cooldownStarted) {
21
- return false;
22
- }
23
- return Date.now() < this._cooldownStarted + this._cooldownDuration;
21
+ return typeof this._jwksTimestamp === 'number'
22
+ ? Date.now() < this._jwksTimestamp + this._cooldownDuration
23
+ : false;
24
+ }
25
+ fresh() {
26
+ return typeof this._jwksTimestamp === 'number'
27
+ ? Date.now() < this._jwksTimestamp + this._cacheMaxAge
28
+ : false;
24
29
  }
25
30
  async getKey(protectedHeader, token) {
26
- if (!this._jwks) {
31
+ if (!this._jwks || !this.fresh()) {
27
32
  await this.reload();
28
33
  }
29
34
  try {
@@ -60,7 +65,7 @@ class RemoteJWKSet extends LocalJWKSet {
60
65
  throw new JWKSInvalid('JSON Web Key Set malformed');
61
66
  }
62
67
  this._jwks = { keys: json.keys };
63
- this._cooldownStarted = Date.now();
68
+ this._jwksTimestamp = Date.now();
64
69
  this._pendingFetch = undefined;
65
70
  })
66
71
  .catch((err) => {
@@ -1,5 +1,5 @@
1
1
  import { JOSEError, JWKSTimeout } from '../util/errors.js';
2
- const fetchJwks = async (url, timeout) => {
2
+ const fetchJwks = async (url, timeout, options) => {
3
3
  let controller;
4
4
  let id;
5
5
  let timedOut = false;
@@ -13,6 +13,7 @@ const fetchJwks = async (url, timeout) => {
13
13
  const response = await fetch(url.href, {
14
14
  signal: controller ? controller.signal : undefined,
15
15
  redirect: 'manual',
16
+ headers: options.headers,
16
17
  }).catch((err) => {
17
18
  if (timedOut)
18
19
  throw new JWKSTimeout();
@@ -1,12 +1,2 @@
1
1
  export default crypto;
2
- export function isCryptoKey(key) {
3
- try {
4
- return (key != null &&
5
- typeof key.extractable === 'boolean' &&
6
- typeof key.algorithm.name === 'string' &&
7
- typeof key.type === 'string');
8
- }
9
- catch (_a) {
10
- return false;
11
- }
12
- }
2
+ export const isCryptoKey = (key) => key instanceof CryptoKey;
@@ -13,20 +13,25 @@ class RemoteJWKSet extends local_js_1.LocalJWKSet {
13
13
  throw new TypeError('url must be an instance of URL');
14
14
  }
15
15
  this._url = new URL(url.href);
16
- this._options = { agent: options === null || options === void 0 ? void 0 : options.agent };
16
+ this._options = { agent: options === null || options === void 0 ? void 0 : options.agent, headers: options === null || options === void 0 ? void 0 : options.headers };
17
17
  this._timeoutDuration =
18
18
  typeof (options === null || options === void 0 ? void 0 : options.timeoutDuration) === 'number' ? options === null || options === void 0 ? void 0 : options.timeoutDuration : 5000;
19
19
  this._cooldownDuration =
20
20
  typeof (options === null || options === void 0 ? void 0 : options.cooldownDuration) === 'number' ? options === null || options === void 0 ? void 0 : options.cooldownDuration : 30000;
21
+ this._cacheMaxAge = typeof (options === null || options === void 0 ? void 0 : options.cacheMaxAge) === 'number' ? options === null || options === void 0 ? void 0 : options.cacheMaxAge : 600000;
21
22
  }
22
23
  coolingDown() {
23
- if (!this._cooldownStarted) {
24
- return false;
25
- }
26
- return Date.now() < this._cooldownStarted + this._cooldownDuration;
24
+ return typeof this._jwksTimestamp === 'number'
25
+ ? Date.now() < this._jwksTimestamp + this._cooldownDuration
26
+ : false;
27
+ }
28
+ fresh() {
29
+ return typeof this._jwksTimestamp === 'number'
30
+ ? Date.now() < this._jwksTimestamp + this._cacheMaxAge
31
+ : false;
27
32
  }
28
33
  async getKey(protectedHeader, token) {
29
- if (!this._jwks) {
34
+ if (!this._jwks || !this.fresh()) {
30
35
  await this.reload();
31
36
  }
32
37
  try {
@@ -63,7 +68,7 @@ class RemoteJWKSet extends local_js_1.LocalJWKSet {
63
68
  throw new errors_js_1.JWKSInvalid('JSON Web Key Set malformed');
64
69
  }
65
70
  this._jwks = { keys: json.keys };
66
- this._cooldownStarted = Date.now();
71
+ this._jwksTimestamp = Date.now();
67
72
  this._pendingFetch = undefined;
68
73
  })
69
74
  .catch((err) => {
@@ -17,10 +17,11 @@ const fetchJwks = async (url, timeout, options) => {
17
17
  default:
18
18
  throw new TypeError('Unsupported URL protocol.');
19
19
  }
20
- const { agent } = options;
20
+ const { agent, headers } = options;
21
21
  const req = get(url.href, {
22
22
  agent,
23
23
  timeout,
24
+ headers,
24
25
  });
25
26
  const [response] = (await Promise.race([(0, events_1.once)(req, 'response'), (0, events_1.once)(req, 'timeout')]));
26
27
  if (!response) {
@@ -6,6 +6,6 @@ const util = require("util");
6
6
  const webcrypto = crypto.webcrypto;
7
7
  exports.default = webcrypto;
8
8
  exports.isCryptoKey = util.types.isCryptoKey
9
- ? (obj) => util.types.isCryptoKey(obj)
9
+ ? (key) => util.types.isCryptoKey(key)
10
10
  :
11
- (obj) => false;
11
+ (key) => false;
@@ -10,20 +10,25 @@ class RemoteJWKSet extends LocalJWKSet {
10
10
  throw new TypeError('url must be an instance of URL');
11
11
  }
12
12
  this._url = new URL(url.href);
13
- this._options = { agent: options === null || options === void 0 ? void 0 : options.agent };
13
+ this._options = { agent: options === null || options === void 0 ? void 0 : options.agent, headers: options === null || options === void 0 ? void 0 : options.headers };
14
14
  this._timeoutDuration =
15
15
  typeof (options === null || options === void 0 ? void 0 : options.timeoutDuration) === 'number' ? options === null || options === void 0 ? void 0 : options.timeoutDuration : 5000;
16
16
  this._cooldownDuration =
17
17
  typeof (options === null || options === void 0 ? void 0 : options.cooldownDuration) === 'number' ? options === null || options === void 0 ? void 0 : options.cooldownDuration : 30000;
18
+ this._cacheMaxAge = typeof (options === null || options === void 0 ? void 0 : options.cacheMaxAge) === 'number' ? options === null || options === void 0 ? void 0 : options.cacheMaxAge : 600000;
18
19
  }
19
20
  coolingDown() {
20
- if (!this._cooldownStarted) {
21
- return false;
22
- }
23
- return Date.now() < this._cooldownStarted + this._cooldownDuration;
21
+ return typeof this._jwksTimestamp === 'number'
22
+ ? Date.now() < this._jwksTimestamp + this._cooldownDuration
23
+ : false;
24
+ }
25
+ fresh() {
26
+ return typeof this._jwksTimestamp === 'number'
27
+ ? Date.now() < this._jwksTimestamp + this._cacheMaxAge
28
+ : false;
24
29
  }
25
30
  async getKey(protectedHeader, token) {
26
- if (!this._jwks) {
31
+ if (!this._jwks || !this.fresh()) {
27
32
  await this.reload();
28
33
  }
29
34
  try {
@@ -60,7 +65,7 @@ class RemoteJWKSet extends LocalJWKSet {
60
65
  throw new JWKSInvalid('JSON Web Key Set malformed');
61
66
  }
62
67
  this._jwks = { keys: json.keys };
63
- this._cooldownStarted = Date.now();
68
+ this._jwksTimestamp = Date.now();
64
69
  this._pendingFetch = undefined;
65
70
  })
66
71
  .catch((err) => {
@@ -15,10 +15,11 @@ const fetchJwks = async (url, timeout, options) => {
15
15
  default:
16
16
  throw new TypeError('Unsupported URL protocol.');
17
17
  }
18
- const { agent } = options;
18
+ const { agent, headers } = options;
19
19
  const req = get(url.href, {
20
20
  agent,
21
21
  timeout,
22
+ headers,
22
23
  });
23
24
  const [response] = (await Promise.race([once(req, 'response'), once(req, 'timeout')]));
24
25
  if (!response) {
@@ -3,6 +3,6 @@ import * as util from 'util';
3
3
  const webcrypto = crypto.webcrypto;
4
4
  export default webcrypto;
5
5
  export const isCryptoKey = util.types.isCryptoKey
6
- ? (obj) => util.types.isCryptoKey(obj)
6
+ ? (key) => util.types.isCryptoKey(key)
7
7
  :
8
- (obj) => false;
8
+ (key) => false;
@@ -4,25 +4,38 @@ import type { JWSHeaderParameters, FlattenedJWSInput, GetKeyFunction } from '../
4
4
  */
5
5
  export interface RemoteJWKSetOptions {
6
6
  /**
7
- * Timeout (in milliseconds) for the HTTP request. When reached the request will be
8
- * aborted and the verification will fail. Default is 5000.
7
+ * Timeout (in milliseconds) for the HTTP request. When reached the request
8
+ * will be aborted and the verification will fail. Default is 5000 (5
9
+ * seconds).
9
10
  */
10
11
  timeoutDuration?: number;
11
12
  /**
12
- * Duration (in milliseconds) for which no more HTTP requests will be triggered
13
- * after a previous successful fetch. Default is 30000.
13
+ * Duration (in milliseconds) for which no more HTTP requests will be
14
+ * triggered after a previous successful fetch. Default is 30000 (30 seconds).
14
15
  */
15
16
  cooldownDuration?: number;
16
17
  /**
17
- * An instance of [http.Agent](https://nodejs.org/api/http.html#http_class_http_agent)
18
- * or [https.Agent](https://nodejs.org/api/https.html#https_class_https_agent) to pass
19
- * to the [http.get](https://nodejs.org/api/http.html#http_http_get_options_callback)
20
- * or [https.get](https://nodejs.org/api/https.html#https_https_get_options_callback)
21
- * method's options. Use when behind an http(s) proxy.
22
- * This is a Node.js runtime specific option, it is ignored
23
- * when used outside of Node.js runtime.
18
+ * Maximum time (in milliseconds) between successful HTTP requests. Default is
19
+ * 600000 (10 minutes).
20
+ */
21
+ cacheMaxAge?: number | typeof Infinity;
22
+ /**
23
+ * An instance of
24
+ * [http.Agent](https://nodejs.org/api/http.html#http_class_http_agent) or
25
+ * [https.Agent](https://nodejs.org/api/https.html#https_class_https_agent) to
26
+ * pass to the
27
+ * [http.get](https://nodejs.org/api/http.html#http_http_get_options_callback)
28
+ * or
29
+ * [https.get](https://nodejs.org/api/https.html#https_https_get_options_callback)
30
+ * method's options. Use when behind an http(s) proxy. This is a Node.js
31
+ * runtime specific option, it is ignored when used outside of Node.js
32
+ * runtime.
24
33
  */
25
34
  agent?: any;
35
+ /**
36
+ * Optional headers to be sent with the HTTP request.
37
+ */
38
+ headers?: Record<string, string>;
26
39
  }
27
40
  interface URL {
28
41
  href: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jose",
3
- "version": "4.6.2",
3
+ "version": "4.8.1",
4
4
  "description": "'JSON Web Almost Everything' - JWA, JWS, JWE, JWT, JWK, JWKS with no dependencies using runtime's native crypto",
5
5
  "keywords": [
6
6
  "browser",
@@ -55,7 +55,9 @@
55
55
  "sideEffects": false,
56
56
  "exports": {
57
57
  ".": {
58
+ "types": "./dist/types/index.d.ts",
58
59
  "browser": "./dist/browser/index.js",
60
+ "worker": "./dist/browser/index.js",
59
61
  "import": "./dist/node/esm/index.js",
60
62
  "require": "./dist/node/cjs/index.js"
61
63
  },