@query-farm/vgi-rpc 0.3.4 → 0.4.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.
Files changed (50) hide show
  1. package/dist/auth.d.ts +13 -0
  2. package/dist/auth.d.ts.map +1 -0
  3. package/dist/client/connect.d.ts.map +1 -1
  4. package/dist/client/index.d.ts +2 -0
  5. package/dist/client/index.d.ts.map +1 -1
  6. package/dist/client/introspect.d.ts +1 -0
  7. package/dist/client/introspect.d.ts.map +1 -1
  8. package/dist/client/oauth.d.ts +26 -0
  9. package/dist/client/oauth.d.ts.map +1 -0
  10. package/dist/client/stream.d.ts +2 -0
  11. package/dist/client/stream.d.ts.map +1 -1
  12. package/dist/client/types.d.ts +2 -0
  13. package/dist/client/types.d.ts.map +1 -1
  14. package/dist/dispatch/stream.d.ts.map +1 -1
  15. package/dist/http/auth.d.ts +21 -0
  16. package/dist/http/auth.d.ts.map +1 -0
  17. package/dist/http/dispatch.d.ts +2 -0
  18. package/dist/http/dispatch.d.ts.map +1 -1
  19. package/dist/http/handler.d.ts.map +1 -1
  20. package/dist/http/index.d.ts +4 -0
  21. package/dist/http/index.d.ts.map +1 -1
  22. package/dist/http/jwt.d.ts +21 -0
  23. package/dist/http/jwt.d.ts.map +1 -0
  24. package/dist/http/types.d.ts +5 -0
  25. package/dist/http/types.d.ts.map +1 -1
  26. package/dist/index.d.ts +3 -2
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +1416 -46
  29. package/dist/index.js.map +18 -13
  30. package/dist/types.d.ts +8 -2
  31. package/dist/types.d.ts.map +1 -1
  32. package/dist/wire/response.d.ts.map +1 -1
  33. package/package.json +3 -2
  34. package/src/auth.ts +31 -0
  35. package/src/client/connect.ts +15 -1
  36. package/src/client/index.ts +2 -0
  37. package/src/client/introspect.ts +14 -2
  38. package/src/client/oauth.ts +74 -0
  39. package/src/client/stream.ts +12 -0
  40. package/src/client/types.ts +2 -0
  41. package/src/dispatch/stream.ts +11 -3
  42. package/src/http/auth.ts +47 -0
  43. package/src/http/dispatch.ts +6 -4
  44. package/src/http/handler.ts +41 -1
  45. package/src/http/index.ts +4 -0
  46. package/src/http/jwt.ts +66 -0
  47. package/src/http/types.ts +6 -0
  48. package/src/index.ts +7 -0
  49. package/src/types.ts +17 -3
  50. package/src/wire/response.ts +28 -14
package/dist/index.js CHANGED
@@ -50,6 +50,48 @@ var init_zstd = __esm(() => {
50
50
  isBun = typeof globalThis.Bun !== "undefined";
51
51
  });
52
52
 
53
+ // src/errors.ts
54
+ class RpcError extends Error {
55
+ errorType;
56
+ errorMessage;
57
+ remoteTraceback;
58
+ constructor(errorType, errorMessage, remoteTraceback) {
59
+ super(`${errorType}: ${errorMessage}`);
60
+ this.errorType = errorType;
61
+ this.errorMessage = errorMessage;
62
+ this.remoteTraceback = remoteTraceback;
63
+ this.name = "RpcError";
64
+ }
65
+ }
66
+
67
+ class VersionError extends Error {
68
+ constructor(message) {
69
+ super(message);
70
+ this.name = "VersionError";
71
+ }
72
+ }
73
+
74
+ // src/auth.ts
75
+ class AuthContext {
76
+ domain;
77
+ authenticated;
78
+ principal;
79
+ claims;
80
+ constructor(domain, authenticated, principal, claims = {}) {
81
+ this.domain = domain;
82
+ this.authenticated = authenticated;
83
+ this.principal = principal;
84
+ this.claims = claims;
85
+ }
86
+ static anonymous() {
87
+ return new AuthContext("", false, null);
88
+ }
89
+ requireAuthenticated() {
90
+ if (!this.authenticated) {
91
+ throw new RpcError("AuthenticationError", "Authentication required", "");
92
+ }
93
+ }
94
+ }
53
95
  // src/constants.ts
54
96
  var RPC_METHOD_KEY = "vgi_rpc.method";
55
97
  var LOG_LEVEL_KEY = "vgi_rpc.log_level";
@@ -183,27 +225,6 @@ import {
183
225
  vectorFromArray as vectorFromArray2
184
226
  } from "@query-farm/apache-arrow";
185
227
 
186
- // src/errors.ts
187
- class RpcError extends Error {
188
- errorType;
189
- errorMessage;
190
- remoteTraceback;
191
- constructor(errorType, errorMessage, remoteTraceback) {
192
- super(`${errorType}: ${errorMessage}`);
193
- this.errorType = errorType;
194
- this.errorMessage = errorMessage;
195
- this.remoteTraceback = remoteTraceback;
196
- this.name = "RpcError";
197
- }
198
- }
199
-
200
- class VersionError extends Error {
201
- constructor(message) {
202
- super(message);
203
- this.name = "VersionError";
204
- }
205
- }
206
-
207
228
  // src/wire/reader.ts
208
229
  import { RecordBatchReader as RecordBatchReader2 } from "@query-farm/apache-arrow";
209
230
 
@@ -489,11 +510,18 @@ async function httpIntrospect(baseUrl, options) {
489
510
  const prefix = options?.prefix ?? "/vgi";
490
511
  const emptySchema = new ArrowSchema([]);
491
512
  const body = buildRequestIpc(emptySchema, {}, DESCRIBE_METHOD_NAME);
513
+ const headers = { "Content-Type": ARROW_CONTENT_TYPE };
514
+ if (options?.authorization) {
515
+ headers.Authorization = options.authorization;
516
+ }
492
517
  const response = await fetch(`${baseUrl}${prefix}/${DESCRIBE_METHOD_NAME}`, {
493
518
  method: "POST",
494
- headers: { "Content-Type": ARROW_CONTENT_TYPE },
519
+ headers,
495
520
  body
496
521
  });
522
+ if (response.status === 401) {
523
+ throw new RpcError("AuthenticationError", "Authentication required", "");
524
+ }
497
525
  const responseBody = new Uint8Array(await response.arrayBuffer());
498
526
  const { batches } = await readResponseBatches(responseBody);
499
527
  return parseDescribeResponse(batches);
@@ -515,6 +543,7 @@ class HttpStreamSession {
515
543
  _compressionLevel;
516
544
  _compressFn;
517
545
  _decompressFn;
546
+ _authorization;
518
547
  constructor(opts) {
519
548
  this._baseUrl = opts.baseUrl;
520
549
  this._prefix = opts.prefix;
@@ -529,6 +558,7 @@ class HttpStreamSession {
529
558
  this._compressionLevel = opts.compressionLevel;
530
559
  this._compressFn = opts.compressFn;
531
560
  this._decompressFn = opts.decompressFn;
561
+ this._authorization = opts.authorization;
532
562
  }
533
563
  get header() {
534
564
  return this._header;
@@ -541,6 +571,9 @@ class HttpStreamSession {
541
571
  headers["Content-Encoding"] = "zstd";
542
572
  headers["Accept-Encoding"] = "zstd";
543
573
  }
574
+ if (this._authorization) {
575
+ headers.Authorization = this._authorization;
576
+ }
544
577
  return headers;
545
578
  }
546
579
  _prepareBody(content) {
@@ -605,6 +638,9 @@ class HttpStreamSession {
605
638
  headers: this._buildHeaders(),
606
639
  body: this._prepareBody(body)
607
640
  });
641
+ if (resp.status === 401) {
642
+ throw new RpcError("AuthenticationError", "Authentication required", "");
643
+ }
608
644
  const responseBody = await this._readResponse(resp);
609
645
  const { batches: responseBatches } = await readResponseBatches(responseBody);
610
646
  let resultRows = [];
@@ -690,6 +726,9 @@ class HttpStreamSession {
690
726
  headers: this._buildHeaders(),
691
727
  body: this._prepareBody(body)
692
728
  });
729
+ if (resp.status === 401) {
730
+ throw new RpcError("AuthenticationError", "Authentication required", "");
731
+ }
693
732
  return this._readResponse(resp);
694
733
  }
695
734
  close() {}
@@ -700,6 +739,7 @@ function httpConnect(baseUrl, options) {
700
739
  const prefix = (options?.prefix ?? "/vgi").replace(/\/+$/, "");
701
740
  const onLog = options?.onLog;
702
741
  const compressionLevel = options?.compressionLevel;
742
+ const authorization = options?.authorization;
703
743
  let methodCache = null;
704
744
  let compressFn;
705
745
  let decompressFn;
@@ -722,6 +762,9 @@ function httpConnect(baseUrl, options) {
722
762
  headers["Content-Encoding"] = "zstd";
723
763
  headers["Accept-Encoding"] = "zstd";
724
764
  }
765
+ if (authorization) {
766
+ headers.Authorization = authorization;
767
+ }
725
768
  return headers;
726
769
  }
727
770
  function prepareBody(content) {
@@ -730,6 +773,11 @@ function httpConnect(baseUrl, options) {
730
773
  }
731
774
  return content;
732
775
  }
776
+ function checkAuth(resp) {
777
+ if (resp.status === 401) {
778
+ throw new RpcError("AuthenticationError", "Authentication required", "");
779
+ }
780
+ }
733
781
  async function readResponse(resp) {
734
782
  let body = new Uint8Array(await resp.arrayBuffer());
735
783
  if (resp.headers.get("Content-Encoding") === "zstd" && decompressFn) {
@@ -740,7 +788,7 @@ function httpConnect(baseUrl, options) {
740
788
  async function ensureMethodCache() {
741
789
  if (methodCache)
742
790
  return methodCache;
743
- const desc = await httpIntrospect(baseUrl, { prefix });
791
+ const desc = await httpIntrospect(baseUrl, { prefix, authorization });
744
792
  methodCache = new Map(desc.methods.map((m) => [m.name, m]));
745
793
  return methodCache;
746
794
  }
@@ -759,6 +807,7 @@ function httpConnect(baseUrl, options) {
759
807
  headers: buildHeaders(),
760
808
  body: prepareBody(body)
761
809
  });
810
+ checkAuth(resp);
762
811
  const responseBody = await readResponse(resp);
763
812
  const { batches } = await readResponseBatches(responseBody);
764
813
  let resultBatch = null;
@@ -794,6 +843,7 @@ function httpConnect(baseUrl, options) {
794
843
  headers: buildHeaders(),
795
844
  body: prepareBody(body)
796
845
  });
846
+ checkAuth(resp);
797
847
  const responseBody = await readResponse(resp);
798
848
  let header = null;
799
849
  let stateToken = null;
@@ -899,7 +949,8 @@ function httpConnect(baseUrl, options) {
899
949
  header,
900
950
  compressionLevel,
901
951
  compressFn,
902
- decompressFn
952
+ decompressFn,
953
+ authorization
903
954
  });
904
955
  },
905
956
  async describe() {
@@ -908,6 +959,53 @@ function httpConnect(baseUrl, options) {
908
959
  close() {}
909
960
  };
910
961
  }
962
+ // src/client/oauth.ts
963
+ function parseMetadataJson(json) {
964
+ const result = {
965
+ resource: json.resource,
966
+ authorizationServers: json.authorization_servers
967
+ };
968
+ if (json.scopes_supported)
969
+ result.scopesSupported = json.scopes_supported;
970
+ if (json.bearer_methods_supported)
971
+ result.bearerMethodsSupported = json.bearer_methods_supported;
972
+ if (json.resource_name)
973
+ result.resourceName = json.resource_name;
974
+ if (json.resource_documentation)
975
+ result.resourceDocumentation = json.resource_documentation;
976
+ if (json.resource_policy_uri)
977
+ result.resourcePolicyUri = json.resource_policy_uri;
978
+ if (json.resource_tos_uri)
979
+ result.resourceTosUri = json.resource_tos_uri;
980
+ return result;
981
+ }
982
+ async function httpOAuthMetadata(baseUrl, prefix) {
983
+ const effectivePrefix = (prefix ?? "/vgi").replace(/\/+$/, "");
984
+ const metadataUrl = `${baseUrl.replace(/\/+$/, "")}/.well-known/oauth-protected-resource${effectivePrefix}`;
985
+ try {
986
+ return await fetchOAuthMetadata(metadataUrl);
987
+ } catch {
988
+ return null;
989
+ }
990
+ }
991
+ async function fetchOAuthMetadata(metadataUrl) {
992
+ const response = await fetch(metadataUrl);
993
+ if (!response.ok) {
994
+ throw new Error(`Failed to fetch OAuth metadata from ${metadataUrl}: ${response.status}`);
995
+ }
996
+ const json = await response.json();
997
+ return parseMetadataJson(json);
998
+ }
999
+ function parseResourceMetadataUrl(wwwAuthenticate) {
1000
+ const bearerMatch = wwwAuthenticate.match(/^Bearer\s+(.*)/i);
1001
+ if (!bearerMatch)
1002
+ return null;
1003
+ const params = bearerMatch[1];
1004
+ const metadataMatch = params.match(/resource_metadata="([^"]+)"/);
1005
+ if (!metadataMatch)
1006
+ return null;
1007
+ return metadataMatch[1];
1008
+ }
911
1009
  // src/client/pipe.ts
912
1010
  import {
913
1011
  Field as Field2,
@@ -1341,6 +1439,35 @@ function subprocessConnect(cmd, options) {
1341
1439
  };
1342
1440
  return client;
1343
1441
  }
1442
+ // src/http/auth.ts
1443
+ function oauthResourceMetadataToJson(metadata) {
1444
+ const json = {
1445
+ resource: metadata.resource,
1446
+ authorization_servers: metadata.authorizationServers
1447
+ };
1448
+ if (metadata.scopesSupported)
1449
+ json.scopes_supported = metadata.scopesSupported;
1450
+ if (metadata.bearerMethodsSupported)
1451
+ json.bearer_methods_supported = metadata.bearerMethodsSupported;
1452
+ if (metadata.resourceName)
1453
+ json.resource_name = metadata.resourceName;
1454
+ if (metadata.resourceDocumentation)
1455
+ json.resource_documentation = metadata.resourceDocumentation;
1456
+ if (metadata.resourcePolicyUri)
1457
+ json.resource_policy_uri = metadata.resourcePolicyUri;
1458
+ if (metadata.resourceTosUri)
1459
+ json.resource_tos_uri = metadata.resourceTosUri;
1460
+ return json;
1461
+ }
1462
+ function wellKnownPath(prefix) {
1463
+ return `/.well-known/oauth-protected-resource${prefix}`;
1464
+ }
1465
+ function buildWwwAuthenticateHeader(metadataUrl) {
1466
+ if (metadataUrl) {
1467
+ return `Bearer resource_metadata="${metadataUrl}"`;
1468
+ }
1469
+ return "Bearer";
1470
+ }
1344
1471
  // src/http/handler.ts
1345
1472
  import { randomBytes } from "node:crypto";
1346
1473
  import { Schema as Schema5 } from "@query-farm/apache-arrow";
@@ -1437,20 +1564,28 @@ function buildLogBatch(schema, level, message, extra, serverId, requestId) {
1437
1564
  }
1438
1565
  return buildEmptyBatch(schema, metadata);
1439
1566
  }
1440
- function buildEmptyBatch(schema, metadata) {
1441
- const children = schema.fields.map((f) => {
1442
- return makeData5({ type: f.type, length: 0, nullCount: 0 });
1443
- });
1444
- if (schema.fields.length === 0) {
1445
- const structType2 = new Struct5(schema.fields);
1446
- const data2 = makeData5({
1447
- type: structType2,
1448
- length: 0,
1449
- children: [],
1450
- nullCount: 0
1451
- });
1452
- return new RecordBatch5(schema, data2, metadata);
1567
+ function makeEmptyData(type) {
1568
+ if (DataType2.isStruct(type)) {
1569
+ const children = type.children.map((f) => makeEmptyData(f.type));
1570
+ return makeData5({ type, length: 0, children, nullCount: 0 });
1453
1571
  }
1572
+ if (DataType2.isList(type)) {
1573
+ const childData = makeEmptyData(type.children[0].type);
1574
+ return makeData5({ type, length: 0, children: [childData], nullCount: 0, valueOffsets: new Int32Array([0]) });
1575
+ }
1576
+ if (DataType2.isFixedSizeList(type)) {
1577
+ const childData = makeEmptyData(type.children[0].type);
1578
+ return makeData5({ type, length: 0, child: childData, nullCount: 0 });
1579
+ }
1580
+ if (DataType2.isMap(type)) {
1581
+ const entryType = type.children[0]?.type;
1582
+ const entryData = entryType ? makeEmptyData(entryType) : makeData5({ type: new Struct5([]), length: 0, children: [], nullCount: 0 });
1583
+ return makeData5({ type, length: 0, children: [entryData], nullCount: 0, valueOffsets: new Int32Array([0]) });
1584
+ }
1585
+ return makeData5({ type, length: 0, nullCount: 0 });
1586
+ }
1587
+ function buildEmptyBatch(schema, metadata) {
1588
+ const children = schema.fields.map((f) => makeEmptyData(f.type));
1454
1589
  const structType = new Struct5(schema.fields);
1455
1590
  const data = makeData5({
1456
1591
  type: structType,
@@ -1476,11 +1611,13 @@ class OutputCollector {
1476
1611
  _outputSchema;
1477
1612
  _serverId;
1478
1613
  _requestId;
1479
- constructor(outputSchema, producerMode = true, serverId = "", requestId = null) {
1614
+ auth;
1615
+ constructor(outputSchema, producerMode = true, serverId = "", requestId = null, authContext) {
1480
1616
  this._outputSchema = outputSchema;
1481
1617
  this._producerMode = producerMode;
1482
1618
  this._serverId = serverId;
1483
1619
  this._requestId = requestId;
1620
+ this.auth = authContext ?? AuthContext.anonymous();
1484
1621
  }
1485
1622
  get outputSchema() {
1486
1623
  return this._outputSchema;
@@ -1783,7 +1920,7 @@ async function httpDispatchUnary(method, body, ctx) {
1783
1920
  if (parsed.methodName !== method.name) {
1784
1921
  throw new HttpRpcError(`Method name in request '${parsed.methodName}' does not match URL '${method.name}'`, 400);
1785
1922
  }
1786
- const out = new OutputCollector(schema, true, ctx.serverId, parsed.requestId);
1923
+ const out = new OutputCollector(schema, true, ctx.serverId, parsed.requestId, ctx.authContext);
1787
1924
  try {
1788
1925
  const result = await method.handler(parsed.params, out);
1789
1926
  const resultBatch = buildResultBatch(schema, result, ctx.serverId, parsed.requestId);
@@ -1820,7 +1957,7 @@ async function httpDispatchStreamInit(method, body, ctx) {
1820
1957
  let headerBytes = null;
1821
1958
  if (method.headerSchema && method.headerInit) {
1822
1959
  try {
1823
- const headerOut = new OutputCollector(method.headerSchema, true, ctx.serverId, parsed.requestId);
1960
+ const headerOut = new OutputCollector(method.headerSchema, true, ctx.serverId, parsed.requestId, ctx.authContext);
1824
1961
  const headerValues = method.headerInit(parsed.params, state, headerOut);
1825
1962
  const headerBatch = buildResultBatch(method.headerSchema, headerValues, ctx.serverId, parsed.requestId);
1826
1963
  const headerBatches = [...headerOut.batches.map((b) => b.batch), headerBatch];
@@ -1888,7 +2025,7 @@ async function httpDispatchStreamExchange(method, body, ctx) {
1888
2025
  if (effectiveProducer) {
1889
2026
  return produceStreamResponse(method, state, outputSchema, inputSchema, ctx, null, null);
1890
2027
  } else {
1891
- const out = new OutputCollector(outputSchema, effectiveProducer, ctx.serverId, null);
2028
+ const out = new OutputCollector(outputSchema, effectiveProducer, ctx.serverId, null, ctx.authContext);
1892
2029
  const conformedBatch = conformBatchToSchema(reqBatch, inputSchema);
1893
2030
  try {
1894
2031
  if (method.exchangeFn) {
@@ -1938,7 +2075,7 @@ async function produceStreamResponse(method, state, outputSchema, inputSchema, c
1938
2075
  const maxBytes = ctx.maxStreamResponseBytes;
1939
2076
  let estimatedBytes = 0;
1940
2077
  while (true) {
1941
- const out = new OutputCollector(outputSchema, true, ctx.serverId, requestId);
2078
+ const out = new OutputCollector(outputSchema, true, ctx.serverId, requestId, ctx.authContext);
1942
2079
  try {
1943
2080
  if (method.producerFn) {
1944
2081
  await method.producerFn(state, out);
@@ -2014,10 +2151,12 @@ function createHttpHandler(protocol, options) {
2014
2151
  const maxRequestBytes = options?.maxRequestBytes;
2015
2152
  const maxStreamResponseBytes = options?.maxStreamResponseBytes;
2016
2153
  const serverId = options?.serverId ?? crypto.randomUUID().replace(/-/g, "").slice(0, 12);
2154
+ const authenticate = options?.authenticate;
2155
+ const oauthMetadata = options?.oauthResourceMetadata;
2017
2156
  const methods = protocol.getMethods();
2018
2157
  const compressionLevel = options?.compressionLevel;
2019
2158
  const stateSerializer = options?.stateSerializer ?? jsonStateSerializer;
2020
- const ctx = {
2159
+ const baseCtx = {
2021
2160
  signingKey,
2022
2161
  tokenTtl,
2023
2162
  serverId,
@@ -2053,6 +2192,18 @@ function createHttpHandler(protocol, options) {
2053
2192
  return async function handler(request) {
2054
2193
  const url = new URL(request.url);
2055
2194
  const path = url.pathname;
2195
+ if (oauthMetadata && path === wellKnownPath(prefix)) {
2196
+ if (request.method !== "GET") {
2197
+ return new Response("Method Not Allowed", { status: 405 });
2198
+ }
2199
+ const body2 = JSON.stringify(oauthResourceMetadataToJson(oauthMetadata));
2200
+ const headers = new Headers({
2201
+ "Content-Type": "application/json",
2202
+ "Cache-Control": "public, max-age=3600"
2203
+ });
2204
+ addCorsHeaders(headers);
2205
+ return new Response(body2, { status: 200, headers });
2206
+ }
2056
2207
  if (request.method === "OPTIONS") {
2057
2208
  if (path === `${prefix}/__capabilities__`) {
2058
2209
  const headers = new Headers;
@@ -2088,6 +2239,22 @@ function createHttpHandler(protocol, options) {
2088
2239
  if (contentEncoding === "zstd") {
2089
2240
  body = zstdDecompress(body);
2090
2241
  }
2242
+ const ctx = { ...baseCtx };
2243
+ if (authenticate) {
2244
+ try {
2245
+ ctx.authContext = await authenticate(request);
2246
+ } catch (error) {
2247
+ const headers = new Headers({ "Content-Type": "text/plain" });
2248
+ addCorsHeaders(headers);
2249
+ if (oauthMetadata) {
2250
+ const metadataUrl = new URL(request.url);
2251
+ metadataUrl.pathname = wellKnownPath(prefix);
2252
+ metadataUrl.search = "";
2253
+ headers.set("WWW-Authenticate", buildWwwAuthenticateHeader(metadataUrl.toString()));
2254
+ }
2255
+ return new Response(error.message || "Unauthorized", { status: 401, headers });
2256
+ }
2257
+ }
2091
2258
  if (path === `${prefix}/${DESCRIBE_METHOD_NAME}`) {
2092
2259
  try {
2093
2260
  const response = httpDispatchDescribe(protocol.name, methods, serverId);
@@ -2147,6 +2314,1200 @@ function createHttpHandler(protocol, options) {
2147
2314
  }
2148
2315
  };
2149
2316
  }
2317
+ // node_modules/oauth4webapi/build/index.js
2318
+ var USER_AGENT;
2319
+ if (typeof navigator === "undefined" || !navigator.userAgent?.startsWith?.("Mozilla/5.0 ")) {
2320
+ const NAME = "oauth4webapi";
2321
+ const VERSION = "v3.8.5";
2322
+ USER_AGENT = `${NAME}/${VERSION}`;
2323
+ }
2324
+ function looseInstanceOf(input, expected) {
2325
+ if (input == null) {
2326
+ return false;
2327
+ }
2328
+ try {
2329
+ return input instanceof expected || Object.getPrototypeOf(input)[Symbol.toStringTag] === expected.prototype[Symbol.toStringTag];
2330
+ } catch {
2331
+ return false;
2332
+ }
2333
+ }
2334
+ var ERR_INVALID_ARG_VALUE = "ERR_INVALID_ARG_VALUE";
2335
+ var ERR_INVALID_ARG_TYPE = "ERR_INVALID_ARG_TYPE";
2336
+ function CodedTypeError(message, code, cause) {
2337
+ const err = new TypeError(message, { cause });
2338
+ Object.assign(err, { code });
2339
+ return err;
2340
+ }
2341
+ var allowInsecureRequests = Symbol();
2342
+ var clockSkew = Symbol();
2343
+ var clockTolerance = Symbol();
2344
+ var customFetch = Symbol();
2345
+ var modifyAssertion = Symbol();
2346
+ var jweDecrypt = Symbol();
2347
+ var jwksCache = Symbol();
2348
+ var encoder = new TextEncoder;
2349
+ var decoder = new TextDecoder;
2350
+ function buf(input) {
2351
+ if (typeof input === "string") {
2352
+ return encoder.encode(input);
2353
+ }
2354
+ return decoder.decode(input);
2355
+ }
2356
+ var encodeBase64Url;
2357
+ if (Uint8Array.prototype.toBase64) {
2358
+ encodeBase64Url = (input) => {
2359
+ if (input instanceof ArrayBuffer) {
2360
+ input = new Uint8Array(input);
2361
+ }
2362
+ return input.toBase64({ alphabet: "base64url", omitPadding: true });
2363
+ };
2364
+ } else {
2365
+ const CHUNK_SIZE = 32768;
2366
+ encodeBase64Url = (input) => {
2367
+ if (input instanceof ArrayBuffer) {
2368
+ input = new Uint8Array(input);
2369
+ }
2370
+ const arr = [];
2371
+ for (let i = 0;i < input.byteLength; i += CHUNK_SIZE) {
2372
+ arr.push(String.fromCharCode.apply(null, input.subarray(i, i + CHUNK_SIZE)));
2373
+ }
2374
+ return btoa(arr.join("")).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
2375
+ };
2376
+ }
2377
+ var decodeBase64Url;
2378
+ if (Uint8Array.fromBase64) {
2379
+ decodeBase64Url = (input) => {
2380
+ try {
2381
+ return Uint8Array.fromBase64(input, { alphabet: "base64url" });
2382
+ } catch (cause) {
2383
+ throw CodedTypeError("The input to be decoded is not correctly encoded.", ERR_INVALID_ARG_VALUE, cause);
2384
+ }
2385
+ };
2386
+ } else {
2387
+ decodeBase64Url = (input) => {
2388
+ try {
2389
+ const binary = atob(input.replace(/-/g, "+").replace(/_/g, "/").replace(/\s/g, ""));
2390
+ const bytes = new Uint8Array(binary.length);
2391
+ for (let i = 0;i < binary.length; i++) {
2392
+ bytes[i] = binary.charCodeAt(i);
2393
+ }
2394
+ return bytes;
2395
+ } catch (cause) {
2396
+ throw CodedTypeError("The input to be decoded is not correctly encoded.", ERR_INVALID_ARG_VALUE, cause);
2397
+ }
2398
+ };
2399
+ }
2400
+ function b64u(input) {
2401
+ if (typeof input === "string") {
2402
+ return decodeBase64Url(input);
2403
+ }
2404
+ return encodeBase64Url(input);
2405
+ }
2406
+
2407
+ class UnsupportedOperationError extends Error {
2408
+ code;
2409
+ constructor(message, options) {
2410
+ super(message, options);
2411
+ this.name = this.constructor.name;
2412
+ this.code = UNSUPPORTED_OPERATION;
2413
+ Error.captureStackTrace?.(this, this.constructor);
2414
+ }
2415
+ }
2416
+
2417
+ class OperationProcessingError extends Error {
2418
+ code;
2419
+ constructor(message, options) {
2420
+ super(message, options);
2421
+ this.name = this.constructor.name;
2422
+ if (options?.code) {
2423
+ this.code = options?.code;
2424
+ }
2425
+ Error.captureStackTrace?.(this, this.constructor);
2426
+ }
2427
+ }
2428
+ function OPE(message, code, cause) {
2429
+ return new OperationProcessingError(message, { code, cause });
2430
+ }
2431
+ async function calculateJwkThumbprint(jwk) {
2432
+ let components;
2433
+ switch (jwk.kty) {
2434
+ case "EC":
2435
+ components = {
2436
+ crv: jwk.crv,
2437
+ kty: jwk.kty,
2438
+ x: jwk.x,
2439
+ y: jwk.y
2440
+ };
2441
+ break;
2442
+ case "OKP":
2443
+ components = {
2444
+ crv: jwk.crv,
2445
+ kty: jwk.kty,
2446
+ x: jwk.x
2447
+ };
2448
+ break;
2449
+ case "AKP":
2450
+ components = {
2451
+ alg: jwk.alg,
2452
+ kty: jwk.kty,
2453
+ pub: jwk.pub
2454
+ };
2455
+ break;
2456
+ case "RSA":
2457
+ components = {
2458
+ e: jwk.e,
2459
+ kty: jwk.kty,
2460
+ n: jwk.n
2461
+ };
2462
+ break;
2463
+ default:
2464
+ throw new UnsupportedOperationError("unsupported JWK key type", { cause: jwk });
2465
+ }
2466
+ return b64u(await crypto.subtle.digest("SHA-256", buf(JSON.stringify(components))));
2467
+ }
2468
+ function assertCryptoKey(key, it) {
2469
+ if (!(key instanceof CryptoKey)) {
2470
+ throw CodedTypeError(`${it} must be a CryptoKey`, ERR_INVALID_ARG_TYPE);
2471
+ }
2472
+ }
2473
+ function assertPrivateKey(key, it) {
2474
+ assertCryptoKey(key, it);
2475
+ if (key.type !== "private") {
2476
+ throw CodedTypeError(`${it} must be a private CryptoKey`, ERR_INVALID_ARG_VALUE);
2477
+ }
2478
+ }
2479
+ function assertPublicKey(key, it) {
2480
+ assertCryptoKey(key, it);
2481
+ if (key.type !== "public") {
2482
+ throw CodedTypeError(`${it} must be a public CryptoKey`, ERR_INVALID_ARG_VALUE);
2483
+ }
2484
+ }
2485
+ function normalizeTyp(value) {
2486
+ return value.toLowerCase().replace(/^application\//, "");
2487
+ }
2488
+ function isJsonObject(input) {
2489
+ if (input === null || typeof input !== "object" || Array.isArray(input)) {
2490
+ return false;
2491
+ }
2492
+ return true;
2493
+ }
2494
+ function prepareHeaders(input) {
2495
+ if (looseInstanceOf(input, Headers)) {
2496
+ input = Object.fromEntries(input.entries());
2497
+ }
2498
+ const headers = new Headers(input ?? {});
2499
+ if (USER_AGENT && !headers.has("user-agent")) {
2500
+ headers.set("user-agent", USER_AGENT);
2501
+ }
2502
+ if (headers.has("authorization")) {
2503
+ throw CodedTypeError('"options.headers" must not include the "authorization" header name', ERR_INVALID_ARG_VALUE);
2504
+ }
2505
+ return headers;
2506
+ }
2507
+ function signal(url, value) {
2508
+ if (value !== undefined) {
2509
+ if (typeof value === "function") {
2510
+ value = value(url.href);
2511
+ }
2512
+ if (!(value instanceof AbortSignal)) {
2513
+ throw CodedTypeError('"options.signal" must return or be an instance of AbortSignal', ERR_INVALID_ARG_TYPE);
2514
+ }
2515
+ return value;
2516
+ }
2517
+ return;
2518
+ }
2519
+ function replaceDoubleSlash(pathname) {
2520
+ if (pathname.includes("//")) {
2521
+ return pathname.replace("//", "/");
2522
+ }
2523
+ return pathname;
2524
+ }
2525
+ function prependWellKnown(url, wellKnown, allowTerminatingSlash = false) {
2526
+ if (url.pathname === "/") {
2527
+ url.pathname = wellKnown;
2528
+ } else {
2529
+ url.pathname = replaceDoubleSlash(`${wellKnown}/${allowTerminatingSlash ? url.pathname : url.pathname.replace(/(\/)$/, "")}`);
2530
+ }
2531
+ return url;
2532
+ }
2533
+ function appendWellKnown(url, wellKnown) {
2534
+ url.pathname = replaceDoubleSlash(`${url.pathname}/${wellKnown}`);
2535
+ return url;
2536
+ }
2537
+ async function performDiscovery(input, urlName, transform, options) {
2538
+ if (!(input instanceof URL)) {
2539
+ throw CodedTypeError(`"${urlName}" must be an instance of URL`, ERR_INVALID_ARG_TYPE);
2540
+ }
2541
+ checkProtocol(input, options?.[allowInsecureRequests] !== true);
2542
+ const url = transform(new URL(input.href));
2543
+ const headers = prepareHeaders(options?.headers);
2544
+ headers.set("accept", "application/json");
2545
+ return (options?.[customFetch] || fetch)(url.href, {
2546
+ body: undefined,
2547
+ headers: Object.fromEntries(headers.entries()),
2548
+ method: "GET",
2549
+ redirect: "manual",
2550
+ signal: signal(url, options?.signal)
2551
+ });
2552
+ }
2553
+ async function discoveryRequest(issuerIdentifier, options) {
2554
+ return performDiscovery(issuerIdentifier, "issuerIdentifier", (url) => {
2555
+ switch (options?.algorithm) {
2556
+ case undefined:
2557
+ case "oidc":
2558
+ appendWellKnown(url, ".well-known/openid-configuration");
2559
+ break;
2560
+ case "oauth2":
2561
+ prependWellKnown(url, ".well-known/oauth-authorization-server");
2562
+ break;
2563
+ default:
2564
+ throw CodedTypeError('"options.algorithm" must be "oidc" (default), or "oauth2"', ERR_INVALID_ARG_VALUE);
2565
+ }
2566
+ return url;
2567
+ }, options);
2568
+ }
2569
+ function assertString(input, it, code, cause) {
2570
+ try {
2571
+ if (typeof input !== "string") {
2572
+ throw CodedTypeError(`${it} must be a string`, ERR_INVALID_ARG_TYPE, cause);
2573
+ }
2574
+ if (input.length === 0) {
2575
+ throw CodedTypeError(`${it} must not be empty`, ERR_INVALID_ARG_VALUE, cause);
2576
+ }
2577
+ } catch (err) {
2578
+ if (code) {
2579
+ throw OPE(err.message, code, cause);
2580
+ }
2581
+ throw err;
2582
+ }
2583
+ }
2584
+ async function processDiscoveryResponse(expectedIssuerIdentifier, response) {
2585
+ const expected = expectedIssuerIdentifier;
2586
+ if (!(expected instanceof URL) && expected !== _nodiscoverycheck) {
2587
+ throw CodedTypeError('"expectedIssuerIdentifier" must be an instance of URL', ERR_INVALID_ARG_TYPE);
2588
+ }
2589
+ if (!looseInstanceOf(response, Response)) {
2590
+ throw CodedTypeError('"response" must be an instance of Response', ERR_INVALID_ARG_TYPE);
2591
+ }
2592
+ if (response.status !== 200) {
2593
+ throw OPE('"response" is not a conform Authorization Server Metadata response (unexpected HTTP status code)', RESPONSE_IS_NOT_CONFORM, response);
2594
+ }
2595
+ assertReadableResponse(response);
2596
+ const json = await getResponseJsonBody(response);
2597
+ assertString(json.issuer, '"response" body "issuer" property', INVALID_RESPONSE, { body: json });
2598
+ if (expected !== _nodiscoverycheck && new URL(json.issuer).href !== expected.href) {
2599
+ throw OPE('"response" body "issuer" property does not match the expected value', JSON_ATTRIBUTE_COMPARISON, { expected: expected.href, body: json, attribute: "issuer" });
2600
+ }
2601
+ return json;
2602
+ }
2603
+ function assertApplicationJson(response) {
2604
+ assertContentType(response, "application/json");
2605
+ }
2606
+ function notJson(response, ...types) {
2607
+ let msg = '"response" content-type must be ';
2608
+ if (types.length > 2) {
2609
+ const last = types.pop();
2610
+ msg += `${types.join(", ")}, or ${last}`;
2611
+ } else if (types.length === 2) {
2612
+ msg += `${types[0]} or ${types[1]}`;
2613
+ } else {
2614
+ msg += types[0];
2615
+ }
2616
+ return OPE(msg, RESPONSE_IS_NOT_JSON, response);
2617
+ }
2618
+ function assertContentTypes(response, ...types) {
2619
+ if (!types.includes(getContentType(response))) {
2620
+ throw notJson(response, ...types);
2621
+ }
2622
+ }
2623
+ function assertContentType(response, contentType) {
2624
+ if (getContentType(response) !== contentType) {
2625
+ throw notJson(response, contentType);
2626
+ }
2627
+ }
2628
+ function randomBytes2() {
2629
+ return b64u(crypto.getRandomValues(new Uint8Array(32)));
2630
+ }
2631
+ function psAlg(key) {
2632
+ switch (key.algorithm.hash.name) {
2633
+ case "SHA-256":
2634
+ return "PS256";
2635
+ case "SHA-384":
2636
+ return "PS384";
2637
+ case "SHA-512":
2638
+ return "PS512";
2639
+ default:
2640
+ throw new UnsupportedOperationError("unsupported RsaHashedKeyAlgorithm hash name", {
2641
+ cause: key
2642
+ });
2643
+ }
2644
+ }
2645
+ function rsAlg(key) {
2646
+ switch (key.algorithm.hash.name) {
2647
+ case "SHA-256":
2648
+ return "RS256";
2649
+ case "SHA-384":
2650
+ return "RS384";
2651
+ case "SHA-512":
2652
+ return "RS512";
2653
+ default:
2654
+ throw new UnsupportedOperationError("unsupported RsaHashedKeyAlgorithm hash name", {
2655
+ cause: key
2656
+ });
2657
+ }
2658
+ }
2659
+ function esAlg(key) {
2660
+ switch (key.algorithm.namedCurve) {
2661
+ case "P-256":
2662
+ return "ES256";
2663
+ case "P-384":
2664
+ return "ES384";
2665
+ case "P-521":
2666
+ return "ES512";
2667
+ default:
2668
+ throw new UnsupportedOperationError("unsupported EcKeyAlgorithm namedCurve", { cause: key });
2669
+ }
2670
+ }
2671
+ function keyToJws(key) {
2672
+ switch (key.algorithm.name) {
2673
+ case "RSA-PSS":
2674
+ return psAlg(key);
2675
+ case "RSASSA-PKCS1-v1_5":
2676
+ return rsAlg(key);
2677
+ case "ECDSA":
2678
+ return esAlg(key);
2679
+ case "Ed25519":
2680
+ case "ML-DSA-44":
2681
+ case "ML-DSA-65":
2682
+ case "ML-DSA-87":
2683
+ return key.algorithm.name;
2684
+ case "EdDSA":
2685
+ return "Ed25519";
2686
+ default:
2687
+ throw new UnsupportedOperationError("unsupported CryptoKey algorithm name", { cause: key });
2688
+ }
2689
+ }
2690
+ function getClockSkew(client) {
2691
+ const skew = client?.[clockSkew];
2692
+ return typeof skew === "number" && Number.isFinite(skew) ? skew : 0;
2693
+ }
2694
+ function getClockTolerance(client) {
2695
+ const tolerance = client?.[clockTolerance];
2696
+ return typeof tolerance === "number" && Number.isFinite(tolerance) && Math.sign(tolerance) !== -1 ? tolerance : 30;
2697
+ }
2698
+ function epochTime() {
2699
+ return Math.floor(Date.now() / 1000);
2700
+ }
2701
+ function assertAs(as) {
2702
+ if (typeof as !== "object" || as === null) {
2703
+ throw CodedTypeError('"as" must be an object', ERR_INVALID_ARG_TYPE);
2704
+ }
2705
+ assertString(as.issuer, '"as.issuer"');
2706
+ }
2707
+ async function signJwt(header, payload, key) {
2708
+ if (!key.usages.includes("sign")) {
2709
+ throw CodedTypeError('CryptoKey instances used for signing assertions must include "sign" in their "usages"', ERR_INVALID_ARG_VALUE);
2710
+ }
2711
+ const input = `${b64u(buf(JSON.stringify(header)))}.${b64u(buf(JSON.stringify(payload)))}`;
2712
+ const signature = b64u(await crypto.subtle.sign(keyToSubtle(key), key, buf(input)));
2713
+ return `${input}.${signature}`;
2714
+ }
2715
+ var jwkCache;
2716
+ async function getSetPublicJwkCache(key, alg) {
2717
+ const { kty, e, n, x, y, crv, pub } = await crypto.subtle.exportKey("jwk", key);
2718
+ const jwk = { kty, e, n, x, y, crv, pub };
2719
+ if (kty === "AKP")
2720
+ jwk.alg = alg;
2721
+ jwkCache.set(key, jwk);
2722
+ return jwk;
2723
+ }
2724
+ async function publicJwk(key, alg) {
2725
+ jwkCache ||= new WeakMap;
2726
+ return jwkCache.get(key) || getSetPublicJwkCache(key, alg);
2727
+ }
2728
+ var URLParse = URL.parse ? (url, base) => URL.parse(url, base) : (url, base) => {
2729
+ try {
2730
+ return new URL(url, base);
2731
+ } catch {
2732
+ return null;
2733
+ }
2734
+ };
2735
+ function checkProtocol(url, enforceHttps) {
2736
+ if (enforceHttps && url.protocol !== "https:") {
2737
+ throw OPE("only requests to HTTPS are allowed", HTTP_REQUEST_FORBIDDEN, url);
2738
+ }
2739
+ if (url.protocol !== "https:" && url.protocol !== "http:") {
2740
+ throw OPE("only HTTP and HTTPS requests are allowed", REQUEST_PROTOCOL_FORBIDDEN, url);
2741
+ }
2742
+ }
2743
+ function validateEndpoint(value, endpoint, useMtlsAlias, enforceHttps) {
2744
+ let url;
2745
+ if (typeof value !== "string" || !(url = URLParse(value))) {
2746
+ throw OPE(`authorization server metadata does not contain a valid ${useMtlsAlias ? `"as.mtls_endpoint_aliases.${endpoint}"` : `"as.${endpoint}"`}`, value === undefined ? MISSING_SERVER_METADATA : INVALID_SERVER_METADATA, { attribute: useMtlsAlias ? `mtls_endpoint_aliases.${endpoint}` : endpoint });
2747
+ }
2748
+ checkProtocol(url, enforceHttps);
2749
+ return url;
2750
+ }
2751
+ function resolveEndpoint(as, endpoint, useMtlsAlias, enforceHttps) {
2752
+ if (useMtlsAlias && as.mtls_endpoint_aliases && endpoint in as.mtls_endpoint_aliases) {
2753
+ return validateEndpoint(as.mtls_endpoint_aliases[endpoint], endpoint, useMtlsAlias, enforceHttps);
2754
+ }
2755
+ return validateEndpoint(as[endpoint], endpoint, useMtlsAlias, enforceHttps);
2756
+ }
2757
+ class DPoPHandler {
2758
+ #header;
2759
+ #privateKey;
2760
+ #publicKey;
2761
+ #clockSkew;
2762
+ #modifyAssertion;
2763
+ #map;
2764
+ #jkt;
2765
+ constructor(client, keyPair, options) {
2766
+ assertPrivateKey(keyPair?.privateKey, '"DPoP.privateKey"');
2767
+ assertPublicKey(keyPair?.publicKey, '"DPoP.publicKey"');
2768
+ if (!keyPair.publicKey.extractable) {
2769
+ throw CodedTypeError('"DPoP.publicKey.extractable" must be true', ERR_INVALID_ARG_VALUE);
2770
+ }
2771
+ this.#modifyAssertion = options?.[modifyAssertion];
2772
+ this.#clockSkew = getClockSkew(client);
2773
+ this.#privateKey = keyPair.privateKey;
2774
+ this.#publicKey = keyPair.publicKey;
2775
+ branded.add(this);
2776
+ }
2777
+ #get(key) {
2778
+ this.#map ||= new Map;
2779
+ let item = this.#map.get(key);
2780
+ if (item) {
2781
+ this.#map.delete(key);
2782
+ this.#map.set(key, item);
2783
+ }
2784
+ return item;
2785
+ }
2786
+ #set(key, val) {
2787
+ this.#map ||= new Map;
2788
+ this.#map.delete(key);
2789
+ if (this.#map.size === 100) {
2790
+ this.#map.delete(this.#map.keys().next().value);
2791
+ }
2792
+ this.#map.set(key, val);
2793
+ }
2794
+ async calculateThumbprint() {
2795
+ if (!this.#jkt) {
2796
+ const jwk = await crypto.subtle.exportKey("jwk", this.#publicKey);
2797
+ this.#jkt ||= await calculateJwkThumbprint(jwk);
2798
+ }
2799
+ return this.#jkt;
2800
+ }
2801
+ async addProof(url, headers, htm, accessToken) {
2802
+ const alg = keyToJws(this.#privateKey);
2803
+ this.#header ||= {
2804
+ alg,
2805
+ typ: "dpop+jwt",
2806
+ jwk: await publicJwk(this.#publicKey, alg)
2807
+ };
2808
+ const nonce = this.#get(url.origin);
2809
+ const now = epochTime() + this.#clockSkew;
2810
+ const payload = {
2811
+ iat: now,
2812
+ jti: randomBytes2(),
2813
+ htm,
2814
+ nonce,
2815
+ htu: `${url.origin}${url.pathname}`,
2816
+ ath: accessToken ? b64u(await crypto.subtle.digest("SHA-256", buf(accessToken))) : undefined
2817
+ };
2818
+ this.#modifyAssertion?.(this.#header, payload);
2819
+ headers.set("dpop", await signJwt(this.#header, payload, this.#privateKey));
2820
+ }
2821
+ cacheNonce(response, url) {
2822
+ try {
2823
+ const nonce = response.headers.get("dpop-nonce");
2824
+ if (nonce) {
2825
+ this.#set(url.origin, nonce);
2826
+ }
2827
+ } catch {}
2828
+ }
2829
+ }
2830
+ var tokenMatch = "[a-zA-Z0-9!#$%&\\'\\*\\+\\-\\.\\^_`\\|~]+";
2831
+ var token68Match = "[a-zA-Z0-9\\-\\._\\~\\+\\/]+={0,2}";
2832
+ var quotedMatch = '"((?:[^"\\\\]|\\\\[\\s\\S])*)"';
2833
+ var quotedParamMatcher = "(" + tokenMatch + ")\\s*=\\s*" + quotedMatch;
2834
+ var paramMatcher = "(" + tokenMatch + ")\\s*=\\s*(" + tokenMatch + ")";
2835
+ var schemeRE = new RegExp("^[,\\s]*(" + tokenMatch + ")");
2836
+ var quotedParamRE = new RegExp("^[,\\s]*" + quotedParamMatcher + "[,\\s]*(.*)");
2837
+ var unquotedParamRE = new RegExp("^[,\\s]*" + paramMatcher + "[,\\s]*(.*)");
2838
+ var token68ParamRE = new RegExp("^(" + token68Match + ")(?:$|[,\\s])(.*)");
2839
+ var jwksMap;
2840
+ function setJwksCache(as, jwks, uat, cache) {
2841
+ jwksMap ||= new WeakMap;
2842
+ jwksMap.set(as, {
2843
+ jwks,
2844
+ uat,
2845
+ get age() {
2846
+ return epochTime() - this.uat;
2847
+ }
2848
+ });
2849
+ if (cache) {
2850
+ Object.assign(cache, { jwks: structuredClone(jwks), uat });
2851
+ }
2852
+ }
2853
+ function isFreshJwksCache(input) {
2854
+ if (typeof input !== "object" || input === null) {
2855
+ return false;
2856
+ }
2857
+ if (!("uat" in input) || typeof input.uat !== "number" || epochTime() - input.uat >= 300) {
2858
+ return false;
2859
+ }
2860
+ if (!("jwks" in input) || !isJsonObject(input.jwks) || !Array.isArray(input.jwks.keys) || !Array.prototype.every.call(input.jwks.keys, isJsonObject)) {
2861
+ return false;
2862
+ }
2863
+ return true;
2864
+ }
2865
+ function clearJwksCache(as, cache) {
2866
+ jwksMap?.delete(as);
2867
+ delete cache?.jwks;
2868
+ delete cache?.uat;
2869
+ }
2870
+ async function getPublicSigKeyFromIssuerJwksUri(as, options, header) {
2871
+ const { alg, kid } = header;
2872
+ checkSupportedJwsAlg(header);
2873
+ if (!jwksMap?.has(as) && isFreshJwksCache(options?.[jwksCache])) {
2874
+ setJwksCache(as, options?.[jwksCache].jwks, options?.[jwksCache].uat);
2875
+ }
2876
+ let jwks;
2877
+ let age;
2878
+ if (jwksMap?.has(as)) {
2879
+ ({ jwks, age } = jwksMap.get(as));
2880
+ if (age >= 300) {
2881
+ clearJwksCache(as, options?.[jwksCache]);
2882
+ return getPublicSigKeyFromIssuerJwksUri(as, options, header);
2883
+ }
2884
+ } else {
2885
+ jwks = await jwksRequest(as, options).then(processJwksResponse);
2886
+ age = 0;
2887
+ setJwksCache(as, jwks, epochTime(), options?.[jwksCache]);
2888
+ }
2889
+ let kty;
2890
+ switch (alg.slice(0, 2)) {
2891
+ case "RS":
2892
+ case "PS":
2893
+ kty = "RSA";
2894
+ break;
2895
+ case "ES":
2896
+ kty = "EC";
2897
+ break;
2898
+ case "Ed":
2899
+ kty = "OKP";
2900
+ break;
2901
+ case "ML":
2902
+ kty = "AKP";
2903
+ break;
2904
+ default:
2905
+ throw new UnsupportedOperationError("unsupported JWS algorithm", { cause: { alg } });
2906
+ }
2907
+ const candidates = jwks.keys.filter((jwk2) => {
2908
+ if (jwk2.kty !== kty) {
2909
+ return false;
2910
+ }
2911
+ if (kid !== undefined && kid !== jwk2.kid) {
2912
+ return false;
2913
+ }
2914
+ if (jwk2.alg !== undefined && alg !== jwk2.alg) {
2915
+ return false;
2916
+ }
2917
+ if (jwk2.use !== undefined && jwk2.use !== "sig") {
2918
+ return false;
2919
+ }
2920
+ if (jwk2.key_ops?.includes("verify") === false) {
2921
+ return false;
2922
+ }
2923
+ switch (true) {
2924
+ case (alg === "ES256" && jwk2.crv !== "P-256"):
2925
+ case (alg === "ES384" && jwk2.crv !== "P-384"):
2926
+ case (alg === "ES512" && jwk2.crv !== "P-521"):
2927
+ case (alg === "Ed25519" && jwk2.crv !== "Ed25519"):
2928
+ case (alg === "EdDSA" && jwk2.crv !== "Ed25519"):
2929
+ return false;
2930
+ }
2931
+ return true;
2932
+ });
2933
+ const { 0: jwk, length } = candidates;
2934
+ if (!length) {
2935
+ if (age >= 60) {
2936
+ clearJwksCache(as, options?.[jwksCache]);
2937
+ return getPublicSigKeyFromIssuerJwksUri(as, options, header);
2938
+ }
2939
+ throw OPE("error when selecting a JWT verification key, no applicable keys found", KEY_SELECTION, { header, candidates, jwks_uri: new URL(as.jwks_uri) });
2940
+ }
2941
+ if (length !== 1) {
2942
+ throw OPE('error when selecting a JWT verification key, multiple applicable keys found, a "kid" JWT Header Parameter is required', KEY_SELECTION, { header, candidates, jwks_uri: new URL(as.jwks_uri) });
2943
+ }
2944
+ return importJwk(alg, jwk);
2945
+ }
2946
+ var skipSubjectCheck = Symbol();
2947
+ function getContentType(input) {
2948
+ return input.headers.get("content-type")?.split(";")[0];
2949
+ }
2950
+ var idTokenClaims = new WeakMap;
2951
+ var jwtRefs = new WeakMap;
2952
+ function validateAudience(expected, result) {
2953
+ if (Array.isArray(result.claims.aud)) {
2954
+ if (!result.claims.aud.includes(expected)) {
2955
+ throw OPE('unexpected JWT "aud" (audience) claim value', JWT_CLAIM_COMPARISON, {
2956
+ expected,
2957
+ claims: result.claims,
2958
+ claim: "aud"
2959
+ });
2960
+ }
2961
+ } else if (result.claims.aud !== expected) {
2962
+ throw OPE('unexpected JWT "aud" (audience) claim value', JWT_CLAIM_COMPARISON, {
2963
+ expected,
2964
+ claims: result.claims,
2965
+ claim: "aud"
2966
+ });
2967
+ }
2968
+ return result;
2969
+ }
2970
+ function validateIssuer(as, result) {
2971
+ const expected = as[_expectedIssuer]?.(result) ?? as.issuer;
2972
+ if (result.claims.iss !== expected) {
2973
+ throw OPE('unexpected JWT "iss" (issuer) claim value', JWT_CLAIM_COMPARISON, {
2974
+ expected,
2975
+ claims: result.claims,
2976
+ claim: "iss"
2977
+ });
2978
+ }
2979
+ return result;
2980
+ }
2981
+ var branded = new WeakSet;
2982
+ var nopkce = Symbol();
2983
+ var jwtClaimNames = {
2984
+ aud: "audience",
2985
+ c_hash: "code hash",
2986
+ client_id: "client id",
2987
+ exp: "expiration time",
2988
+ iat: "issued at",
2989
+ iss: "issuer",
2990
+ jti: "jwt id",
2991
+ nonce: "nonce",
2992
+ s_hash: "state hash",
2993
+ sub: "subject",
2994
+ ath: "access token hash",
2995
+ htm: "http method",
2996
+ htu: "http uri",
2997
+ cnf: "confirmation",
2998
+ auth_time: "authentication time"
2999
+ };
3000
+ function validatePresence(required, result) {
3001
+ for (const claim of required) {
3002
+ if (result.claims[claim] === undefined) {
3003
+ throw OPE(`JWT "${claim}" (${jwtClaimNames[claim]}) claim missing`, INVALID_RESPONSE, {
3004
+ claims: result.claims
3005
+ });
3006
+ }
3007
+ }
3008
+ return result;
3009
+ }
3010
+ var expectNoNonce = Symbol();
3011
+ var skipAuthTimeCheck = Symbol();
3012
+ var UNSUPPORTED_OPERATION = "OAUTH_UNSUPPORTED_OPERATION";
3013
+ var PARSE_ERROR = "OAUTH_PARSE_ERROR";
3014
+ var INVALID_RESPONSE = "OAUTH_INVALID_RESPONSE";
3015
+ var INVALID_REQUEST = "OAUTH_INVALID_REQUEST";
3016
+ var RESPONSE_IS_NOT_JSON = "OAUTH_RESPONSE_IS_NOT_JSON";
3017
+ var RESPONSE_IS_NOT_CONFORM = "OAUTH_RESPONSE_IS_NOT_CONFORM";
3018
+ var HTTP_REQUEST_FORBIDDEN = "OAUTH_HTTP_REQUEST_FORBIDDEN";
3019
+ var REQUEST_PROTOCOL_FORBIDDEN = "OAUTH_REQUEST_PROTOCOL_FORBIDDEN";
3020
+ var JWT_TIMESTAMP_CHECK = "OAUTH_JWT_TIMESTAMP_CHECK_FAILED";
3021
+ var JWT_CLAIM_COMPARISON = "OAUTH_JWT_CLAIM_COMPARISON_FAILED";
3022
+ var JSON_ATTRIBUTE_COMPARISON = "OAUTH_JSON_ATTRIBUTE_COMPARISON_FAILED";
3023
+ var KEY_SELECTION = "OAUTH_KEY_SELECTION_FAILED";
3024
+ var MISSING_SERVER_METADATA = "OAUTH_MISSING_SERVER_METADATA";
3025
+ var INVALID_SERVER_METADATA = "OAUTH_INVALID_SERVER_METADATA";
3026
+ function checkJwtType(expected, result) {
3027
+ if (typeof result.header.typ !== "string" || normalizeTyp(result.header.typ) !== expected) {
3028
+ throw OPE('unexpected JWT "typ" header parameter value', INVALID_RESPONSE, {
3029
+ header: result.header
3030
+ });
3031
+ }
3032
+ return result;
3033
+ }
3034
+ function assertReadableResponse(response) {
3035
+ if (response.bodyUsed) {
3036
+ throw CodedTypeError('"response" body has been used already', ERR_INVALID_ARG_VALUE);
3037
+ }
3038
+ }
3039
+ async function jwksRequest(as, options) {
3040
+ assertAs(as);
3041
+ const url = resolveEndpoint(as, "jwks_uri", false, options?.[allowInsecureRequests] !== true);
3042
+ const headers = prepareHeaders(options?.headers);
3043
+ headers.set("accept", "application/json");
3044
+ headers.append("accept", "application/jwk-set+json");
3045
+ return (options?.[customFetch] || fetch)(url.href, {
3046
+ body: undefined,
3047
+ headers: Object.fromEntries(headers.entries()),
3048
+ method: "GET",
3049
+ redirect: "manual",
3050
+ signal: signal(url, options?.signal)
3051
+ });
3052
+ }
3053
+ async function processJwksResponse(response) {
3054
+ if (!looseInstanceOf(response, Response)) {
3055
+ throw CodedTypeError('"response" must be an instance of Response', ERR_INVALID_ARG_TYPE);
3056
+ }
3057
+ if (response.status !== 200) {
3058
+ throw OPE('"response" is not a conform JSON Web Key Set response (unexpected HTTP status code)', RESPONSE_IS_NOT_CONFORM, response);
3059
+ }
3060
+ assertReadableResponse(response);
3061
+ const json = await getResponseJsonBody(response, (response2) => assertContentTypes(response2, "application/json", "application/jwk-set+json"));
3062
+ if (!Array.isArray(json.keys)) {
3063
+ throw OPE('"response" body "keys" property must be an array', INVALID_RESPONSE, { body: json });
3064
+ }
3065
+ if (!Array.prototype.every.call(json.keys, isJsonObject)) {
3066
+ throw OPE('"response" body "keys" property members must be JWK formatted objects', INVALID_RESPONSE, { body: json });
3067
+ }
3068
+ return json;
3069
+ }
3070
+ function supported(alg) {
3071
+ switch (alg) {
3072
+ case "PS256":
3073
+ case "ES256":
3074
+ case "RS256":
3075
+ case "PS384":
3076
+ case "ES384":
3077
+ case "RS384":
3078
+ case "PS512":
3079
+ case "ES512":
3080
+ case "RS512":
3081
+ case "Ed25519":
3082
+ case "EdDSA":
3083
+ case "ML-DSA-44":
3084
+ case "ML-DSA-65":
3085
+ case "ML-DSA-87":
3086
+ return true;
3087
+ default:
3088
+ return false;
3089
+ }
3090
+ }
3091
+ function checkSupportedJwsAlg(header) {
3092
+ if (!supported(header.alg)) {
3093
+ throw new UnsupportedOperationError('unsupported JWS "alg" identifier', {
3094
+ cause: { alg: header.alg }
3095
+ });
3096
+ }
3097
+ }
3098
+ function checkRsaKeyAlgorithm(key) {
3099
+ const { algorithm } = key;
3100
+ if (typeof algorithm.modulusLength !== "number" || algorithm.modulusLength < 2048) {
3101
+ throw new UnsupportedOperationError(`unsupported ${algorithm.name} modulusLength`, {
3102
+ cause: key
3103
+ });
3104
+ }
3105
+ }
3106
+ function ecdsaHashName(key) {
3107
+ const { algorithm } = key;
3108
+ switch (algorithm.namedCurve) {
3109
+ case "P-256":
3110
+ return "SHA-256";
3111
+ case "P-384":
3112
+ return "SHA-384";
3113
+ case "P-521":
3114
+ return "SHA-512";
3115
+ default:
3116
+ throw new UnsupportedOperationError("unsupported ECDSA namedCurve", { cause: key });
3117
+ }
3118
+ }
3119
+ function keyToSubtle(key) {
3120
+ switch (key.algorithm.name) {
3121
+ case "ECDSA":
3122
+ return {
3123
+ name: key.algorithm.name,
3124
+ hash: ecdsaHashName(key)
3125
+ };
3126
+ case "RSA-PSS": {
3127
+ checkRsaKeyAlgorithm(key);
3128
+ switch (key.algorithm.hash.name) {
3129
+ case "SHA-256":
3130
+ case "SHA-384":
3131
+ case "SHA-512":
3132
+ return {
3133
+ name: key.algorithm.name,
3134
+ saltLength: parseInt(key.algorithm.hash.name.slice(-3), 10) >> 3
3135
+ };
3136
+ default:
3137
+ throw new UnsupportedOperationError("unsupported RSA-PSS hash name", { cause: key });
3138
+ }
3139
+ }
3140
+ case "RSASSA-PKCS1-v1_5":
3141
+ checkRsaKeyAlgorithm(key);
3142
+ return key.algorithm.name;
3143
+ case "ML-DSA-44":
3144
+ case "ML-DSA-65":
3145
+ case "ML-DSA-87":
3146
+ case "Ed25519":
3147
+ return key.algorithm.name;
3148
+ }
3149
+ throw new UnsupportedOperationError("unsupported CryptoKey algorithm name", { cause: key });
3150
+ }
3151
+ async function validateJwsSignature(protectedHeader, payload, key, signature) {
3152
+ const data = buf(`${protectedHeader}.${payload}`);
3153
+ const algorithm = keyToSubtle(key);
3154
+ const verified = await crypto.subtle.verify(algorithm, key, signature, data);
3155
+ if (!verified) {
3156
+ throw OPE("JWT signature verification failed", INVALID_RESPONSE, {
3157
+ key,
3158
+ data,
3159
+ signature,
3160
+ algorithm
3161
+ });
3162
+ }
3163
+ }
3164
+ async function validateJwt(jws, checkAlg, clockSkew2, clockTolerance2, decryptJwt) {
3165
+ let { 0: protectedHeader, 1: payload, length } = jws.split(".");
3166
+ if (length === 5) {
3167
+ if (decryptJwt !== undefined) {
3168
+ jws = await decryptJwt(jws);
3169
+ ({ 0: protectedHeader, 1: payload, length } = jws.split("."));
3170
+ } else {
3171
+ throw new UnsupportedOperationError("JWE decryption is not configured", { cause: jws });
3172
+ }
3173
+ }
3174
+ if (length !== 3) {
3175
+ throw OPE("Invalid JWT", INVALID_RESPONSE, jws);
3176
+ }
3177
+ let header;
3178
+ try {
3179
+ header = JSON.parse(buf(b64u(protectedHeader)));
3180
+ } catch (cause) {
3181
+ throw OPE("failed to parse JWT Header body as base64url encoded JSON", PARSE_ERROR, cause);
3182
+ }
3183
+ if (!isJsonObject(header)) {
3184
+ throw OPE("JWT Header must be a top level object", INVALID_RESPONSE, jws);
3185
+ }
3186
+ checkAlg(header);
3187
+ if (header.crit !== undefined) {
3188
+ throw new UnsupportedOperationError('no JWT "crit" header parameter extensions are supported', {
3189
+ cause: { header }
3190
+ });
3191
+ }
3192
+ let claims;
3193
+ try {
3194
+ claims = JSON.parse(buf(b64u(payload)));
3195
+ } catch (cause) {
3196
+ throw OPE("failed to parse JWT Payload body as base64url encoded JSON", PARSE_ERROR, cause);
3197
+ }
3198
+ if (!isJsonObject(claims)) {
3199
+ throw OPE("JWT Payload must be a top level object", INVALID_RESPONSE, jws);
3200
+ }
3201
+ const now = epochTime() + clockSkew2;
3202
+ if (claims.exp !== undefined) {
3203
+ if (typeof claims.exp !== "number") {
3204
+ throw OPE('unexpected JWT "exp" (expiration time) claim type', INVALID_RESPONSE, { claims });
3205
+ }
3206
+ if (claims.exp <= now - clockTolerance2) {
3207
+ throw OPE('unexpected JWT "exp" (expiration time) claim value, expiration is past current timestamp', JWT_TIMESTAMP_CHECK, { claims, now, tolerance: clockTolerance2, claim: "exp" });
3208
+ }
3209
+ }
3210
+ if (claims.iat !== undefined) {
3211
+ if (typeof claims.iat !== "number") {
3212
+ throw OPE('unexpected JWT "iat" (issued at) claim type', INVALID_RESPONSE, { claims });
3213
+ }
3214
+ }
3215
+ if (claims.iss !== undefined) {
3216
+ if (typeof claims.iss !== "string") {
3217
+ throw OPE('unexpected JWT "iss" (issuer) claim type', INVALID_RESPONSE, { claims });
3218
+ }
3219
+ }
3220
+ if (claims.nbf !== undefined) {
3221
+ if (typeof claims.nbf !== "number") {
3222
+ throw OPE('unexpected JWT "nbf" (not before) claim type', INVALID_RESPONSE, { claims });
3223
+ }
3224
+ if (claims.nbf > now + clockTolerance2) {
3225
+ throw OPE('unexpected JWT "nbf" (not before) claim value', JWT_TIMESTAMP_CHECK, {
3226
+ claims,
3227
+ now,
3228
+ tolerance: clockTolerance2,
3229
+ claim: "nbf"
3230
+ });
3231
+ }
3232
+ }
3233
+ if (claims.aud !== undefined) {
3234
+ if (typeof claims.aud !== "string" && !Array.isArray(claims.aud)) {
3235
+ throw OPE('unexpected JWT "aud" (audience) claim type', INVALID_RESPONSE, { claims });
3236
+ }
3237
+ }
3238
+ return { header, claims, jwt: jws };
3239
+ }
3240
+ function checkSigningAlgorithm(client, issuer, fallback, header) {
3241
+ if (client !== undefined) {
3242
+ if (typeof client === "string" ? header.alg !== client : !client.includes(header.alg)) {
3243
+ throw OPE('unexpected JWT "alg" header parameter', INVALID_RESPONSE, {
3244
+ header,
3245
+ expected: client,
3246
+ reason: "client configuration"
3247
+ });
3248
+ }
3249
+ return;
3250
+ }
3251
+ if (Array.isArray(issuer)) {
3252
+ if (!issuer.includes(header.alg)) {
3253
+ throw OPE('unexpected JWT "alg" header parameter', INVALID_RESPONSE, {
3254
+ header,
3255
+ expected: issuer,
3256
+ reason: "authorization server metadata"
3257
+ });
3258
+ }
3259
+ return;
3260
+ }
3261
+ if (fallback !== undefined) {
3262
+ if (typeof fallback === "string" ? header.alg !== fallback : typeof fallback === "function" ? !fallback(header.alg) : !fallback.includes(header.alg)) {
3263
+ throw OPE('unexpected JWT "alg" header parameter', INVALID_RESPONSE, {
3264
+ header,
3265
+ expected: fallback,
3266
+ reason: "default value"
3267
+ });
3268
+ }
3269
+ return;
3270
+ }
3271
+ throw OPE('missing client or server configuration to verify used JWT "alg" header parameter', undefined, { client, issuer, fallback });
3272
+ }
3273
+ var skipStateCheck = Symbol();
3274
+ var expectNoState = Symbol();
3275
+ function algToSubtle(alg) {
3276
+ switch (alg) {
3277
+ case "PS256":
3278
+ case "PS384":
3279
+ case "PS512":
3280
+ return { name: "RSA-PSS", hash: `SHA-${alg.slice(-3)}` };
3281
+ case "RS256":
3282
+ case "RS384":
3283
+ case "RS512":
3284
+ return { name: "RSASSA-PKCS1-v1_5", hash: `SHA-${alg.slice(-3)}` };
3285
+ case "ES256":
3286
+ case "ES384":
3287
+ return { name: "ECDSA", namedCurve: `P-${alg.slice(-3)}` };
3288
+ case "ES512":
3289
+ return { name: "ECDSA", namedCurve: "P-521" };
3290
+ case "EdDSA":
3291
+ return "Ed25519";
3292
+ case "Ed25519":
3293
+ case "ML-DSA-44":
3294
+ case "ML-DSA-65":
3295
+ case "ML-DSA-87":
3296
+ return alg;
3297
+ default:
3298
+ throw new UnsupportedOperationError("unsupported JWS algorithm", { cause: { alg } });
3299
+ }
3300
+ }
3301
+ async function importJwk(alg, jwk) {
3302
+ const { ext, key_ops, use, ...key } = jwk;
3303
+ return crypto.subtle.importKey("jwk", key, algToSubtle(alg), true, ["verify"]);
3304
+ }
3305
+ function normalizeHtu(htu) {
3306
+ const url = new URL(htu);
3307
+ url.search = "";
3308
+ url.hash = "";
3309
+ return url.href;
3310
+ }
3311
+ async function validateDPoP(request, accessToken, accessTokenClaims, options) {
3312
+ const headerValue = request.headers.get("dpop");
3313
+ if (headerValue === null) {
3314
+ throw OPE("operation indicated DPoP use but the request has no DPoP HTTP Header", INVALID_REQUEST, { headers: request.headers });
3315
+ }
3316
+ if (request.headers.get("authorization")?.toLowerCase().startsWith("dpop ") === false) {
3317
+ throw OPE(`operation indicated DPoP use but the request's Authorization HTTP Header scheme is not DPoP`, INVALID_REQUEST, { headers: request.headers });
3318
+ }
3319
+ if (typeof accessTokenClaims.cnf?.jkt !== "string") {
3320
+ throw OPE("operation indicated DPoP use but the JWT Access Token has no jkt confirmation claim", INVALID_REQUEST, { claims: accessTokenClaims });
3321
+ }
3322
+ const clockSkew2 = getClockSkew(options);
3323
+ const proof = await validateJwt(headerValue, checkSigningAlgorithm.bind(undefined, options?.signingAlgorithms, undefined, supported), clockSkew2, getClockTolerance(options), undefined).then(checkJwtType.bind(undefined, "dpop+jwt")).then(validatePresence.bind(undefined, ["iat", "jti", "ath", "htm", "htu"]));
3324
+ const now = epochTime() + clockSkew2;
3325
+ const diff = Math.abs(now - proof.claims.iat);
3326
+ if (diff > 300) {
3327
+ throw OPE("DPoP Proof iat is not recent enough", JWT_TIMESTAMP_CHECK, {
3328
+ now,
3329
+ claims: proof.claims,
3330
+ claim: "iat"
3331
+ });
3332
+ }
3333
+ if (proof.claims.htm !== request.method) {
3334
+ throw OPE("DPoP Proof htm mismatch", JWT_CLAIM_COMPARISON, {
3335
+ expected: request.method,
3336
+ claims: proof.claims,
3337
+ claim: "htm"
3338
+ });
3339
+ }
3340
+ if (typeof proof.claims.htu !== "string" || normalizeHtu(proof.claims.htu) !== normalizeHtu(request.url)) {
3341
+ throw OPE("DPoP Proof htu mismatch", JWT_CLAIM_COMPARISON, {
3342
+ expected: normalizeHtu(request.url),
3343
+ claims: proof.claims,
3344
+ claim: "htu"
3345
+ });
3346
+ }
3347
+ {
3348
+ const expected = b64u(await crypto.subtle.digest("SHA-256", buf(accessToken)));
3349
+ if (proof.claims.ath !== expected) {
3350
+ throw OPE("DPoP Proof ath mismatch", JWT_CLAIM_COMPARISON, {
3351
+ expected,
3352
+ claims: proof.claims,
3353
+ claim: "ath"
3354
+ });
3355
+ }
3356
+ }
3357
+ {
3358
+ const expected = await calculateJwkThumbprint(proof.header.jwk);
3359
+ if (accessTokenClaims.cnf.jkt !== expected) {
3360
+ throw OPE("JWT Access Token confirmation mismatch", JWT_CLAIM_COMPARISON, {
3361
+ expected,
3362
+ claims: accessTokenClaims,
3363
+ claim: "cnf.jkt"
3364
+ });
3365
+ }
3366
+ }
3367
+ const { 0: protectedHeader, 1: payload, 2: encodedSignature } = headerValue.split(".");
3368
+ const signature = b64u(encodedSignature);
3369
+ const { jwk, alg } = proof.header;
3370
+ if (!jwk) {
3371
+ throw OPE("DPoP Proof is missing the jwk header parameter", INVALID_REQUEST, {
3372
+ header: proof.header
3373
+ });
3374
+ }
3375
+ const key = await importJwk(alg, jwk);
3376
+ if (key.type !== "public") {
3377
+ throw OPE("DPoP Proof jwk header parameter must contain a public key", INVALID_REQUEST, {
3378
+ header: proof.header
3379
+ });
3380
+ }
3381
+ await validateJwsSignature(protectedHeader, payload, key, signature);
3382
+ }
3383
+ async function validateJwtAccessToken(as, request, expectedAudience, options) {
3384
+ assertAs(as);
3385
+ if (!looseInstanceOf(request, Request)) {
3386
+ throw CodedTypeError('"request" must be an instance of Request', ERR_INVALID_ARG_TYPE);
3387
+ }
3388
+ assertString(expectedAudience, '"expectedAudience"');
3389
+ const authorization = request.headers.get("authorization");
3390
+ if (authorization === null) {
3391
+ throw OPE('"request" is missing an Authorization HTTP Header', INVALID_REQUEST, {
3392
+ headers: request.headers
3393
+ });
3394
+ }
3395
+ let { 0: scheme, 1: accessToken, length } = authorization.split(" ");
3396
+ scheme = scheme.toLowerCase();
3397
+ switch (scheme) {
3398
+ case "dpop":
3399
+ case "bearer":
3400
+ break;
3401
+ default:
3402
+ throw new UnsupportedOperationError("unsupported Authorization HTTP Header scheme", {
3403
+ cause: { headers: request.headers }
3404
+ });
3405
+ }
3406
+ if (length !== 2) {
3407
+ throw OPE("invalid Authorization HTTP Header format", INVALID_REQUEST, {
3408
+ headers: request.headers
3409
+ });
3410
+ }
3411
+ const requiredClaims = [
3412
+ "iss",
3413
+ "exp",
3414
+ "aud",
3415
+ "sub",
3416
+ "iat",
3417
+ "jti",
3418
+ "client_id"
3419
+ ];
3420
+ if (options?.requireDPoP || scheme === "dpop" || request.headers.has("dpop")) {
3421
+ requiredClaims.push("cnf");
3422
+ }
3423
+ const { claims, header } = await validateJwt(accessToken, checkSigningAlgorithm.bind(undefined, options?.signingAlgorithms, undefined, supported), getClockSkew(options), getClockTolerance(options), undefined).then(checkJwtType.bind(undefined, "at+jwt")).then(validatePresence.bind(undefined, requiredClaims)).then(validateIssuer.bind(undefined, as)).then(validateAudience.bind(undefined, expectedAudience)).catch(reassignRSCode);
3424
+ for (const claim of ["client_id", "jti", "sub"]) {
3425
+ if (typeof claims[claim] !== "string") {
3426
+ throw OPE(`unexpected JWT "${claim}" claim type`, INVALID_REQUEST, { claims });
3427
+ }
3428
+ }
3429
+ if ("cnf" in claims) {
3430
+ if (!isJsonObject(claims.cnf)) {
3431
+ throw OPE('unexpected JWT "cnf" (confirmation) claim value', INVALID_REQUEST, { claims });
3432
+ }
3433
+ const { 0: cnf, length: length2 } = Object.keys(claims.cnf);
3434
+ if (length2) {
3435
+ if (length2 !== 1) {
3436
+ throw new UnsupportedOperationError("multiple confirmation claims are not supported", {
3437
+ cause: { claims }
3438
+ });
3439
+ }
3440
+ if (cnf !== "jkt") {
3441
+ throw new UnsupportedOperationError("unsupported JWT Confirmation method", {
3442
+ cause: { claims }
3443
+ });
3444
+ }
3445
+ }
3446
+ }
3447
+ const { 0: protectedHeader, 1: payload, 2: encodedSignature } = accessToken.split(".");
3448
+ const signature = b64u(encodedSignature);
3449
+ const key = await getPublicSigKeyFromIssuerJwksUri(as, options, header);
3450
+ await validateJwsSignature(protectedHeader, payload, key, signature);
3451
+ if (options?.requireDPoP || scheme === "dpop" || claims.cnf?.jkt !== undefined || request.headers.has("dpop")) {
3452
+ await validateDPoP(request, accessToken, claims, options).catch(reassignRSCode);
3453
+ }
3454
+ return claims;
3455
+ }
3456
+ function reassignRSCode(err) {
3457
+ if (err instanceof OperationProcessingError && err?.code === INVALID_REQUEST) {
3458
+ err.code = INVALID_RESPONSE;
3459
+ }
3460
+ throw err;
3461
+ }
3462
+ async function getResponseJsonBody(response, check = assertApplicationJson) {
3463
+ let json;
3464
+ try {
3465
+ json = await response.json();
3466
+ } catch (cause) {
3467
+ check(response);
3468
+ throw OPE('failed to parse "response" body as JSON', PARSE_ERROR, cause);
3469
+ }
3470
+ if (!isJsonObject(json)) {
3471
+ throw OPE('"response" body must be a top level object', INVALID_RESPONSE, { body: json });
3472
+ }
3473
+ return json;
3474
+ }
3475
+ var _nodiscoverycheck = Symbol();
3476
+ var _expectedIssuer = Symbol();
3477
+
3478
+ // src/http/jwt.ts
3479
+ function jwtAuthenticate(options) {
3480
+ const principalClaim = options.principalClaim ?? "sub";
3481
+ const domain = options.domain ?? "jwt";
3482
+ const audience = options.audience;
3483
+ let asPromise = null;
3484
+ async function getAuthorizationServer() {
3485
+ if (options.jwksUri) {
3486
+ return {
3487
+ issuer: options.issuer,
3488
+ jwks_uri: options.jwksUri
3489
+ };
3490
+ }
3491
+ const issuerUrl = new URL(options.issuer);
3492
+ const response = await discoveryRequest(issuerUrl);
3493
+ return processDiscoveryResponse(issuerUrl, response);
3494
+ }
3495
+ return async function authenticate(request) {
3496
+ if (!asPromise) {
3497
+ asPromise = getAuthorizationServer();
3498
+ }
3499
+ let as;
3500
+ try {
3501
+ as = await asPromise;
3502
+ } catch (error) {
3503
+ asPromise = null;
3504
+ throw error;
3505
+ }
3506
+ const claims = await validateJwtAccessToken(as, request, audience);
3507
+ const principal = claims[principalClaim] ?? null;
3508
+ return new AuthContext(domain, true, principal, claims);
3509
+ };
3510
+ }
2150
3511
  // src/protocol.ts
2151
3512
  import { Schema as Schema7 } from "@query-farm/apache-arrow";
2152
3513
 
@@ -2341,8 +3702,11 @@ async function dispatchStream(method, params, writer, reader, serverId, requestI
2341
3702
  if (expectedInputSchema && !isProducer && inputBatch.schema !== expectedInputSchema) {
2342
3703
  try {
2343
3704
  inputBatch = conformBatchToSchema(inputBatch, expectedInputSchema);
2344
- } catch {
2345
- throw new TypeError(`Input schema mismatch: expected ${expectedInputSchema}, got ${inputBatch.schema}`);
3705
+ } catch (e) {
3706
+ if (e instanceof TypeError) {
3707
+ throw e;
3708
+ }
3709
+ console.debug?.(`Schema conformance skipped: ${e instanceof Error ? e.message : e}`);
2346
3710
  }
2347
3711
  }
2348
3712
  const out = new OutputCollector(outputSchema, effectiveProducer, serverId, requestId);
@@ -2550,15 +3914,20 @@ export {
2550
3914
  subprocessConnect,
2551
3915
  str,
2552
3916
  pipeConnect,
3917
+ parseResourceMetadataUrl,
2553
3918
  parseDescribeResponse,
3919
+ oauthResourceMetadataToJson,
3920
+ jwtAuthenticate,
2554
3921
  jsonStateSerializer,
2555
3922
  int32,
2556
3923
  int,
2557
3924
  inferParamTypes,
3925
+ httpOAuthMetadata,
2558
3926
  httpIntrospect,
2559
3927
  httpConnect,
2560
3928
  float32,
2561
3929
  float,
3930
+ fetchOAuthMetadata,
2562
3931
  createHttpHandler,
2563
3932
  bytes,
2564
3933
  bool,
@@ -2583,7 +3952,8 @@ export {
2583
3952
  DESCRIBE_VERSION_KEY,
2584
3953
  DESCRIBE_VERSION,
2585
3954
  DESCRIBE_METHOD_NAME,
3955
+ AuthContext,
2586
3956
  ARROW_CONTENT_TYPE
2587
3957
  };
2588
3958
 
2589
- //# debugId=A10C22D56B2874CF64756E2164756E21
3959
+ //# debugId=FCA96ECA4C5D644864756E2164756E21