oauth4webapi 2.0.2 → 2.0.4

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
@@ -39,7 +39,7 @@ import * as oauth2 from 'oauth4webapi'
39
39
  **`example`** Deno import
40
40
 
41
41
  ```js
42
- import * as oauth2 from 'https://deno.land/x/oauth4webapi@v2.0.2/mod.ts'
42
+ import * as oauth2 from 'https://deno.land/x/oauth4webapi@v2.0.4/mod.ts'
43
43
  ```
44
44
 
45
45
  - Authorization Code Flow - OpenID Connect [source](examples/code.ts), or plain OAuth 2 [source](examples/oauth.ts)
package/build/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  let USER_AGENT;
2
2
  if (typeof navigator === 'undefined' || !navigator.userAgent?.startsWith?.('Mozilla/5.0 ')) {
3
3
  const NAME = 'oauth4webapi';
4
- const VERSION = 'v2.0.1';
4
+ const VERSION = 'v2.0.3';
5
5
  USER_AGENT = `${NAME}/${VERSION}`;
6
6
  }
7
7
  const encoder = new TextEncoder();
@@ -114,10 +114,6 @@ function isPublicKey(key) {
114
114
  return isCryptoKey(key) && key.type === 'public';
115
115
  }
116
116
  const SUPPORTED_JWS_ALGS = ['PS256', 'ES256', 'RS256', 'EdDSA'];
117
- function preserveBodyStream(response) {
118
- assertReadableResponse(response);
119
- return response.clone();
120
- }
121
117
  function processDpopNonce(response) {
122
118
  const url = new URL(response.url);
123
119
  if (response.headers.has('dpop-nonce')) {
@@ -205,9 +201,10 @@ export async function processDiscoveryResponse(expectedIssuerIdentifier, respons
205
201
  if (response.status !== 200) {
206
202
  throw new OPE('"response" is not a conform Authorization Server Metadata response');
207
203
  }
204
+ assertReadableResponse(response);
208
205
  let json;
209
206
  try {
210
- json = await preserveBodyStream(response).json();
207
+ json = await response.json();
211
208
  }
212
209
  catch {
213
210
  throw new OPE('failed to parse "response" body as JSON');
@@ -484,13 +481,15 @@ async function dpopProofJwt(headers, options, url, htm, accessToken) {
484
481
  }, privateKey);
485
482
  headers.set('dpop', proof);
486
483
  }
487
- const jwkCache = Symbol();
484
+ let jwkCache;
488
485
  async function publicJwk(key) {
489
- if (key[jwkCache]) {
490
- return key[jwkCache];
486
+ jwkCache || (jwkCache = new WeakMap());
487
+ if (jwkCache.has(key)) {
488
+ return jwkCache.get(key);
491
489
  }
492
490
  const { kty, e, n, x, y, crv } = await crypto.subtle.exportKey('jwk', key);
493
- const jwk = (key[jwkCache] = { kty, e, n, x, y, crv });
491
+ const jwk = { kty, e, n, x, y, crv };
492
+ jwkCache.set(key, jwk);
494
493
  return jwk;
495
494
  }
496
495
  export async function pushedAuthorizationRequest(as, client, parameters, options) {
@@ -590,9 +589,10 @@ export async function processPushedAuthorizationResponse(as, client, response) {
590
589
  }
591
590
  throw new OPE('"response" is not a conform Pushed Authorization Request Endpoint response');
592
591
  }
592
+ assertReadableResponse(response);
593
593
  let json;
594
594
  try {
595
- json = await preserveBodyStream(response).json();
595
+ json = await response.json();
596
596
  }
597
597
  catch {
598
598
  throw new OPE('failed to parse "response" body as JSON');
@@ -648,30 +648,31 @@ export async function userInfoRequest(as, client, accessToken, options) {
648
648
  }
649
649
  return protectedResourceRequest(accessToken, 'GET', url, headers, null, options);
650
650
  }
651
- const jwksCache = Symbol();
651
+ let jwksCache;
652
652
  async function getPublicSigKeyFromIssuerJwksUri(as, options, header) {
653
653
  const { alg, kid } = header;
654
654
  checkSupportedJwsAlg(alg);
655
655
  let jwks;
656
656
  let age;
657
- if (as[jwksCache]) {
657
+ jwksCache || (jwksCache = new WeakMap());
658
+ if (jwksCache.has(as)) {
658
659
  ;
659
- ({ jwks, age } = as[jwksCache]);
660
+ ({ jwks, age } = jwksCache.get(as));
660
661
  if (age >= 300) {
661
- as[jwksCache] = undefined;
662
+ jwksCache.delete(as);
662
663
  return getPublicSigKeyFromIssuerJwksUri(as, options, header);
663
664
  }
664
665
  }
665
666
  else {
666
667
  jwks = await jwksRequest(as, options).then(processJwksResponse);
667
668
  age = 0;
668
- as[jwksCache] = {
669
+ jwksCache.set(as, {
669
670
  jwks,
670
671
  iat: epochTime(),
671
672
  get age() {
672
673
  return epochTime() - this.iat;
673
674
  },
674
- };
675
+ });
675
676
  }
676
677
  let kty;
677
678
  switch (alg.slice(0, 2)) {
@@ -714,7 +715,7 @@ async function getPublicSigKeyFromIssuerJwksUri(as, options, header) {
714
715
  const { 0: jwk, length } = candidates;
715
716
  if (!length) {
716
717
  if (age >= 60) {
717
- as[jwksCache] = undefined;
718
+ jwksCache.delete(as);
718
719
  return getPublicSigKeyFromIssuerJwksUri(as, options, header);
719
720
  }
720
721
  throw new OPE('error when selecting a JWT verification key, no applicable keys found');
@@ -743,7 +744,8 @@ export async function processUserInfoResponse(as, client, expectedSubject, respo
743
744
  }
744
745
  let json;
745
746
  if (getContentType(response) === 'application/jwt') {
746
- const { claims } = await validateJwt(await preserveBodyStream(response).text(), checkSigningAlgorithm.bind(undefined, client.userinfo_signed_response_alg, as.userinfo_signing_alg_values_supported), noSignatureCheck)
747
+ assertReadableResponse(response);
748
+ const { claims } = await validateJwt(await response.text(), checkSigningAlgorithm.bind(undefined, client.userinfo_signed_response_alg, as.userinfo_signing_alg_values_supported), noSignatureCheck)
747
749
  .then(validateOptionalAudience.bind(undefined, client.client_id))
748
750
  .then(validateOptionalIssuer.bind(undefined, as.issuer));
749
751
  json = claims;
@@ -752,8 +754,9 @@ export async function processUserInfoResponse(as, client, expectedSubject, respo
752
754
  if (client.userinfo_signed_response_alg) {
753
755
  throw new OPE('JWT UserInfo Response expected');
754
756
  }
757
+ assertReadableResponse(response);
755
758
  try {
756
- json = await preserveBodyStream(response).json();
759
+ json = await response.json();
757
760
  }
758
761
  catch {
759
762
  throw new OPE('failed to parse "response" body as JSON');
@@ -832,9 +835,10 @@ async function processGenericAccessTokenResponse(as, client, response, ignoreIdT
832
835
  }
833
836
  throw new OPE('"response" is not a conform Token Endpoint response');
834
837
  }
838
+ assertReadableResponse(response);
835
839
  let json;
836
840
  try {
837
- json = await preserveBodyStream(response).json();
841
+ json = await response.json();
838
842
  }
839
843
  catch {
840
844
  throw new OPE('failed to parse "response" body as JSON');
@@ -1100,7 +1104,8 @@ export async function processIntrospectionResponse(as, client, response) {
1100
1104
  }
1101
1105
  let json;
1102
1106
  if (getContentType(response) === 'application/token-introspection+jwt') {
1103
- const { claims } = await validateJwt(await preserveBodyStream(response).text(), checkSigningAlgorithm.bind(undefined, client.introspection_signed_response_alg, as.introspection_signing_alg_values_supported), noSignatureCheck)
1107
+ assertReadableResponse(response);
1108
+ const { claims } = await validateJwt(await response.text(), checkSigningAlgorithm.bind(undefined, client.introspection_signed_response_alg, as.introspection_signing_alg_values_supported), noSignatureCheck)
1104
1109
  .then(checkJwtType.bind(undefined, 'token-introspection+jwt'))
1105
1110
  .then(validatePresence.bind(undefined, ['aud', 'iat', 'iss']))
1106
1111
  .then(validateIssuer.bind(undefined, as.issuer))
@@ -1111,8 +1116,9 @@ export async function processIntrospectionResponse(as, client, response) {
1111
1116
  }
1112
1117
  }
1113
1118
  else {
1119
+ assertReadableResponse(response);
1114
1120
  try {
1115
- json = await preserveBodyStream(response).json();
1121
+ json = await response.json();
1116
1122
  }
1117
1123
  catch {
1118
1124
  throw new OPE('failed to parse "response" body as JSON');
@@ -1149,9 +1155,10 @@ async function processJwksResponse(response) {
1149
1155
  if (response.status !== 200) {
1150
1156
  throw new OPE('"response" is not a conform JSON Web Key Set response');
1151
1157
  }
1158
+ assertReadableResponse(response);
1152
1159
  let json;
1153
1160
  try {
1154
- json = await preserveBodyStream(response).json();
1161
+ json = await response.json();
1155
1162
  }
1156
1163
  catch {
1157
1164
  throw new OPE('failed to parse "response" body as JSON');
@@ -1169,8 +1176,9 @@ async function processJwksResponse(response) {
1169
1176
  }
1170
1177
  async function handleOAuthBodyError(response) {
1171
1178
  if (response.status > 399 && response.status < 500) {
1179
+ assertReadableResponse(response);
1172
1180
  try {
1173
- const json = await preserveBodyStream(response).json();
1181
+ const json = await response.json();
1174
1182
  if (isJsonObject(json) && typeof json.error === 'string' && json.error.length) {
1175
1183
  if (json.error_description !== undefined && typeof json.error_description !== 'string') {
1176
1184
  delete json.error_description;
@@ -1458,9 +1466,10 @@ export async function processDeviceAuthorizationResponse(as, client, response) {
1458
1466
  }
1459
1467
  throw new OPE('"response" is not a conform Device Authorization Endpoint response');
1460
1468
  }
1469
+ assertReadableResponse(response);
1461
1470
  let json;
1462
1471
  try {
1463
- json = await preserveBodyStream(response).json();
1472
+ json = await response.json();
1464
1473
  }
1465
1474
  catch {
1466
1475
  throw new OPE('failed to parse "response" body as JSON');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oauth4webapi",
3
- "version": "2.0.2",
3
+ "version": "2.0.4",
4
4
  "description": "OAuth 2 / OpenID Connect for Web Platform API JavaScript runtimes",
5
5
  "keywords": [
6
6
  "auth",
@@ -52,7 +52,6 @@
52
52
  "docs": "patch-package && typedoc",
53
53
  "format": "npm run _format -- --write",
54
54
  "format-check": "npm run _format -- --check",
55
- "prepack": "npm run format && npm run docs && ./examples/.update-diffs.sh && git diff --quiet && npm run test && npm run build",
56
55
  "tap:browsers": "./tap/.browsers.sh",
57
56
  "tap:bun": "./tap/.bun.sh",
58
57
  "tap:deno": "./tap/.deno.sh",
@@ -63,21 +62,21 @@
63
62
  "test": "bash -c 'source .node_flags.sh && ava'"
64
63
  },
65
64
  "devDependencies": {
66
- "@esbuild-kit/esm-loader": "^2.5.0",
65
+ "@esbuild-kit/esm-loader": "^2.5.1",
67
66
  "@types/node": "^18.11.9",
68
67
  "@types/qunit": "^2.19.3",
69
68
  "ava": "^5.1.0",
70
69
  "edge-runtime": "^2.0.2",
71
- "esbuild": "^0.15.14",
72
- "jose": "^4.11.0",
70
+ "esbuild": "^0.15.15",
71
+ "jose": "^4.11.1",
73
72
  "patch-package": "^6.5.0",
74
- "prettier": "^2.7.1",
73
+ "prettier": "^2.8.0",
75
74
  "prettier-plugin-jsdoc": "^0.4.2",
76
75
  "qunit": "^2.19.3",
77
76
  "timekeeper": "^2.2.0",
78
- "typedoc": "^0.23.20",
77
+ "typedoc": "^0.23.21",
79
78
  "typedoc-plugin-markdown": "^3.13.6",
80
- "typescript": "^4.8.4",
81
- "undici": "^5.12.0"
79
+ "typescript": "^4.9.3",
80
+ "undici": "^5.13.0"
82
81
  }
83
82
  }