oauth4webapi 1.2.1 → 1.2.2

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
@@ -67,7 +67,7 @@ The supported JavaScript runtimes include ones that
67
67
  - These are (not an exhaustive list):
68
68
  - Browsers
69
69
  - Cloudflare Workers
70
- - Deno (^1.21.0)
70
+ - Deno
71
71
  - Electron
72
72
  - Next.js Middlewares
73
73
  - Node.js ([runtime flags may be needed](https://github.com/panva/oauth4webapi/issues/8))
package/build/index.d.ts CHANGED
@@ -537,7 +537,7 @@ export interface DPoPOptions extends CryptoKeyPair {
537
537
  * Its algorithm must be compatible with a supported {@link JWSAlgorithm JWS `alg` Algorithm}.
538
538
  */
539
539
  privateKey: CryptoKey;
540
- /** The public key corresponding to {@link DPoPOptions.privateKey} */
540
+ /** The public key corresponding to {@link DPoPOptions.privateKey}. */
541
541
  publicKey: CryptoKey;
542
542
  /**
543
543
  * Server-Provided Nonce to use in the request. This option serves as an override in case the
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 = 'v1.2.1';
4
+ const VERSION = 'v1.2.2';
5
5
  USER_AGENT = `${NAME}/${VERSION}`;
6
6
  }
7
7
  const encoder = new TextEncoder();
@@ -151,11 +151,17 @@ function prepareHeaders(input) {
151
151
  return headers;
152
152
  }
153
153
  function signal(value) {
154
- return typeof value === 'function' ? value() : value;
154
+ if (typeof value === 'function') {
155
+ value = value();
156
+ }
157
+ if (!(value instanceof AbortSignal)) {
158
+ throw new TypeError('"options.signal" must return or be an instance of AbortSignal');
159
+ }
160
+ return value;
155
161
  }
156
162
  export async function discoveryRequest(issuerIdentifier, options) {
157
163
  if (!(issuerIdentifier instanceof URL)) {
158
- throw new TypeError('"issuer" must be an instance of URL');
164
+ throw new TypeError('"issuerIdentifier" must be an instance of URL');
159
165
  }
160
166
  if (issuerIdentifier.protocol !== 'https:' && issuerIdentifier.protocol !== 'http:') {
161
167
  throw new TypeError('"issuer.protocol" must be "https:" or "http:"');
@@ -315,20 +321,20 @@ async function privateKeyJwt(as, client, key, kid) {
315
321
  kid,
316
322
  }, clientAssertion(as, client), key);
317
323
  }
318
- function assertIssuer(metadata) {
319
- if (typeof metadata !== 'object' || metadata === null) {
320
- throw new TypeError('"issuer" must be an object');
324
+ function assertAs(as) {
325
+ if (typeof as !== 'object' || as === null) {
326
+ throw new TypeError('"as" must be an object');
321
327
  }
322
- if (!validateString(metadata.issuer)) {
323
- throw new TypeError('"issuer.issuer" property must be a non-empty string');
328
+ if (!validateString(as.issuer)) {
329
+ throw new TypeError('"as.issuer" property must be a non-empty string');
324
330
  }
325
331
  return true;
326
332
  }
327
- function assertClient(metadata) {
328
- if (typeof metadata !== 'object' || metadata === null) {
333
+ function assertClient(client) {
334
+ if (typeof client !== 'object' || client === null) {
329
335
  throw new TypeError('"client" must be an object');
330
336
  }
331
- if (!validateString(metadata.client_id)) {
337
+ if (!validateString(client.client_id)) {
332
338
  throw new TypeError('"client.client_id" property must be a non-empty string');
333
339
  }
334
340
  return true;
@@ -399,7 +405,7 @@ async function jwt(header, claimsSet, key) {
399
405
  return `${input}.${signature}`;
400
406
  }
401
407
  export async function issueRequestObject(as, client, parameters, privateKey) {
402
- assertIssuer(as);
408
+ assertAs(as);
403
409
  assertClient(client);
404
410
  if (!(parameters instanceof URLSearchParams)) {
405
411
  throw new TypeError('"parameters" must be an instance of URLSearchParams');
@@ -468,13 +474,13 @@ async function publicJwk(key) {
468
474
  return { kty, crv, e, n, x, y };
469
475
  }
470
476
  export async function pushedAuthorizationRequest(as, client, parameters, options) {
471
- assertIssuer(as);
477
+ assertAs(as);
472
478
  assertClient(client);
473
479
  if (!(parameters instanceof URLSearchParams)) {
474
480
  throw new TypeError('"parameters" must be an instance of URLSearchParams');
475
481
  }
476
482
  if (typeof as.pushed_authorization_request_endpoint !== 'string') {
477
- throw new TypeError('"issuer.pushed_authorization_request_endpoint" must be a string');
483
+ throw new TypeError('"as.pushed_authorization_request_endpoint" must be a string');
478
484
  }
479
485
  const url = new URL(as.pushed_authorization_request_endpoint);
480
486
  const body = new URLSearchParams(parameters);
@@ -555,7 +561,7 @@ export function parseWwwAuthenticateChallenges(response) {
555
561
  return challenges;
556
562
  }
557
563
  export async function processPushedAuthorizationResponse(as, client, response) {
558
- assertIssuer(as);
564
+ assertAs(as);
559
565
  assertClient(client);
560
566
  if (!(response instanceof Response)) {
561
567
  throw new TypeError('"response" must be an instance of Response');
@@ -609,10 +615,10 @@ export async function protectedResourceRequest(accessToken, method, url, headers
609
615
  }).then(processDpopNonce);
610
616
  }
611
617
  export async function userInfoRequest(as, client, accessToken, options) {
612
- assertIssuer(as);
618
+ assertAs(as);
613
619
  assertClient(client);
614
620
  if (typeof as.userinfo_endpoint !== 'string') {
615
- throw new TypeError('"issuer.userinfo_endpoint" must be a string');
621
+ throw new TypeError('"as.userinfo_endpoint" must be a string');
616
622
  }
617
623
  const url = new URL(as.userinfo_endpoint);
618
624
  const headers = prepareHeaders(options?.headers);
@@ -716,7 +722,7 @@ function getContentType(response) {
716
722
  return response.headers.get('content-type')?.split(';')[0];
717
723
  }
718
724
  export async function processUserInfoResponse(as, client, expectedSubject, response, options) {
719
- assertIssuer(as);
725
+ assertAs(as);
720
726
  assertClient(client);
721
727
  if (!(response instanceof Response)) {
722
728
  throw new TypeError('"response" must be an instance of Response');
@@ -727,7 +733,7 @@ export async function processUserInfoResponse(as, client, expectedSubject, respo
727
733
  let json;
728
734
  if (getContentType(response) === 'application/jwt') {
729
735
  if (typeof as.jwks_uri !== 'string') {
730
- throw new TypeError('"issuer.jwks_uri" must be a string');
736
+ throw new TypeError('"as.jwks_uri" must be a string');
731
737
  }
732
738
  const { claims } = await validateJwt(await preserveBodyStream(response).text(), checkSigningAlgorithm.bind(undefined, client.userinfo_signed_response_alg, as.userinfo_signing_alg_values_supported), getPublicSigKeyFromIssuerJwksUri.bind(undefined, as, options))
733
739
  .then(validateOptionalAudience.bind(undefined, client.client_id))
@@ -813,7 +819,7 @@ async function authenticatedRequest(as, client, method, url, body, headers, opti
813
819
  }
814
820
  async function tokenEndpointRequest(as, client, grantType, parameters, options) {
815
821
  if (typeof as.token_endpoint !== 'string') {
816
- throw new TypeError('"issuer.token_endpoint" must be a string');
822
+ throw new TypeError('"as.token_endpoint" must be a string');
817
823
  }
818
824
  const url = new URL(as.token_endpoint);
819
825
  parameters.set('grant_type', grantType);
@@ -825,7 +831,7 @@ async function tokenEndpointRequest(as, client, grantType, parameters, options)
825
831
  return authenticatedRequest(as, client, 'POST', url, parameters, headers, options);
826
832
  }
827
833
  export async function refreshTokenGrantRequest(as, client, refreshToken, options) {
828
- assertIssuer(as);
834
+ assertAs(as);
829
835
  assertClient(client);
830
836
  if (!validateString(refreshToken)) {
831
837
  throw new TypeError('"refreshToken" must be a non-empty string');
@@ -842,7 +848,7 @@ export function getValidatedIdTokenClaims(ref) {
842
848
  return idTokenClaims.get(ref);
843
849
  }
844
850
  async function processGenericAccessTokenResponse(as, client, response, options, ignoreIdToken = false, ignoreRefreshToken = false) {
845
- assertIssuer(as);
851
+ assertAs(as);
846
852
  assertClient(client);
847
853
  if (!(response instanceof Response)) {
848
854
  throw new TypeError('"response" must be an instance of Response');
@@ -892,7 +898,7 @@ async function processGenericAccessTokenResponse(as, client, response, options,
892
898
  }
893
899
  if (json.id_token) {
894
900
  if (typeof as.jwks_uri !== 'string') {
895
- throw new TypeError('"issuer.jwks_uri" must be a string');
901
+ throw new TypeError('"as.jwks_uri" must be a string');
896
902
  }
897
903
  const { header, claims } = await validateJwt(json.id_token, checkSigningAlgorithm.bind(undefined, client.id_token_signed_response_alg, as.id_token_signing_alg_values_supported), getPublicSigKeyFromIssuerJwksUri.bind(undefined, as, options))
898
904
  .then(validatePresence.bind(undefined, ['aud', 'exp', 'iat', 'iss', 'sub']))
@@ -948,7 +954,7 @@ function validateIssuer(expected, result) {
948
954
  return result;
949
955
  }
950
956
  export async function authorizationCodeGrantRequest(as, client, callbackParameters, redirectUri, codeVerifier, options) {
951
- assertIssuer(as);
957
+ assertAs(as);
952
958
  assertClient(client);
953
959
  if (!(callbackParameters instanceof CallbackParameters)) {
954
960
  throw new TypeError('"callbackParameters" must be an instance of CallbackParameters obtained from "validateAuthResponse()", or "validateJwtAuthResponse()');
@@ -1050,7 +1056,7 @@ function checkJwtType(expected, result) {
1050
1056
  return result;
1051
1057
  }
1052
1058
  export async function clientCredentialsGrantRequest(as, client, parameters, options) {
1053
- assertIssuer(as);
1059
+ assertAs(as);
1054
1060
  assertClient(client);
1055
1061
  return tokenEndpointRequest(as, client, 'client_credentials', new URLSearchParams(parameters), options);
1056
1062
  }
@@ -1062,13 +1068,13 @@ export async function processClientCredentialsResponse(as, client, response) {
1062
1068
  return result;
1063
1069
  }
1064
1070
  export async function revocationRequest(as, client, token, options) {
1065
- assertIssuer(as);
1071
+ assertAs(as);
1066
1072
  assertClient(client);
1067
1073
  if (!validateString(token)) {
1068
1074
  throw new TypeError('"token" must be a non-empty string');
1069
1075
  }
1070
1076
  if (typeof as.revocation_endpoint !== 'string') {
1071
- throw new TypeError('"issuer.revocation_endpoint" must be a string');
1077
+ throw new TypeError('"as.revocation_endpoint" must be a string');
1072
1078
  }
1073
1079
  const url = new URL(as.revocation_endpoint);
1074
1080
  const body = new URLSearchParams(options?.additionalParameters);
@@ -1096,13 +1102,13 @@ function assertReadableResponse(response) {
1096
1102
  }
1097
1103
  }
1098
1104
  export async function introspectionRequest(as, client, token, options) {
1099
- assertIssuer(as);
1105
+ assertAs(as);
1100
1106
  assertClient(client);
1101
1107
  if (!validateString(token)) {
1102
1108
  throw new TypeError('"token" must be a non-empty string');
1103
1109
  }
1104
1110
  if (typeof as.introspection_endpoint !== 'string') {
1105
- throw new TypeError('"issuer.introspection_endpoint" must be a string');
1111
+ throw new TypeError('"as.introspection_endpoint" must be a string');
1106
1112
  }
1107
1113
  const url = new URL(as.introspection_endpoint);
1108
1114
  const body = new URLSearchParams(options?.additionalParameters);
@@ -1117,7 +1123,7 @@ export async function introspectionRequest(as, client, token, options) {
1117
1123
  return authenticatedRequest(as, client, 'POST', url, body, headers, options);
1118
1124
  }
1119
1125
  export async function processIntrospectionResponse(as, client, response, options) {
1120
- assertIssuer(as);
1126
+ assertAs(as);
1121
1127
  assertClient(client);
1122
1128
  if (!(response instanceof Response)) {
1123
1129
  throw new TypeError('"response" must be an instance of Response');
@@ -1132,7 +1138,7 @@ export async function processIntrospectionResponse(as, client, response, options
1132
1138
  let json;
1133
1139
  if (getContentType(response) === 'application/token-introspection+jwt') {
1134
1140
  if (typeof as.jwks_uri !== 'string') {
1135
- throw new TypeError('"issuer.jwks_uri" must be a string');
1141
+ throw new TypeError('"as.jwks_uri" must be a string');
1136
1142
  }
1137
1143
  const { claims } = await validateJwt(await preserveBodyStream(response).text(), checkSigningAlgorithm.bind(undefined, client.introspection_signed_response_alg, as.introspection_signing_alg_values_supported), getPublicSigKeyFromIssuerJwksUri.bind(undefined, as, options))
1138
1144
  .then(checkJwtType.bind(undefined, 'token-introspection+jwt'))
@@ -1161,9 +1167,9 @@ export async function processIntrospectionResponse(as, client, response, options
1161
1167
  return json;
1162
1168
  }
1163
1169
  export async function jwksRequest(as, options) {
1164
- assertIssuer(as);
1170
+ assertAs(as);
1165
1171
  if (typeof as.jwks_uri !== 'string') {
1166
- throw new TypeError('"issuer.jwks_uri" must be a string');
1172
+ throw new TypeError('"as.jwks_uri" must be a string');
1167
1173
  }
1168
1174
  const url = new URL(as.jwks_uri);
1169
1175
  const headers = prepareHeaders(options?.headers);
@@ -1328,7 +1334,7 @@ async function validateJwt(jws, checkAlg, getKey) {
1328
1334
  return { header, claims };
1329
1335
  }
1330
1336
  export async function validateJwtAuthResponse(as, client, parameters, expectedState, options) {
1331
- assertIssuer(as);
1337
+ assertAs(as);
1332
1338
  assertClient(client);
1333
1339
  if (parameters instanceof URL) {
1334
1340
  parameters = parameters.searchParams;
@@ -1341,7 +1347,7 @@ export async function validateJwtAuthResponse(as, client, parameters, expectedSt
1341
1347
  throw new OPE('"parameters" does not contain a JARM response');
1342
1348
  }
1343
1349
  if (typeof as.jwks_uri !== 'string') {
1344
- throw new TypeError('"issuer.jwks_uri" must be a string');
1350
+ throw new TypeError('"as.jwks_uri" must be a string');
1345
1351
  }
1346
1352
  const { claims } = await validateJwt(response, checkSigningAlgorithm.bind(undefined, client.authorization_signed_response_alg, as.authorization_signing_alg_values_supported), getPublicSigKeyFromIssuerJwksUri.bind(undefined, as, options))
1347
1353
  .then(validatePresence.bind(undefined, ['aud', 'exp', 'iss']))
@@ -1384,7 +1390,7 @@ export const expectNoState = Symbol();
1384
1390
  class CallbackParameters extends URLSearchParams {
1385
1391
  }
1386
1392
  export function validateAuthResponse(as, client, parameters, expectedState) {
1387
- assertIssuer(as);
1393
+ assertAs(as);
1388
1394
  assertClient(client);
1389
1395
  if (parameters instanceof URL) {
1390
1396
  parameters = parameters.searchParams;
@@ -1460,13 +1466,13 @@ async function importJwk(jwk) {
1460
1466
  return crypto.subtle.importKey('jwk', key, algorithm, true, ['verify']);
1461
1467
  }
1462
1468
  export async function deviceAuthorizationRequest(as, client, parameters, options) {
1463
- assertIssuer(as);
1469
+ assertAs(as);
1464
1470
  assertClient(client);
1465
1471
  if (!(parameters instanceof URLSearchParams)) {
1466
1472
  throw new TypeError('"parameters" must be an instance of URLSearchParams');
1467
1473
  }
1468
1474
  if (typeof as.device_authorization_endpoint !== 'string') {
1469
- throw new TypeError('"issuer.device_authorization_endpoint" must be a string');
1475
+ throw new TypeError('"as.device_authorization_endpoint" must be a string');
1470
1476
  }
1471
1477
  const url = new URL(as.device_authorization_endpoint);
1472
1478
  const body = new URLSearchParams(parameters);
@@ -1476,7 +1482,7 @@ export async function deviceAuthorizationRequest(as, client, parameters, options
1476
1482
  return authenticatedRequest(as, client, 'POST', url, body, headers, options);
1477
1483
  }
1478
1484
  export async function processDeviceAuthorizationResponse(as, client, response) {
1479
- assertIssuer(as);
1485
+ assertAs(as);
1480
1486
  assertClient(client);
1481
1487
  if (!(response instanceof Response)) {
1482
1488
  throw new TypeError('"response" must be an instance of Response');
@@ -1520,7 +1526,7 @@ export async function processDeviceAuthorizationResponse(as, client, response) {
1520
1526
  return json;
1521
1527
  }
1522
1528
  export async function deviceCodeGrantRequest(as, client, deviceCode, options) {
1523
- assertIssuer(as);
1529
+ assertAs(as);
1524
1530
  assertClient(client);
1525
1531
  if (!validateString(deviceCode)) {
1526
1532
  throw new TypeError('"deviceCode" must be a non-empty string');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oauth4webapi",
3
- "version": "1.2.1",
3
+ "version": "1.2.2",
4
4
  "description": "OAuth 2 / OpenID Connect for Web Platform API JavaScript runtimes",
5
5
  "keywords": [
6
6
  "auth",
@@ -43,35 +43,33 @@
43
43
  "scripts": {
44
44
  "_format": "find src test tap examples conformance -type f -name '*.ts' -o -name '*.mjs' | xargs prettier",
45
45
  "build": "rm -rf build && tsc && tsc --declaration true --emitDeclarationOnly true --removeComments false && tsc -p test && tsc -p examples && tsc -p conformance && tsc -p tap",
46
- "conformance": "patch-package && NODE_OPTIONS='--no-warnings --loader=@esbuild-kit/esm-loader' ava --config conformance/ava.config.ts",
47
- "coverage": "patch-package && c8 ava",
46
+ "conformance": "bash -c 'patch-package && source .node_flags.sh && ava --config conformance/ava.config.ts'",
48
47
  "docs": "patch-package && typedoc",
49
48
  "format": "npm run _format -- --write",
50
49
  "format-check": "npm run _format -- --check",
51
50
  "prepack": "npm run format && npm run docs && ./examples/.update-diffs.sh && git diff --quiet && npm run test && npm run build",
52
51
  "tap:deno": "./tap/.deno.sh",
53
52
  "tap:edge-runtime": "./tap/.edge-runtime.sh",
54
- "tap:node": "./tap/.node.sh",
53
+ "tap:node": "bash -c './tap/.node.sh'",
55
54
  "tap:workers": "./tap/.workers.sh",
56
55
  "tap:browsers": "./tap/.browsers.sh",
57
- "test": "ava"
56
+ "test": "bash -c 'source .node_flags.sh && ava'"
58
57
  },
59
58
  "devDependencies": {
60
59
  "@esbuild-kit/esm-loader": "^2.5.0",
61
- "@types/node": "^18.8.3",
60
+ "@types/node": "^18.11.2",
62
61
  "@types/qunit": "^2.19.3",
63
62
  "ava": "^4.3.3",
64
- "c8": "^7.12.0",
65
- "edge-runtime": "^1.1.0-beta.31",
63
+ "edge-runtime": "^1.1.0-beta.40",
66
64
  "jose": "^4.10.0",
67
65
  "patch-package": "^6.4.7",
68
66
  "prettier": "^2.7.1",
69
67
  "prettier-plugin-jsdoc": "^0.4.2",
70
- "qunit": "^2.19.1",
68
+ "qunit": "^2.19.2",
71
69
  "testcafe": "^2.0.1",
72
70
  "testcafe-browser-provider-browserstack": "^1.14.0",
73
71
  "timekeeper": "^2.2.0",
74
- "typedoc": "^0.23.15",
72
+ "typedoc": "^0.23.17",
75
73
  "typedoc-plugin-markdown": "^3.13.6",
76
74
  "typescript": "^4.8.4",
77
75
  "undici": "^5.11.0",