@broberg/sso 0.18.2 → 0.18.3

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/dist/index.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkFWFXRNDG_cjs = require('./chunk-FWFXRNDG.cjs');
3
+ var chunkCHRCHUZ3_cjs = require('./chunk-CHRCHUZ3.cjs');
4
4
  var fs = require('fs');
5
5
  var http = require('http');
6
6
  var jose = require('jose');
@@ -48,37 +48,37 @@ async function verifyDpopProof(proof, o) {
48
48
  try {
49
49
  header = jose.decodeProtectedHeader(proof);
50
50
  } catch {
51
- throw new chunkFWFXRNDG_cjs.SsoError("DPoP proof is not a JWS");
51
+ throw new chunkCHRCHUZ3_cjs.SsoError("DPoP proof is not a JWS");
52
52
  }
53
- if (header.typ !== "dpop+jwt") throw new chunkFWFXRNDG_cjs.SsoError(`DPoP proof has typ ${JSON.stringify(header.typ)}, not "dpop+jwt"`);
54
- if (!header.alg || !ASYMMETRIC.has(header.alg)) throw new chunkFWFXRNDG_cjs.SsoError(`DPoP proof alg ${JSON.stringify(header.alg)} is not an accepted asymmetric algorithm`);
53
+ if (header.typ !== "dpop+jwt") throw new chunkCHRCHUZ3_cjs.SsoError(`DPoP proof has typ ${JSON.stringify(header.typ)}, not "dpop+jwt"`);
54
+ if (!header.alg || !ASYMMETRIC.has(header.alg)) throw new chunkCHRCHUZ3_cjs.SsoError(`DPoP proof alg ${JSON.stringify(header.alg)} is not an accepted asymmetric algorithm`);
55
55
  const jwk = header.jwk;
56
- if (!jwk || typeof jwk !== "object") throw new chunkFWFXRNDG_cjs.SsoError("DPoP proof carries no jwk");
57
- if ("d" in jwk) throw new chunkFWFXRNDG_cjs.SsoError("DPoP proof jwk contains a private key");
56
+ if (!jwk || typeof jwk !== "object") throw new chunkCHRCHUZ3_cjs.SsoError("DPoP proof carries no jwk");
57
+ if ("d" in jwk) throw new chunkCHRCHUZ3_cjs.SsoError("DPoP proof jwk contains a private key");
58
58
  let payload;
59
59
  try {
60
60
  const key = await jose.importJWK(jwk, header.alg);
61
61
  ({ payload } = await jose.jwtVerify(proof, key, { typ: "dpop+jwt", algorithms: [header.alg] }));
62
62
  } catch (e) {
63
- throw new chunkFWFXRNDG_cjs.SsoError(`DPoP proof signature rejected: ${e instanceof Error ? e.message : String(e)}`);
63
+ throw new chunkCHRCHUZ3_cjs.SsoError(`DPoP proof signature rejected: ${e instanceof Error ? e.message : String(e)}`);
64
64
  }
65
- if (await jose.calculateJwkThumbprint(jwk) !== o.jkt) throw new chunkFWFXRNDG_cjs.SsoError("DPoP proof key does not match the ticket's cnf.jkt");
66
- if (payload.htm !== o.method.toUpperCase()) throw new chunkFWFXRNDG_cjs.SsoError(`DPoP proof is for ${JSON.stringify(payload.htm)}, the request is ${o.method.toUpperCase()}`);
65
+ if (await jose.calculateJwkThumbprint(jwk) !== o.jkt) throw new chunkCHRCHUZ3_cjs.SsoError("DPoP proof key does not match the ticket's cnf.jkt");
66
+ if (payload.htm !== o.method.toUpperCase()) throw new chunkCHRCHUZ3_cjs.SsoError(`DPoP proof is for ${JSON.stringify(payload.htm)}, the request is ${o.method.toUpperCase()}`);
67
67
  let htu;
68
68
  try {
69
69
  htu = normalizeHtu(String(payload.htu));
70
70
  } catch {
71
- throw new chunkFWFXRNDG_cjs.SsoError("DPoP proof htu is not a URL");
71
+ throw new chunkCHRCHUZ3_cjs.SsoError("DPoP proof htu is not a URL");
72
72
  }
73
- if (htu !== normalizeHtu(o.url)) throw new chunkFWFXRNDG_cjs.SsoError(`DPoP proof is for ${htu}, the request is ${normalizeHtu(o.url)}`);
73
+ if (htu !== normalizeHtu(o.url)) throw new chunkCHRCHUZ3_cjs.SsoError(`DPoP proof is for ${htu}, the request is ${normalizeHtu(o.url)}`);
74
74
  const nowSec = Math.floor(o.now() / 1e3);
75
75
  if (typeof payload.iat !== "number" || Math.abs(nowSec - payload.iat) > o.iatWindowSec) {
76
- throw new chunkFWFXRNDG_cjs.SsoError(`DPoP proof iat is outside \xB1${o.iatWindowSec}s`);
76
+ throw new chunkCHRCHUZ3_cjs.SsoError(`DPoP proof iat is outside \xB1${o.iatWindowSec}s`);
77
77
  }
78
- if (payload.ath !== await accessTokenHash(o.ticket)) throw new chunkFWFXRNDG_cjs.SsoError("DPoP proof ath does not match this ticket");
79
- if (typeof payload.jti !== "string" || payload.jti === "") throw new chunkFWFXRNDG_cjs.SsoError("DPoP proof has no jti");
78
+ if (payload.ath !== await accessTokenHash(o.ticket)) throw new chunkCHRCHUZ3_cjs.SsoError("DPoP proof ath does not match this ticket");
79
+ if (typeof payload.jti !== "string" || payload.jti === "") throw new chunkCHRCHUZ3_cjs.SsoError("DPoP proof has no jti");
80
80
  if (await o.replay.seen(`${o.jkt}:${payload.jti}`, o.iatWindowSec * 2 * 1e3)) {
81
- throw new chunkFWFXRNDG_cjs.SsoError("DPoP proof was already used (jti replay)");
81
+ throw new chunkCHRCHUZ3_cjs.SsoError("DPoP proof was already used (jti replay)");
82
82
  }
83
83
  }
84
84
 
@@ -193,7 +193,7 @@ function createTicketClient(options = {}) {
193
193
  if (!res.ok || !body.access_token) {
194
194
  const desc = body.error_description ?? "";
195
195
  const code = desc.includes(":") ? desc.slice(0, desc.indexOf(":")).trim() : body.error ?? "exchange_refused";
196
- throw new TicketExchangeError(`BrobergID refused the ticket for ${audience}: ${desc || body.error || res.status}`, code, res.status);
196
+ throw new TicketExchangeError(`BID refused the ticket for ${audience}: ${desc || body.error || res.status}`, code, res.status);
197
197
  }
198
198
  const nowSec = Math.floor(now() / 1e3);
199
199
  const exp = jwtExp(body.access_token) ?? nowSec + (body.expires_in ?? 300);
@@ -241,10 +241,10 @@ function createTicketVerifier(options) {
241
241
  now = () => Date.now()
242
242
  } = options;
243
243
  const replayStore = options.replayStore ?? createMemoryReplayStore(now);
244
- if (!issuer) throw new chunkFWFXRNDG_cjs.SsoError("createTicketVerifier needs an issuer");
245
- if (!audience) throw new chunkFWFXRNDG_cjs.SsoError("createTicketVerifier needs this receiver's audience");
244
+ if (!issuer) throw new chunkCHRCHUZ3_cjs.SsoError("createTicketVerifier needs an issuer");
245
+ if (!audience) throw new chunkCHRCHUZ3_cjs.SsoError("createTicketVerifier needs this receiver's audience");
246
246
  let cachePromise = null;
247
- const cacheFor = (jwksUri) => chunkFWFXRNDG_cjs.createJwksCache({
247
+ const cacheFor = (jwksUri) => chunkCHRCHUZ3_cjs.createJwksCache({
248
248
  jwksUri,
249
249
  fetchImpl,
250
250
  ...options.warmUp ? { warmUp: true } : {},
@@ -260,12 +260,12 @@ function createTicketVerifier(options) {
260
260
  if (!res.ok) throw new Error(`answered ${res.status}`);
261
261
  doc = await res.json();
262
262
  } catch (cause) {
263
- throw new chunkFWFXRNDG_cjs.JwksUnavailableError(`${url}: ${cause instanceof Error ? cause.message : String(cause)}`);
263
+ throw new chunkCHRCHUZ3_cjs.JwksUnavailableError(`${url}: ${cause instanceof Error ? cause.message : String(cause)}`);
264
264
  }
265
265
  if (doc.issuer !== issuer) {
266
- throw new chunkFWFXRNDG_cjs.SsoError(`issuer is ${issuer} but ${url} says ${doc.issuer} \u2014 they must match exactly`);
266
+ throw new chunkCHRCHUZ3_cjs.SsoError(`issuer is ${issuer} but ${url} says ${doc.issuer} \u2014 they must match exactly`);
267
267
  }
268
- if (!doc.jwks_uri) throw new chunkFWFXRNDG_cjs.SsoError(`${url} names no jwks_uri`);
268
+ if (!doc.jwks_uri) throw new chunkCHRCHUZ3_cjs.SsoError(`${url} names no jwks_uri`);
269
269
  return cacheFor(doc.jwks_uri);
270
270
  })().catch((err) => {
271
271
  cachePromise = null;
@@ -281,51 +281,51 @@ function createTicketVerifier(options) {
281
281
  try {
282
282
  header = jose.decodeProtectedHeader(token);
283
283
  } catch {
284
- throw new chunkFWFXRNDG_cjs.SsoError("ticket is not a JWS");
284
+ throw new chunkCHRCHUZ3_cjs.SsoError("ticket is not a JWS");
285
285
  }
286
- if (!header.kid) throw new chunkFWFXRNDG_cjs.SsoError("ticket has no kid \u2014 cannot pick a signing key");
287
- if (header.typ === "logout+jwt") throw new chunkFWFXRNDG_cjs.SsoError("a logout token is not a ticket");
286
+ if (!header.kid) throw new chunkCHRCHUZ3_cjs.SsoError("ticket has no kid \u2014 cannot pick a signing key");
287
+ if (header.typ === "logout+jwt") throw new chunkCHRCHUZ3_cjs.SsoError("a logout token is not a ticket");
288
288
  const cache = await keys();
289
289
  let payload;
290
290
  try {
291
291
  ({ payload } = await jose.jwtVerify(token, async () => cache.getKey(header.kid, header.alg ?? "EdDSA"), {
292
292
  issuer,
293
293
  audience,
294
- algorithms: chunkFWFXRNDG_cjs.ALLOWED_ALGS,
294
+ algorithms: chunkCHRCHUZ3_cjs.ALLOWED_ALGS,
295
295
  clockTolerance: clockToleranceSec,
296
296
  requiredClaims: ["exp", "iat", "jti", "sub"]
297
297
  }));
298
298
  } catch (e) {
299
- if (e instanceof chunkFWFXRNDG_cjs.JwksUnavailableError) throw e;
300
- throw new chunkFWFXRNDG_cjs.SsoError(`ticket rejected: ${e instanceof Error ? e.message : String(e)}`);
299
+ if (e instanceof chunkCHRCHUZ3_cjs.JwksUnavailableError) throw e;
300
+ throw new chunkCHRCHUZ3_cjs.SsoError(`ticket rejected: ${e instanceof Error ? e.message : String(e)}`);
301
301
  }
302
- if ("events" in payload) throw new chunkFWFXRNDG_cjs.SsoError("a logout token is not a ticket");
303
- if ("nonce" in payload) throw new chunkFWFXRNDG_cjs.SsoError("an ID token is not a ticket");
302
+ if ("events" in payload) throw new chunkCHRCHUZ3_cjs.SsoError("a logout token is not a ticket");
303
+ if ("nonce" in payload) throw new chunkCHRCHUZ3_cjs.SsoError("an ID token is not a ticket");
304
304
  const type = payload.principal_type;
305
305
  if (typeof type !== "string" || !PRINCIPAL_TYPES.includes(type)) {
306
- throw new chunkFWFXRNDG_cjs.SsoError(`ticket has no valid principal_type (got ${JSON.stringify(type)})`);
306
+ throw new chunkCHRCHUZ3_cjs.SsoError(`ticket has no valid principal_type (got ${JSON.stringify(type)})`);
307
307
  }
308
308
  const lifetime = payload.exp - payload.iat;
309
309
  if (lifetime > maxLifetimeSec) {
310
- throw new chunkFWFXRNDG_cjs.SsoError(`ticket claims a ${lifetime}s lifetime; at most ${maxLifetimeSec}s is accepted`);
310
+ throw new chunkCHRCHUZ3_cjs.SsoError(`ticket claims a ${lifetime}s lifetime; at most ${maxLifetimeSec}s is accepted`);
311
311
  }
312
- if (typeof payload.sub !== "string" || payload.sub === "") throw new chunkFWFXRNDG_cjs.SsoError("ticket has no sub");
312
+ if (typeof payload.sub !== "string" || payload.sub === "") throw new chunkCHRCHUZ3_cjs.SsoError("ticket has no sub");
313
313
  const scopes = typeof payload.scope === "string" ? payload.scope.split(" ").filter(Boolean) : [];
314
314
  const required = opts.scope === void 0 ? [] : Array.isArray(opts.scope) ? opts.scope : [opts.scope];
315
315
  const missing = required.filter((s) => !scopes.includes(s));
316
- if (missing.length) throw new chunkFWFXRNDG_cjs.SsoError(`ticket lacks scope ${missing.join(", ")}`);
316
+ if (missing.length) throw new chunkCHRCHUZ3_cjs.SsoError(`ticket lacks scope ${missing.join(", ")}`);
317
317
  const ver = payload.ver === void 0 ? 0 : payload.ver;
318
318
  if (typeof ver !== "number" || !Number.isInteger(ver) || ver < 0) {
319
- throw new chunkFWFXRNDG_cjs.SsoError(`ticket has an invalid ver (got ${JSON.stringify(payload.ver)})`);
319
+ throw new chunkCHRCHUZ3_cjs.SsoError(`ticket has an invalid ver (got ${JSON.stringify(payload.ver)})`);
320
320
  }
321
321
  if (ver > TICKET_FORMAT_VERSION) {
322
- throw new chunkFWFXRNDG_cjs.SsoError(`ticket format version ${ver} is newer than this @broberg/sso understands (${TICKET_FORMAT_VERSION}) \u2014 upgrade @broberg/sso`);
322
+ throw new chunkCHRCHUZ3_cjs.SsoError(`ticket format version ${ver} is newer than this @broberg/sso understands (${TICKET_FORMAT_VERSION}) \u2014 upgrade @broberg/sso`);
323
323
  }
324
324
  const act = payload.act === void 0 ? null : readActor(payload.act, 1);
325
325
  const cnfRaw = payload.cnf;
326
326
  const cnf = cnfRaw && typeof cnfRaw.jkt === "string" && cnfRaw.jkt ? { jkt: cnfRaw.jkt } : null;
327
327
  if (cnf) {
328
- if (!opts.dpop?.proof) throw new chunkFWFXRNDG_cjs.SsoError("ticket is DPoP-bound (cnf.jkt) but no DPoP proof was presented");
328
+ if (!opts.dpop?.proof) throw new chunkCHRCHUZ3_cjs.SsoError("ticket is DPoP-bound (cnf.jkt) but no DPoP proof was presented");
329
329
  await verifyDpopProof(opts.dpop.proof, {
330
330
  method: opts.dpop.method,
331
331
  url: opts.dpop.url,
@@ -336,11 +336,11 @@ function createTicketVerifier(options) {
336
336
  now
337
337
  });
338
338
  } else if (requireDpop) {
339
- throw new chunkFWFXRNDG_cjs.SsoError(cnfRaw !== void 0 ? "ticket has a cnf without a string jkt \u2014 DPoP is required here" : "this receiver requires DPoP; the ticket is not bound (no cnf.jkt)");
339
+ throw new chunkCHRCHUZ3_cjs.SsoError(cnfRaw !== void 0 ? "ticket has a cnf without a string jkt \u2014 DPoP is required here" : "this receiver requires DPoP; the ticket is not bound (no cnf.jkt)");
340
340
  }
341
341
  const named = (v) => typeof v === "string" && v ? v : null;
342
342
  const clientId = type === "user" ? named(payload.client_id) ?? named(payload.azp) : named(payload.client_id) ?? payload.sub;
343
- if (clientId === null) throw new chunkFWFXRNDG_cjs.SsoError("a user ticket names no app (no client_id or azp)");
343
+ if (clientId === null) throw new chunkCHRCHUZ3_cjs.SsoError("a user ticket names no app (no client_id or azp)");
344
344
  return {
345
345
  principal: payload.sub,
346
346
  type,
@@ -357,113 +357,113 @@ function createTicketVerifier(options) {
357
357
  };
358
358
  }
359
359
  function readActor(raw, depth) {
360
- if (depth > MAX_ACT_DEPTH) throw new chunkFWFXRNDG_cjs.SsoError(`ticket's delegation chain is deeper than ${MAX_ACT_DEPTH}`);
360
+ if (depth > MAX_ACT_DEPTH) throw new chunkCHRCHUZ3_cjs.SsoError(`ticket's delegation chain is deeper than ${MAX_ACT_DEPTH}`);
361
361
  const link = raw;
362
362
  if (!link || typeof link !== "object" || typeof link.sub !== "string" || link.sub === "") {
363
- throw new chunkFWFXRNDG_cjs.SsoError(`ticket's act (link ${depth}) has no string sub`);
363
+ throw new chunkCHRCHUZ3_cjs.SsoError(`ticket's act (link ${depth}) has no string sub`);
364
364
  }
365
365
  return link.act === void 0 ? { sub: link.sub } : { sub: link.sub, act: readActor(link.act, depth + 1) };
366
366
  }
367
367
 
368
368
  Object.defineProperty(exports, "AVATAR_TYPES", {
369
369
  enumerable: true,
370
- get: function () { return chunkFWFXRNDG_cjs.AVATAR_TYPES; }
370
+ get: function () { return chunkCHRCHUZ3_cjs.AVATAR_TYPES; }
371
371
  });
372
372
  Object.defineProperty(exports, "DEFAULT_SESSION_MAX_AGE", {
373
373
  enumerable: true,
374
- get: function () { return chunkFWFXRNDG_cjs.DEFAULT_SESSION_MAX_AGE; }
374
+ get: function () { return chunkCHRCHUZ3_cjs.DEFAULT_SESSION_MAX_AGE; }
375
375
  });
376
376
  Object.defineProperty(exports, "JwksError", {
377
377
  enumerable: true,
378
- get: function () { return chunkFWFXRNDG_cjs.JwksError; }
378
+ get: function () { return chunkCHRCHUZ3_cjs.JwksError; }
379
379
  });
380
380
  Object.defineProperty(exports, "JwksUnavailableError", {
381
381
  enumerable: true,
382
- get: function () { return chunkFWFXRNDG_cjs.JwksUnavailableError; }
382
+ get: function () { return chunkCHRCHUZ3_cjs.JwksUnavailableError; }
383
383
  });
384
384
  Object.defineProperty(exports, "JwksUnknownKeyError", {
385
385
  enumerable: true,
386
- get: function () { return chunkFWFXRNDG_cjs.JwksUnknownKeyError; }
386
+ get: function () { return chunkCHRCHUZ3_cjs.JwksUnknownKeyError; }
387
387
  });
388
388
  Object.defineProperty(exports, "MAX_AVATAR_BYTES", {
389
389
  enumerable: true,
390
- get: function () { return chunkFWFXRNDG_cjs.MAX_AVATAR_BYTES; }
390
+ get: function () { return chunkCHRCHUZ3_cjs.MAX_AVATAR_BYTES; }
391
391
  });
392
392
  Object.defineProperty(exports, "MAX_INVITATIONS", {
393
393
  enumerable: true,
394
- get: function () { return chunkFWFXRNDG_cjs.MAX_INVITATIONS; }
394
+ get: function () { return chunkCHRCHUZ3_cjs.MAX_INVITATIONS; }
395
395
  });
396
396
  Object.defineProperty(exports, "SsoAppApiError", {
397
397
  enumerable: true,
398
- get: function () { return chunkFWFXRNDG_cjs.SsoAppApiError; }
398
+ get: function () { return chunkCHRCHUZ3_cjs.SsoAppApiError; }
399
399
  });
400
400
  Object.defineProperty(exports, "SsoAvatarRejectedError", {
401
401
  enumerable: true,
402
- get: function () { return chunkFWFXRNDG_cjs.SsoAvatarRejectedError; }
402
+ get: function () { return chunkCHRCHUZ3_cjs.SsoAvatarRejectedError; }
403
403
  });
404
404
  Object.defineProperty(exports, "SsoConfigError", {
405
405
  enumerable: true,
406
- get: function () { return chunkFWFXRNDG_cjs.SsoConfigError; }
406
+ get: function () { return chunkCHRCHUZ3_cjs.SsoConfigError; }
407
407
  });
408
408
  Object.defineProperty(exports, "SsoError", {
409
409
  enumerable: true,
410
- get: function () { return chunkFWFXRNDG_cjs.SsoError; }
410
+ get: function () { return chunkCHRCHUZ3_cjs.SsoError; }
411
411
  });
412
412
  Object.defineProperty(exports, "SsoInsufficientScopeError", {
413
413
  enumerable: true,
414
- get: function () { return chunkFWFXRNDG_cjs.SsoInsufficientScopeError; }
414
+ get: function () { return chunkCHRCHUZ3_cjs.SsoInsufficientScopeError; }
415
415
  });
416
416
  Object.defineProperty(exports, "SsoIntrospectionUnavailableError", {
417
417
  enumerable: true,
418
- get: function () { return chunkFWFXRNDG_cjs.SsoIntrospectionUnavailableError; }
418
+ get: function () { return chunkCHRCHUZ3_cjs.SsoIntrospectionUnavailableError; }
419
419
  });
420
420
  Object.defineProperty(exports, "SsoReauthError", {
421
421
  enumerable: true,
422
- get: function () { return chunkFWFXRNDG_cjs.SsoReauthError; }
422
+ get: function () { return chunkCHRCHUZ3_cjs.SsoReauthError; }
423
423
  });
424
424
  Object.defineProperty(exports, "SsoTokenInactiveError", {
425
425
  enumerable: true,
426
- get: function () { return chunkFWFXRNDG_cjs.SsoTokenInactiveError; }
426
+ get: function () { return chunkCHRCHUZ3_cjs.SsoTokenInactiveError; }
427
427
  });
428
428
  Object.defineProperty(exports, "cookieHeader", {
429
429
  enumerable: true,
430
- get: function () { return chunkFWFXRNDG_cjs.cookieHeader; }
430
+ get: function () { return chunkCHRCHUZ3_cjs.cookieHeader; }
431
431
  });
432
432
  Object.defineProperty(exports, "createJwksCache", {
433
433
  enumerable: true,
434
- get: function () { return chunkFWFXRNDG_cjs.createJwksCache; }
434
+ get: function () { return chunkCHRCHUZ3_cjs.createJwksCache; }
435
435
  });
436
436
  Object.defineProperty(exports, "createSsoClient", {
437
437
  enumerable: true,
438
- get: function () { return chunkFWFXRNDG_cjs.createSsoClient; }
438
+ get: function () { return chunkCHRCHUZ3_cjs.createSsoClient; }
439
439
  });
440
440
  Object.defineProperty(exports, "loadSsoConfig", {
441
441
  enumerable: true,
442
- get: function () { return chunkFWFXRNDG_cjs.loadSsoConfig; }
442
+ get: function () { return chunkCHRCHUZ3_cjs.loadSsoConfig; }
443
443
  });
444
444
  Object.defineProperty(exports, "memoryTokenStore", {
445
445
  enumerable: true,
446
- get: function () { return chunkFWFXRNDG_cjs.memoryTokenStore; }
446
+ get: function () { return chunkCHRCHUZ3_cjs.memoryTokenStore; }
447
447
  });
448
448
  Object.defineProperty(exports, "readCookie", {
449
449
  enumerable: true,
450
- get: function () { return chunkFWFXRNDG_cjs.readCookie; }
450
+ get: function () { return chunkCHRCHUZ3_cjs.readCookie; }
451
451
  });
452
452
  Object.defineProperty(exports, "signSession", {
453
453
  enumerable: true,
454
- get: function () { return chunkFWFXRNDG_cjs.signSession; }
454
+ get: function () { return chunkCHRCHUZ3_cjs.signSession; }
455
455
  });
456
456
  Object.defineProperty(exports, "signValue", {
457
457
  enumerable: true,
458
- get: function () { return chunkFWFXRNDG_cjs.signValue; }
458
+ get: function () { return chunkCHRCHUZ3_cjs.signValue; }
459
459
  });
460
460
  Object.defineProperty(exports, "verifySession", {
461
461
  enumerable: true,
462
- get: function () { return chunkFWFXRNDG_cjs.verifySession; }
462
+ get: function () { return chunkCHRCHUZ3_cjs.verifySession; }
463
463
  });
464
464
  Object.defineProperty(exports, "verifyValue", {
465
465
  enumerable: true,
466
- get: function () { return chunkFWFXRNDG_cjs.verifyValue; }
466
+ get: function () { return chunkCHRCHUZ3_cjs.verifyValue; }
467
467
  });
468
468
  exports.DEFAULT_ISSUER = DEFAULT_ISSUER;
469
469
  exports.MAX_ACT_DEPTH = MAX_ACT_DEPTH;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/dpop.ts","../src/fetch-ticket.ts","../src/ticket.ts"],"names":["generateKeyPair","exportJWK","calculateJwkThumbprint","SignJWT","decodeProtectedHeader","SsoError","importJWK","jwtVerify","request","existsSync","createJwksCache","JwksUnavailableError","ALLOWED_ALGS"],"mappings":";;;;;;;AAuCA,eAAsB,aAAA,GAAkC;AACtD,EAAA,MAAM,EAAE,UAAA,EAAY,SAAA,EAAU,GAAI,MAAMA,qBAAgB,OAAA,EAAS,EAAE,WAAA,EAAa,KAAA,EAAO,CAAA;AACvF,EAAA,MAAM,GAAA,GAAM,MAAMC,cAAA,CAAU,SAAS,CAAA;AACrC,EAAA,MAAM,SAAA,GAAiB,EAAE,GAAA,EAAK,GAAA,CAAI,GAAA,EAAK,GAAA,EAAK,GAAA,CAAI,GAAA,EAAK,CAAA,EAAG,GAAA,CAAI,CAAA,EAAG,CAAA,EAAG,IAAI,CAAA,EAAE;AACxE,EAAA,OAAO,EAAE,UAAA,EAAY,SAAA,EAAW,KAAK,MAAMC,2BAAA,CAAuB,SAAS,CAAA,EAAE;AAC/E;AAEA,IAAM,GAAA,GAAM,IAAI,WAAA,EAAY;AAC5B,IAAM,MAAA,GAAS,CAAC,KAAA,KACd,IAAA,CAAK,OAAO,YAAA,CAAa,GAAG,IAAI,UAAA,CAAW,KAAK,CAAC,CAAC,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA,CAAE,OAAA,CAAQ,OAAO,GAAG,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA;AAG/G,eAAsB,gBAAgB,MAAA,EAAiC;AACrE,EAAA,OAAO,MAAA,CAAO,MAAM,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,WAAW,GAAA,CAAI,MAAA,CAAO,MAAM,CAAC,CAAC,CAAA;AACzE;AAGO,SAAS,aAAa,GAAA,EAAqB;AAChD,EAAA,MAAM,CAAA,GAAI,IAAI,GAAA,CAAI,GAAG,CAAA;AACrB,EAAA,OAAO,CAAA,EAAG,EAAE,QAAQ,CAAA,EAAA,EAAK,EAAE,IAAI,CAAA,EAAG,EAAE,QAAQ,CAAA,CAAA;AAC9C;AAGA,eAAsB,eAAA,CACpB,KACA,IAAA,EACiB;AACjB,EAAA,MAAM,OAAA,GAAmC;AAAA,IACvC,GAAA,EAAK,OAAO,UAAA,EAAW;AAAA,IACvB,GAAA,EAAK,IAAA,CAAK,MAAA,CAAO,WAAA,EAAY;AAAA,IAC7B,GAAA,EAAK,YAAA,CAAa,IAAA,CAAK,GAAG,CAAA;AAAA,IAC1B,GAAA,EAAK,KAAK,KAAA,CAAA,CAAO,IAAA,CAAK,OAAM,IAAK,IAAA,CAAK,GAAA,EAAI,IAAK,GAAI;AAAA,GACrD;AACA,EAAA,IAAI,IAAA,CAAK,WAAW,MAAA,EAAW,OAAA,CAAQ,MAAM,MAAM,eAAA,CAAgB,KAAK,MAAM,CAAA;AAC9E,EAAA,OAAO,IAAIC,YAAA,CAAQ,OAAO,CAAA,CAAE,kBAAA,CAAmB,EAAE,GAAA,EAAK,UAAA,EAAY,GAAA,EAAK,OAAA,EAAS,KAAK,GAAA,CAAI,SAAA,EAAW,CAAA,CAAE,IAAA,CAAK,IAAI,UAAU,CAAA;AAC3H;AAYO,SAAS,uBAAA,CAAwB,GAAA,GAAoB,MAAM,IAAA,CAAK,KAAI,EAAgB;AACzF,EAAA,MAAM,OAAA,uBAAc,GAAA,EAAoB;AACxC,EAAA,OAAO;AAAA,IACL,MAAM,IAAA,CAAK,GAAA,EAAK,KAAA,EAAO;AACrB,MAAA,MAAM,IAAI,GAAA,EAAI;AACd,MAAA,KAAA,MAAW,CAAC,CAAA,EAAG,KAAK,CAAA,IAAK,OAAA,MAAa,KAAA,IAAS,CAAA,EAAG,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA;AAClE,MAAA,IAAI,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA,EAAG,OAAO,IAAA;AAC7B,MAAA,OAAA,CAAQ,GAAA,CAAI,GAAA,EAAK,CAAA,GAAI,KAAK,CAAA;AAC1B,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,GACF;AACF;AAaA,IAAM,UAAA,mBAAa,IAAI,GAAA,CAAI,CAAC,SAAS,OAAA,EAAS,OAAA,EAAS,OAAA,EAAS,OAAA,EAAS,OAAA,EAAS,OAAA,EAAS,OAAA,EAAS,OAAA,EAAS,OAAO,CAAC,CAAA;AAGrH,eAAsB,eAAA,CAAgB,OAAe,CAAA,EAAsC;AACzF,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAA,GAASC,2BAAsB,KAAK,CAAA;AAAA,EACtC,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,IAAIC,2BAAS,yBAAyB,CAAA;AAAA,EAC9C;AACA,EAAA,IAAI,MAAA,CAAO,GAAA,KAAQ,UAAA,EAAY,MAAM,IAAIA,0BAAA,CAAS,CAAA,mBAAA,EAAsB,IAAA,CAAK,SAAA,CAAU,MAAA,CAAO,GAAG,CAAC,CAAA,gBAAA,CAAkB,CAAA;AACpH,EAAA,IAAI,CAAC,MAAA,CAAO,GAAA,IAAO,CAAC,UAAA,CAAW,GAAA,CAAI,OAAO,GAAG,CAAA,EAAG,MAAM,IAAIA,2BAAS,CAAA,eAAA,EAAkB,IAAA,CAAK,UAAU,MAAA,CAAO,GAAG,CAAC,CAAA,wCAAA,CAA0C,CAAA;AACzJ,EAAA,MAAM,MAAM,MAAA,CAAO,GAAA;AACnB,EAAA,IAAI,CAAC,OAAO,OAAO,GAAA,KAAQ,UAAU,MAAM,IAAIA,2BAAS,2BAA2B,CAAA;AACnF,EAAA,IAAI,GAAA,IAAO,GAAA,EAAK,MAAM,IAAIA,2BAAS,uCAAuC,CAAA;AAE1E,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,MAAMC,cAAA,CAAU,GAAA,EAAK,OAAO,GAAG,CAAA;AAC3C,IAAA,CAAC,EAAE,OAAA,EAAQ,GAAI,MAAMC,eAAU,KAAA,EAAO,GAAA,EAAK,EAAE,GAAA,EAAK,YAAY,UAAA,EAAY,CAAC,MAAA,CAAO,GAAG,GAAG,CAAA;AAAA,EAC1F,SAAS,CAAA,EAAG;AACV,IAAA,MAAM,IAAIF,0BAAA,CAAS,CAAA,+BAAA,EAAkC,CAAA,YAAa,KAAA,GAAQ,EAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA,CAAE,CAAA;AAAA,EACnG;AAEA,EAAA,IAAK,MAAMH,4BAAuB,GAAG,CAAA,KAAO,EAAE,GAAA,EAAK,MAAM,IAAIG,0BAAA,CAAS,oDAAoD,CAAA;AAC1H,EAAA,IAAI,OAAA,CAAQ,QAAQ,CAAA,CAAE,MAAA,CAAO,aAAY,EAAG,MAAM,IAAIA,0BAAA,CAAS,CAAA,kBAAA,EAAqB,KAAK,SAAA,CAAU,OAAA,CAAQ,GAAG,CAAC,CAAA,iBAAA,EAAoB,EAAE,MAAA,CAAO,WAAA,EAAa,CAAA,CAAE,CAAA;AAC3J,EAAA,IAAI,GAAA;AACJ,EAAA,IAAI;AACF,IAAA,GAAA,GAAM,YAAA,CAAa,MAAA,CAAO,OAAA,CAAQ,GAAG,CAAC,CAAA;AAAA,EACxC,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,IAAIA,2BAAS,6BAA6B,CAAA;AAAA,EAClD;AACA,EAAA,IAAI,GAAA,KAAQ,YAAA,CAAa,CAAA,CAAE,GAAG,GAAG,MAAM,IAAIA,0BAAA,CAAS,CAAA,kBAAA,EAAqB,GAAG,CAAA,iBAAA,EAAoB,YAAA,CAAa,CAAA,CAAE,GAAG,CAAC,CAAA,CAAE,CAAA;AACrH,EAAA,MAAM,SAAS,IAAA,CAAK,KAAA,CAAM,CAAA,CAAE,GAAA,KAAQ,GAAI,CAAA;AACxC,EAAA,IAAI,OAAO,OAAA,CAAQ,GAAA,KAAQ,QAAA,IAAY,IAAA,CAAK,GAAA,CAAI,MAAA,GAAS,OAAA,CAAQ,GAAG,CAAA,GAAI,CAAA,CAAE,YAAA,EAAc;AACtF,IAAA,MAAM,IAAIA,0BAAA,CAAS,CAAA,8BAAA,EAA8B,CAAA,CAAE,YAAY,CAAA,CAAA,CAAG,CAAA;AAAA,EACpE;AACA,EAAA,IAAI,OAAA,CAAQ,GAAA,KAAS,MAAM,eAAA,CAAgB,CAAA,CAAE,MAAM,CAAA,EAAI,MAAM,IAAIA,0BAAA,CAAS,2CAA2C,CAAA;AACrH,EAAA,IAAI,OAAO,OAAA,CAAQ,GAAA,KAAQ,QAAA,IAAY,OAAA,CAAQ,QAAQ,EAAA,EAAI,MAAM,IAAIA,0BAAA,CAAS,uBAAuB,CAAA;AACrG,EAAA,IAAI,MAAM,CAAA,CAAE,MAAA,CAAO,IAAA,CAAK,GAAG,CAAA,CAAE,GAAG,CAAA,CAAA,EAAI,OAAA,CAAQ,GAAG,CAAA,CAAA,EAAI,CAAA,CAAE,YAAA,GAAe,CAAA,GAAI,GAAI,CAAA,EAAG;AAC7E,IAAA,MAAM,IAAIA,2BAAS,0CAA0C,CAAA;AAAA,EAC/D;AACF;;;ACrIO,IAAM,cAAA,GAAiB;AAC9B,IAAM,UAAA,GAAa,WAAA;AAGZ,IAAM,uBAAA,GAAN,cAAsC,KAAA,CAAM;AAAA,EACjD,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,yBAAA;AAAA,EACd;AACF;AAOO,IAAM,mBAAA,GAAN,cAAkC,KAAA,CAAM;AAAA,EAC7C,WAAA,CAAY,OAAA,EAA0B,IAAA,EAAuB,MAAA,EAAgB;AAC3E,IAAA,KAAA,CAAM,OAAO,CAAA;AADuB,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAAuB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAE3D,IAAA,IAAA,CAAK,IAAA,GAAO,qBAAA;AAAA,EACd;AAAA,EAHsC,IAAA;AAAA,EAAuB,MAAA;AAI/D;AAGO,IAAM,sBAAA,GAAN,cAAqC,KAAA,CAAM;AAAA,EAChD,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,wBAAA;AAAA,EACd;AACF;AAuCA,SAAS,kBAAkB,GAAA,EAA8B;AACvD,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,EAAE,KAAK,CAAA;AACnC,IAAA,MAAM,GAAA,GAAMG,YAAA;AAAA,MACV,EAAE,UAAA,EAAY,UAAA,EAAY,IAAA,EAAM,iBAAA,EAAmB,QAAQ,MAAA,EAAQ,OAAA,EAAS,EAAE,cAAA,EAAgB,oBAAoB,gBAAA,EAAkB,MAAA,CAAO,UAAA,CAAW,IAAI,GAAE,EAAE;AAAA,MAC9J,CAAC,GAAA,KAAQ;AACP,QAAA,IAAI,IAAA,GAAO,EAAA;AACX,QAAA,GAAA,CAAI,YAAY,MAAM,CAAA;AACtB,QAAA,GAAA,CAAI,EAAA,CAAG,MAAA,EAAQ,CAAC,CAAA,KAAO,QAAQ,CAAE,CAAA;AACjC,QAAA,GAAA,CAAI,EAAA,CAAG,OAAO,MAAM;AAClB,UAAA,IAAA,CAAK,GAAA,CAAI,UAAA,IAAc,CAAA,KAAM,GAAA,IAAA,CAAQ,GAAA,CAAI,UAAA,IAAc,CAAA,IAAK,GAAA,EAAK,OAAA,CAAQ,IAAA,CAAK,IAAA,EAAM,CAAA;AAAA,sBACxE,IAAI,sBAAA,CAAuB,qBAAqB,GAAA,CAAI,UAAU,EAAE,CAAC,CAAA;AAAA,QAC/E,CAAC,CAAA;AAAA,MACH;AAAA,KACF;AACA,IAAA,GAAA,CAAI,EAAA,CAAG,OAAA,EAAS,CAAC,CAAA,KAAM,MAAA,CAAO,IAAI,sBAAA,CAAuB,CAAA,iBAAA,EAAoB,CAAA,CAAE,OAAO,CAAA,CAAE,CAAC,CAAC,CAAA;AAC1F,IAAA,GAAA,CAAI,IAAI,IAAI,CAAA;AAAA,EACd,CAAC,CAAA;AACH;AAGA,SAAS,OAAO,KAAA,EAA8B;AAC5C,EAAA,IAAI;AACF,IAAA,MAAM,UAAU,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,IAAA,CAAK,MAAM,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,KAAK,EAAA,EAAI,WAAW,CAAA,CAAE,QAAA,CAAS,MAAM,CAAC,CAAA;AAC/F,IAAA,OAAO,OAAO,OAAA,CAAQ,GAAA,KAAQ,QAAA,GAAW,QAAQ,GAAA,GAAM,IAAA;AAAA,EACzD,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAEO,SAAS,kBAAA,CAAmB,OAAA,GAA+B,EAAC,EAAiB;AAClF,EAAA,MAAM,UAAU,OAAA,CAAQ,MAAA,IAAU,cAAA,EAAgB,OAAA,CAAQ,QAAQ,EAAE,CAAA;AACpE,EAAA,MAAM,cAAA,GAAiB,QAAQ,cAAA,IAAkB,EAAA;AACjD,EAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,GAAA,IAAO,OAAA,CAAQ,GAAA;AACnC,EAAA,MAAM,SAAA,GAAY,QAAQ,SAAA,IAAa,KAAA;AACvC,EAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,GAAA,KAAQ,MAAM,KAAK,GAAA,EAAI,CAAA;AAC3C,EAAA,MAAM,OAAA,GAAU,QAAQ,OAAA,IAAW,iBAAA;AACnC,EAAA,MAAM,KAAA,GAAQ,QAAQ,KAAA,KAAU,MAAM,CAAC,CAAC,GAAA,CAAI,YAAA,IAAgBC,aAAA,CAAW,UAAU,CAAA,CAAA;AAEjF,EAAA,MAAM,KAAA,uBAAY,GAAA,EAA4C;AAC9D,EAAA,MAAM,QAAA,uBAAe,GAAA,EAA6B;AAClD,EAAA,IAAI,OAAA,GAAmC,IAAA;AACvC,EAAA,MAAM,MAAA,GAAS,MAAO,OAAA,KAAY,aAAA,EAAc;AAEhD,EAAA,eAAe,aAAA,GAAiC;AAC9C,IAAA,IAAI,KAAA,EAAM,EAAG,OAAO,OAAA,CAAQ,MAAM,CAAA;AAClC,IAAA,MAAM,MAAM,GAAA,CAAI,4BAAA;AAChB,IAAA,MAAM,SAAS,GAAA,CAAI,8BAAA;AACnB,IAAA,IAAI,OAAO,MAAA,EAAQ;AACjB,MAAA,IAAI,GAAA;AACJ,MAAA,IAAI;AACF,QAAA,GAAA,GAAM,MAAM,SAAA,CAAU,CAAA,EAAG,GAAG,CAAA,UAAA,EAAa,mBAAmB,MAAM,CAAC,CAAA,CAAA,EAAI,EAAE,SAAS,EAAE,aAAA,EAAe,UAAU,MAAM,CAAA,CAAA,IAAM,CAAA;AAAA,MAC3H,SAAS,CAAA,EAAG;AACV,QAAA,MAAM,IAAI,sBAAA,CAAuB,CAAA,kCAAA,EAAqC,CAAA,YAAa,KAAA,GAAQ,EAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA,CAAE,CAAA;AAAA,MACpH;AACA,MAAA,IAAI,CAAC,IAAI,EAAA,EAAI,MAAM,IAAI,sBAAA,CAAuB,CAAA,8BAAA,EAAiC,GAAA,CAAI,MAAM,CAAA,CAAE,CAAA;AAC3F,MAAA,MAAM,EAAE,KAAA,EAAM,GAAK,MAAM,IAAI,IAAA,EAAK;AAClC,MAAA,IAAI,CAAC,KAAA,EAAO,MAAM,IAAI,uBAAuB,wCAAwC,CAAA;AACrF,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,MAAM,IAAI,uBAAA;AAAA,MACR;AAAA,KAEF;AAAA,EACF;AAEA,EAAA,eAAe,QAAA,CAAS,UAAkB,KAAA,EAAoE;AAC5G,IAAA,MAAM,OAAA,GAAU,MAAM,aAAA,EAAc;AACpC,IAAA,MAAM,IAAA,GAAO,IAAI,eAAA,CAAgB;AAAA,MAC/B,UAAA,EAAY,iDAAA;AAAA,MACZ,aAAA,EAAe,OAAA;AAAA,MACf,kBAAA,EAAoB,sCAAA;AAAA,MACpB;AAAA,KACD,CAAA;AACD,IAAA,IAAI,KAAA,EAAO,IAAA,CAAK,GAAA,CAAI,OAAA,EAAS,KAAK,CAAA;AAClC,IAAA,IAAI,GAAA;AACJ,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,GAAW,GAAG,MAAM,CAAA,aAAA,CAAA;AAC1B,MAAA,MAAM,OAAA,GAAkC,EAAE,cAAA,EAAgB,mCAAA,EAAoC;AAC9F,MAAA,IAAI,OAAA,CAAQ,IAAA,EAAM,OAAA,CAAQ,IAAA,GAAO,MAAM,eAAA,CAAgB,MAAM,MAAA,EAAO,EAAG,EAAE,MAAA,EAAQ,MAAA,EAAQ,GAAA,EAAK,QAAA,EAAU,KAAK,CAAA;AAC7G,MAAA,GAAA,GAAM,MAAM,UAAU,QAAA,EAAU,EAAE,QAAQ,MAAA,EAAQ,OAAA,EAAS,IAAA,EAAM,IAAA,EAAM,CAAA;AAAA,IACzE,SAAS,CAAA,EAAG;AACV,MAAA,MAAM,IAAI,sBAAA,CAAuB,CAAA,EAAG,MAAM,CAAA,cAAA,EAAiB,CAAA,YAAa,KAAA,GAAQ,CAAA,CAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA,CAAE,CAAA;AAAA,IACzG;AACA,IAAA,IAAI,OAAmG,EAAC;AACxG,IAAA,IAAI;AACF,MAAA,IAAA,GAAQ,MAAM,IAAI,IAAA,EAAK;AAAA,IACzB,CAAA,CAAA,MAAQ;AAAA,IAER;AACA,IAAA,IAAI,GAAA,CAAI,MAAA,IAAU,GAAA,EAAK,MAAM,IAAI,sBAAA,CAAuB,CAAA,EAAG,MAAM,CAAA,UAAA,EAAa,GAAA,CAAI,MAAM,CAAA,CAAE,CAAA;AAC1F,IAAA,IAAI,CAAC,GAAA,CAAI,EAAA,IAAM,CAAC,KAAK,YAAA,EAAc;AACjC,MAAA,MAAM,IAAA,GAAO,KAAK,iBAAA,IAAqB,EAAA;AACvC,MAAA,MAAM,OAAO,IAAA,CAAK,QAAA,CAAS,GAAG,CAAA,GAAI,KAAK,KAAA,CAAM,CAAA,EAAG,IAAA,CAAK,OAAA,CAAQ,GAAG,CAAC,CAAA,CAAE,IAAA,EAAK,GAAI,KAAK,KAAA,IAAS,kBAAA;AAC1F,MAAA,MAAM,IAAI,mBAAA,CAAoB,CAAA,iCAAA,EAAoC,QAAQ,CAAA,EAAA,EAAK,IAAA,IAAQ,IAAA,CAAK,KAAA,IAAS,GAAA,CAAI,MAAM,CAAA,CAAA,EAAI,IAAA,EAAM,IAAI,MAAM,CAAA;AAAA,IACrI;AACA,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,GAAA,KAAQ,GAAI,CAAA;AACtC,IAAA,MAAM,MAAM,MAAA,CAAO,IAAA,CAAK,YAAY,CAAA,IAAK,MAAA,IAAU,KAAK,UAAA,IAAc,GAAA,CAAA;AACtE,IAAA,OAAO,EAAE,KAAA,EAAO,IAAA,CAAK,YAAA,EAAc,GAAA,EAAI;AAAA,EACzC;AAEA,EAAA,MAAM,MAAA,GAAuB;AAAA,IAC3B,MAAM,WAAA,CAAY,EAAE,UAAU,KAAA,EAAO,MAAA,EAAQ,KAAI,EAAG;AAClD,MAAA,MAAM,SAAS,MAAM,MAAA,CAAO,IAAI,EAAE,QAAA,EAAU,OAAO,CAAA;AACnD,MAAA,IAAI,CAAC,QAAQ,IAAA,EAAM,OAAO,EAAE,aAAA,EAAe,CAAA,OAAA,EAAU,MAAM,CAAA,CAAA,EAAG;AAC9D,MAAA,OAAO,EAAE,aAAA,EAAe,CAAA,KAAA,EAAQ,MAAM,CAAA,CAAA,EAAI,MAAM,MAAM,eAAA,CAAgB,MAAM,MAAA,IAAU,EAAE,MAAA,EAAQ,KAAK,MAAA,EAAQ,GAAA,EAAK,CAAA,EAAE;AAAA,IACtH,CAAA;AAAA,IACA,MAAM,GAAA,CAAI,EAAE,QAAA,EAAU,OAAM,EAAG;AAC7B,MAAA,MAAM,GAAA,GAAM,CAAA,EAAG,QAAQ,CAAA,CAAA,EAAI,SAAS,EAAE,CAAA,CAAA;AACtC,MAAA,MAAM,GAAA,GAAM,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA;AACzB,MAAA,IAAI,GAAA,IAAO,IAAI,GAAA,GAAM,cAAA,GAAiB,KAAI,GAAI,GAAA,SAAa,GAAA,CAAI,KAAA;AAC/D,MAAA,MAAM,OAAA,GAAU,QAAA,CAAS,GAAA,CAAI,GAAG,CAAA;AAChC,MAAA,IAAI,SAAS,OAAO,OAAA;AACpB,MAAA,MAAM,IAAI,QAAA,CAAS,QAAA,EAAU,KAAK,CAAA,CAC/B,IAAA,CAAK,CAAC,CAAA,KAAM;AACX,QAAA,KAAA,CAAM,GAAA,CAAI,KAAK,CAAC,CAAA;AAChB,QAAA,OAAO,CAAA,CAAE,KAAA;AAAA,MACX,CAAC,CAAA,CACA,OAAA,CAAQ,MAAM,QAAA,CAAS,MAAA,CAAO,GAAG,CAAC,CAAA;AACrC,MAAA,QAAA,CAAS,GAAA,CAAI,KAAK,CAAC,CAAA;AACnB,MAAA,OAAO,CAAA;AAAA,IACT;AAAA,GACF;AACA,EAAA,OAAO,MAAA;AACT;AAEA,IAAI,MAAA,GAA8B,IAAA;AAE3B,SAAS,YAAY,IAAA,EAA6D;AACvF,EAAA,MAAA,KAAW,kBAAA,EAAmB;AAC9B,EAAA,OAAO,MAAA,CAAO,IAAI,IAAI,CAAA;AACxB;AC1LA,IAAM,eAAA,GAA4C,CAAC,OAAA,EAAS,SAAA,EAAW,SAAS,MAAM,CAAA;AAa/E,IAAM,qBAAA,GAAwB;AAE9B,IAAM,aAAA,GAAgB;AA8EtB,SAAS,qBAAqB,OAAA,EAAgD;AACnF,EAAA,MAAM;AAAA,IACJ,MAAA;AAAA,IACA,QAAA;AAAA,IACA,iBAAiB,EAAA,GAAK,EAAA;AAAA,IACtB,iBAAA,GAAoB,EAAA;AAAA,IACpB,SAAA,GAAY,KAAA;AAAA,IACZ,WAAA,GAAc,KAAA;AAAA,IACd,gBAAA,GAAmB,EAAA;AAAA,IACnB,GAAA,GAAM,MAAM,IAAA,CAAK,GAAA;AAAI,GACvB,GAAI,OAAA;AACJ,EAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,WAAA,IAAe,uBAAA,CAAwB,GAAG,CAAA;AACtE,EAAA,IAAI,CAAC,MAAA,EAAQ,MAAM,IAAIJ,2BAAS,sCAAsC,CAAA;AACtE,EAAA,IAAI,CAAC,QAAA,EAAU,MAAM,IAAIA,2BAAS,qDAAqD,CAAA;AAEvF,EAAA,IAAI,YAAA,GAA0C,IAAA;AAC9C,EAAA,MAAM,QAAA,GAAW,CAAC,OAAA,KAChBK,iCAAA,CAAgB;AAAA,IACd,OAAA;AAAA,IACA,SAAA;AAAA,IACA,GAAI,OAAA,CAAQ,MAAA,GAAS,EAAE,MAAA,EAAQ,IAAA,KAAS,EAAC;AAAA,IACzC,GAAI,QAAQ,oBAAA,KAAyB,MAAA,GAAY,EAAE,oBAAA,EAAsB,OAAA,CAAQ,oBAAA,EAAqB,GAAI;AAAC,GAC5G,CAAA;AAEH,EAAA,eAAe,IAAA,GAA2B;AACxC,IAAA,YAAA,KAAA,CAAkB,YAAY;AAC5B,MAAA,IAAI,OAAA,CAAQ,OAAA,EAAS,OAAO,QAAA,CAAS,QAAQ,OAAO,CAAA;AACpD,MAAA,MAAM,GAAA,GAAM,GAAG,MAAM,CAAA,iCAAA,CAAA;AACrB,MAAA,IAAI,GAAA;AACJ,MAAA,IAAI;AACF,QAAA,MAAM,GAAA,GAAM,MAAM,SAAA,CAAU,GAAG,CAAA;AAC/B,QAAA,IAAI,CAAC,IAAI,EAAA,EAAI,MAAM,IAAI,KAAA,CAAM,CAAA,SAAA,EAAY,GAAA,CAAI,MAAM,CAAA,CAAE,CAAA;AACrD,QAAA,GAAA,GAAO,MAAM,IAAI,IAAA,EAAK;AAAA,MACxB,SAAS,KAAA,EAAO;AAEd,QAAA,MAAM,IAAIC,sCAAA,CAAqB,CAAA,EAAG,GAAG,CAAA,EAAA,EAAK,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CAAC,CAAA,CAAE,CAAA;AAAA,MACpG;AACA,MAAA,IAAI,GAAA,CAAI,WAAW,MAAA,EAAQ;AACzB,QAAA,MAAM,IAAIN,2BAAS,CAAA,UAAA,EAAa,MAAM,QAAQ,GAAG,CAAA,MAAA,EAAS,GAAA,CAAI,MAAM,CAAA,+BAAA,CAA4B,CAAA;AAAA,MAClG;AACA,MAAA,IAAI,CAAC,IAAI,QAAA,EAAU,MAAM,IAAIA,0BAAA,CAAS,CAAA,EAAG,GAAG,CAAA,kBAAA,CAAoB,CAAA;AAChE,MAAA,OAAO,QAAA,CAAS,IAAI,QAAQ,CAAA;AAAA,IAC9B,CAAA,GAAG,CAAE,KAAA,CAAM,CAAC,GAAA,KAAQ;AAClB,MAAA,YAAA,GAAe,IAAA;AACf,MAAA,MAAM,GAAA;AAAA,IACR,CAAC,CAAA;AACD,IAAA,OAAO,YAAA;AAAA,EACT;AACA,EAAA,IAAI,QAAQ,MAAA,EAAQ,KAAK,IAAA,EAAK,CAAE,MAAM,MAAM;AAAA,EAAC,CAAC,CAAA;AAE9C,EAAA,OAAO;AAAA,IACL,MAAM,MAAA,CAAO,KAAA,EAAO,IAAA,GAAO,EAAC,EAAG;AAC7B,MAAA,IAAI,MAAA;AACJ,MAAA,IAAI;AACF,QAAA,MAAA,GAASD,2BAAsB,KAAK,CAAA;AAAA,MACtC,CAAA,CAAA,MAAQ;AACN,QAAA,MAAM,IAAIC,2BAAS,qBAAqB,CAAA;AAAA,MAC1C;AACA,MAAA,IAAI,CAAC,MAAA,CAAO,GAAA,EAAK,MAAM,IAAIA,2BAAS,oDAA+C,CAAA;AACnF,MAAA,IAAI,OAAO,GAAA,KAAQ,YAAA,EAAc,MAAM,IAAIA,2BAAS,gCAAgC,CAAA;AAEpF,MAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,EAAK;AACzB,MAAA,IAAI,OAAA;AACJ,MAAA,IAAI;AACF,QAAA,CAAC,EAAE,OAAA,EAAQ,GAAI,MAAME,eAAU,KAAA,EAAO,YAAY,KAAA,CAAM,MAAA,CAAO,MAAA,CAAO,GAAA,EAAM,MAAA,CAAO,GAAA,IAAO,OAAO,CAAA,EAAG;AAAA,UAClG,MAAA;AAAA,UACA,QAAA;AAAA,UACA,UAAA,EAAYK,8BAAA;AAAA,UACZ,cAAA,EAAgB,iBAAA;AAAA,UAChB,cAAA,EAAgB,CAAC,KAAA,EAAO,KAAA,EAAO,OAAO,KAAK;AAAA,SAC5C,CAAA;AAAA,MACH,SAAS,CAAA,EAAG;AAEV,QAAA,IAAI,CAAA,YAAaD,wCAAsB,MAAM,CAAA;AAC7C,QAAA,MAAM,IAAIN,0BAAA,CAAS,CAAA,iBAAA,EAAoB,CAAA,YAAa,KAAA,GAAQ,EAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA,CAAE,CAAA;AAAA,MACrF;AAIA,MAAA,IAAI,QAAA,IAAY,OAAA,EAAS,MAAM,IAAIA,2BAAS,gCAAgC,CAAA;AAC5E,MAAA,IAAI,OAAA,IAAW,OAAA,EAAS,MAAM,IAAIA,2BAAS,6BAA6B,CAAA;AAExE,MAAA,MAAM,OAAO,OAAA,CAAQ,cAAA;AACrB,MAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,CAAC,eAAA,CAAgB,QAAA,CAAS,IAAqB,CAAA,EAAG;AAChF,QAAA,MAAM,IAAIA,0BAAA,CAAS,CAAA,wCAAA,EAA2C,KAAK,SAAA,CAAU,IAAI,CAAC,CAAA,CAAA,CAAG,CAAA;AAAA,MACvF;AACA,MAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,GAAA,GAAO,OAAA,CAAQ,GAAA;AACxC,MAAA,IAAI,WAAW,cAAA,EAAgB;AAC7B,QAAA,MAAM,IAAIA,0BAAA,CAAS,CAAA,gBAAA,EAAmB,QAAQ,CAAA,oBAAA,EAAuB,cAAc,CAAA,aAAA,CAAe,CAAA;AAAA,MACpG;AACA,MAAA,IAAI,OAAO,OAAA,CAAQ,GAAA,KAAQ,QAAA,IAAY,OAAA,CAAQ,QAAQ,EAAA,EAAI,MAAM,IAAIA,0BAAA,CAAS,mBAAmB,CAAA;AAEjG,MAAA,MAAM,MAAA,GAAS,OAAO,OAAA,CAAQ,KAAA,KAAU,QAAA,GAAW,OAAA,CAAQ,KAAA,CAAM,KAAA,CAAM,GAAG,CAAA,CAAE,MAAA,CAAO,OAAO,IAAI,EAAC;AAC/F,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,KAAA,KAAU,MAAA,GAAY,EAAC,GAAI,KAAA,CAAM,OAAA,CAAQ,IAAA,CAAK,KAAK,CAAA,GAAI,IAAA,CAAK,KAAA,GAAQ,CAAC,KAAK,KAAK,CAAA;AACrG,MAAA,MAAM,OAAA,GAAU,SAAS,MAAA,CAAO,CAAC,MAAM,CAAC,MAAA,CAAO,QAAA,CAAS,CAAC,CAAC,CAAA;AAC1D,MAAA,IAAI,OAAA,CAAQ,MAAA,EAAQ,MAAM,IAAIA,0BAAA,CAAS,sBAAsB,OAAA,CAAQ,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA;AAIjF,MAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,GAAA,KAAQ,MAAA,GAAY,IAAI,OAAA,CAAQ,GAAA;AACpD,MAAA,IAAI,OAAO,QAAQ,QAAA,IAAY,CAAC,OAAO,SAAA,CAAU,GAAG,CAAA,IAAK,GAAA,GAAM,CAAA,EAAG;AAChE,QAAA,MAAM,IAAIA,2BAAS,CAAA,+BAAA,EAAkC,IAAA,CAAK,UAAU,OAAA,CAAQ,GAAG,CAAC,CAAA,CAAA,CAAG,CAAA;AAAA,MACrF;AACA,MAAA,IAAI,MAAM,qBAAA,EAAuB;AAC/B,QAAA,MAAM,IAAIA,0BAAA,CAAS,CAAA,sBAAA,EAAyB,GAAG,CAAA,8CAAA,EAAiD,qBAAqB,CAAA,6BAAA,CAA0B,CAAA;AAAA,MACjJ;AAIA,MAAA,MAAM,GAAA,GAAM,QAAQ,GAAA,KAAQ,MAAA,GAAY,OAAO,SAAA,CAAU,OAAA,CAAQ,KAAK,CAAC,CAAA;AACvE,MAAA,MAAM,SAAS,OAAA,CAAQ,GAAA;AACvB,MAAA,MAAM,GAAA,GAAM,MAAA,IAAU,OAAO,MAAA,CAAO,GAAA,KAAQ,QAAA,IAAY,MAAA,CAAO,GAAA,GAAM,EAAE,GAAA,EAAK,MAAA,CAAO,GAAA,EAAI,GAAI,IAAA;AAG3F,MAAA,IAAI,GAAA,EAAK;AACP,QAAA,IAAI,CAAC,IAAA,CAAK,IAAA,EAAM,OAAO,MAAM,IAAIA,2BAAS,gEAAgE,CAAA;AAC1G,QAAA,MAAM,eAAA,CAAgB,IAAA,CAAK,IAAA,CAAK,KAAA,EAAO;AAAA,UACrC,MAAA,EAAQ,KAAK,IAAA,CAAK,MAAA;AAAA,UAClB,GAAA,EAAK,KAAK,IAAA,CAAK,GAAA;AAAA,UACf,MAAA,EAAQ,KAAA;AAAA,UACR,KAAK,GAAA,CAAI,GAAA;AAAA,UACT,MAAA,EAAQ,WAAA;AAAA,UACR,YAAA,EAAc,gBAAA;AAAA,UACd;AAAA,SACD,CAAA;AAAA,MACH,WAAW,WAAA,EAAa;AACtB,QAAA,MAAM,IAAIA,0BAAA,CAAS,MAAA,KAAW,MAAA,GAAY,uEAAkE,mEAAmE,CAAA;AAAA,MACjL;AAIA,MAAA,MAAM,QAAQ,CAAC,CAAA,KAAgB,OAAO,CAAA,KAAM,QAAA,IAAY,IAAI,CAAA,GAAI,IAAA;AAChE,MAAA,MAAM,QAAA,GACJ,IAAA,KAAS,MAAA,GACL,KAAA,CAAM,QAAQ,SAAS,CAAA,IAAK,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA,GAC7C,KAAA,CAAM,OAAA,CAAQ,SAAS,KAAK,OAAA,CAAQ,GAAA;AAC1C,MAAA,IAAI,QAAA,KAAa,IAAA,EAAM,MAAM,IAAIA,2BAAS,kDAAkD,CAAA;AAC5F,MAAA,OAAO;AAAA,QACL,WAAW,OAAA,CAAQ,GAAA;AAAA,QACnB,IAAA;AAAA,QACA,QAAA;AAAA,QACA,GAAA,EAAK,OAAO,OAAA,CAAQ,GAAA,KAAQ,YAAY,OAAA,CAAQ,GAAA,GAAM,QAAQ,GAAA,GAAM,IAAA;AAAA,QACpE,GAAA;AAAA,QACA,OAAA,EAAS,GAAA;AAAA,QACT,GAAA;AAAA,QACA,MAAA;AAAA,QACA,KAAK,OAAA,CAAQ,GAAA;AAAA,QACb,GAAA,EAAK,MAAA,CAAO,OAAA,CAAQ,GAAG;AAAA,OACzB;AAAA,IACF;AAAA,GACF;AACF;AAEA,SAAS,SAAA,CAAU,KAAc,KAAA,EAA4B;AAC3D,EAAA,IAAI,QAAQ,aAAA,EAAe,MAAM,IAAIA,0BAAA,CAAS,CAAA,yCAAA,EAA4C,aAAa,CAAA,CAAE,CAAA;AACzG,EAAA,MAAM,IAAA,GAAO,GAAA;AACb,EAAA,IAAI,CAAC,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,IAAY,OAAO,IAAA,CAAK,GAAA,KAAQ,QAAA,IAAY,IAAA,CAAK,GAAA,KAAQ,EAAA,EAAI;AACxF,IAAA,MAAM,IAAIA,0BAAA,CAAS,CAAA,mBAAA,EAAsB,KAAK,CAAA,mBAAA,CAAqB,CAAA;AAAA,EACrE;AACA,EAAA,OAAO,KAAK,GAAA,KAAQ,MAAA,GAAY,EAAE,GAAA,EAAK,IAAA,CAAK,KAAI,GAAI,EAAE,GAAA,EAAK,IAAA,CAAK,KAAK,GAAA,EAAK,SAAA,CAAU,KAAK,GAAA,EAAK,KAAA,GAAQ,CAAC,CAAA,EAAE;AAC3G","file":"index.cjs","sourcesContent":["/**\n * F084.157 — DPoP (RFC 9449): a bound ticket works only for whoever holds the key\n * (broberg-id-F087.16, joint design #2572/#2574).\n *\n * A DPoP-bound ticket carries `cnf.jkt`, the thumbprint of the caller's public\n * key. With every request the caller signs a short PROOF (method, URL, time, a\n * hash of the ticket) with the matching private key. A ticket copied out of a log\n * is useless on another machine: it has the ticket, not the key.\n *\n * THE RULE THAT MAKES IT PROTECTION (agreed with broberg-id, (A) in #2574): once a\n * receiver verifies with this version, a ticket WITH cnf.jkt needs a valid proof —\n * also while DPoP is otherwise optional. `requireDpop` only decides whether\n * UNBOUND tickets are still accepted. Were bound tickets accepted without a proof\n * during the rollout, a stolen bound ticket would work as bearer the whole time.\n *\n * Not here yet: server nonces (RFC 9449 §8). The jti replay store covers replay\n * inside the iat window.\n */\nimport {\n SignJWT,\n calculateJwkThumbprint,\n decodeProtectedHeader,\n exportJWK,\n generateKeyPair,\n importJWK,\n jwtVerify,\n type JWK,\n} from \"jose\";\nimport { SsoError } from \"./client.js\";\n\n/** One process's DPoP key. The private half cannot be exported. */\nexport interface DpopKey {\n privateKey: CryptoKey;\n publicJwk: JWK;\n /** RFC 7638 thumbprint — what BID puts in the ticket's cnf.jkt. */\n jkt: string;\n}\n\n/** A fresh ES256 key pair, private key non-extractable, never written anywhere. */\nexport async function createDpopKey(): Promise<DpopKey> {\n const { privateKey, publicKey } = await generateKeyPair(\"ES256\", { extractable: false });\n const jwk = await exportJWK(publicKey); // a public key is always exportable\n const publicJwk: JWK = { kty: jwk.kty, crv: jwk.crv, x: jwk.x, y: jwk.y };\n return { privateKey, publicJwk, jkt: await calculateJwkThumbprint(publicJwk) };\n}\n\nconst enc = new TextEncoder();\nconst b64url = (bytes: ArrayBuffer) =>\n btoa(String.fromCharCode(...new Uint8Array(bytes))).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n\n/** `ath`: base64url(SHA-256(ticket)) — ties a proof to one ticket. */\nexport async function accessTokenHash(ticket: string): Promise<string> {\n return b64url(await crypto.subtle.digest(\"SHA-256\", enc.encode(ticket)));\n}\n\n/** RFC 9449 §4.3: htu is compared without query and fragment. */\nexport function normalizeHtu(url: string): string {\n const u = new URL(url);\n return `${u.protocol}//${u.host}${u.pathname}`;\n}\n\n/** Sign one proof. Pass `ticket` when calling a resource server (adds ath); omit it for BID's token endpoint. */\nexport async function createDpopProof(\n key: DpopKey,\n opts: { method: string; url: string; ticket?: string; now?: () => number },\n): Promise<string> {\n const payload: Record<string, unknown> = {\n jti: crypto.randomUUID(),\n htm: opts.method.toUpperCase(),\n htu: normalizeHtu(opts.url),\n iat: Math.floor((opts.now?.() ?? Date.now()) / 1000),\n };\n if (opts.ticket !== undefined) payload.ath = await accessTokenHash(opts.ticket);\n return new SignJWT(payload).setProtectedHeader({ typ: \"dpop+jwt\", alg: \"ES256\", jwk: key.publicJwk }).sign(key.privateKey);\n}\n\n/**\n * Remembers which proofs were already used. The default is in-memory, which\n * holds on ONE machine: a receiver running on two machines must pass a shared\n * store, or a proof replayed against the other machine inside the window passes.\n */\nexport interface ReplayStore {\n /** Record `key`; resolve true if it was already recorded within `ttlMs`. */\n seen(key: string, ttlMs: number): Promise<boolean>;\n}\n\nexport function createMemoryReplayStore(now: () => number = () => Date.now()): ReplayStore {\n const entries = new Map<string, number>();\n return {\n async seen(key, ttlMs) {\n const t = now();\n for (const [k, until] of entries) if (until <= t) entries.delete(k);\n if (entries.has(key)) return true;\n entries.set(key, t + ttlMs);\n return false;\n },\n };\n}\n\nexport interface VerifyProofOptions {\n method: string;\n /** The receiver's PUBLIC URL for this request (behind a proxy the process sees an internal one). */\n url: string;\n ticket: string;\n jkt: string;\n replay: ReplayStore;\n iatWindowSec: number;\n now: () => number;\n}\n\nconst ASYMMETRIC = new Set([\"ES256\", \"ES384\", \"ES512\", \"EdDSA\", \"PS256\", \"PS384\", \"PS512\", \"RS256\", \"RS384\", \"RS512\"]);\n\n/** Throws SsoError naming the first thing that is wrong. */\nexport async function verifyDpopProof(proof: string, o: VerifyProofOptions): Promise<void> {\n let header;\n try {\n header = decodeProtectedHeader(proof);\n } catch {\n throw new SsoError(\"DPoP proof is not a JWS\");\n }\n if (header.typ !== \"dpop+jwt\") throw new SsoError(`DPoP proof has typ ${JSON.stringify(header.typ)}, not \"dpop+jwt\"`);\n if (!header.alg || !ASYMMETRIC.has(header.alg)) throw new SsoError(`DPoP proof alg ${JSON.stringify(header.alg)} is not an accepted asymmetric algorithm`);\n const jwk = header.jwk as JWK | undefined;\n if (!jwk || typeof jwk !== \"object\") throw new SsoError(\"DPoP proof carries no jwk\");\n if (\"d\" in jwk) throw new SsoError(\"DPoP proof jwk contains a private key\");\n\n let payload;\n try {\n const key = await importJWK(jwk, header.alg);\n ({ payload } = await jwtVerify(proof, key, { typ: \"dpop+jwt\", algorithms: [header.alg] }));\n } catch (e) {\n throw new SsoError(`DPoP proof signature rejected: ${e instanceof Error ? e.message : String(e)}`);\n }\n\n if ((await calculateJwkThumbprint(jwk)) !== o.jkt) throw new SsoError(\"DPoP proof key does not match the ticket's cnf.jkt\");\n if (payload.htm !== o.method.toUpperCase()) throw new SsoError(`DPoP proof is for ${JSON.stringify(payload.htm)}, the request is ${o.method.toUpperCase()}`);\n let htu: string;\n try {\n htu = normalizeHtu(String(payload.htu));\n } catch {\n throw new SsoError(\"DPoP proof htu is not a URL\");\n }\n if (htu !== normalizeHtu(o.url)) throw new SsoError(`DPoP proof is for ${htu}, the request is ${normalizeHtu(o.url)}`);\n const nowSec = Math.floor(o.now() / 1000);\n if (typeof payload.iat !== \"number\" || Math.abs(nowSec - payload.iat) > o.iatWindowSec) {\n throw new SsoError(`DPoP proof iat is outside ±${o.iatWindowSec}s`);\n }\n if (payload.ath !== (await accessTokenHash(o.ticket))) throw new SsoError(\"DPoP proof ath does not match this ticket\");\n if (typeof payload.jti !== \"string\" || payload.jti === \"\") throw new SsoError(\"DPoP proof has no jti\");\n if (await o.replay.seen(`${o.jkt}:${payload.jti}`, o.iatWindowSec * 2 * 1000)) {\n throw new SsoError(\"DPoP proof was already used (jti replay)\");\n }\n}\n","/**\n * F084.154 — fetch a BrobergID ticket WITHOUT a key (broberg-id-F087.10/.11).\n *\n * The sending half of F084.153: a workload proves who it is with the identity its\n * platform already gives it, and BID exchanges that for a short-lived ticket\n * (RFC 8693 token exchange). No secret is stored anywhere.\n *\n * Fly.io POST unix:/.fly/api /v1/tokens/oidc {aud: issuer}\n * GitHub Actions GET $ACTIONS_ID_TOKEN_REQUEST_URL&audience=issuer\n * (needs `permissions: id-token: write` in the workflow)\n * then POST {issuer}/oauth2/token grant_type=…token-exchange\n *\n * Reference implementation: broberg-id/.github/workflows/ticket-probe.yml.\n * The ticket itself is never logged or put in an error message.\n */\nimport { existsSync } from \"node:fs\";\nimport { request } from \"node:http\";\nimport { createDpopKey, createDpopProof, type DpopKey } from \"./dpop.js\";\n\nexport const DEFAULT_ISSUER = \"https://id.broberg.ai\";\nconst FLY_SOCKET = \"/.fly/api\";\n\n/** No platform identity to exchange: not on Fly, not in a GitHub Actions job with id-token: write. */\nexport class NoWorkloadIdentityError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"NoWorkloadIdentityError\";\n }\n}\n\n/**\n * BID refused the exchange. `code` is BID's own error name (the part of\n * error_description before the colon, e.g. `no_rule_for_audience`), `status` the\n * HTTP status. A 4xx is PERMANENT for this request — fix the rule, do not retry.\n */\nexport class TicketExchangeError extends Error {\n constructor(message: string, readonly code: string, readonly status: number) {\n super(message);\n this.name = \"TicketExchangeError\";\n }\n}\n\n/** BID or the platform could not be reached, or answered 5xx. TRANSIENT — retry later. */\nexport class TicketUnavailableError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"TicketUnavailableError\";\n }\n}\n\nexport interface TicketClientOptions {\n issuer?: string;\n /** Renew this many seconds before exp. Default 30. */\n renewBeforeSec?: number;\n /** Injectable for tests. */\n env?: Record<string, string | undefined>;\n fetchImpl?: typeof fetch;\n now?: () => number;\n /** Ask Fly's machine API for an OIDC token. Default: POST over the /.fly/api unix socket. */\n flyOidc?: (aud: string) => Promise<string>;\n /** Whether the Fly socket is present. Default: checks /.fly/api. */\n onFly?: () => boolean;\n /**\n * F084.157 — ask BID for DPoP-BOUND tickets. One ES256 key per client\n * (non-extractable, never stored); every call then needs a proof, which\n * `authHeaders` makes. Default false: bearer tickets, exactly as before.\n */\n dpop?: boolean;\n}\n\n/** Headers for one call to a receiver. With `dpop`, `authorization` is `DPoP <ticket>` and `dpop` is the proof. */\nexport interface TicketAuthHeaders {\n authorization: string;\n dpop?: string;\n}\n\nexport interface TicketClient {\n /** A ticket for `audience` (BID's short name, e.g. \"discovery\"), from cache while it is fresh. */\n get(opts: { audience: string; scope?: string }): Promise<string>;\n /**\n * F084.157 — the headers for ONE request to a receiver: a ticket plus, with\n * `dpop`, a fresh proof bound to this method and URL (use it once). Without\n * `dpop`: `{ authorization: \"Bearer <ticket>\" }`.\n */\n authHeaders(opts: { audience: string; scope?: string; method: string; url: string }): Promise<TicketAuthHeaders>;\n}\n\nfunction flyOidcOverSocket(aud: string): Promise<string> {\n return new Promise((resolve, reject) => {\n const body = JSON.stringify({ aud });\n const req = request(\n { socketPath: FLY_SOCKET, path: \"/v1/tokens/oidc\", method: \"POST\", headers: { \"content-type\": \"application/json\", \"content-length\": Buffer.byteLength(body) } },\n (res) => {\n let data = \"\";\n res.setEncoding(\"utf8\");\n res.on(\"data\", (c) => (data += c));\n res.on(\"end\", () => {\n if ((res.statusCode ?? 0) >= 200 && (res.statusCode ?? 0) < 300) resolve(data.trim());\n else reject(new TicketUnavailableError(`Fly OIDC answered ${res.statusCode}`));\n });\n },\n );\n req.on(\"error\", (e) => reject(new TicketUnavailableError(`Fly OIDC socket: ${e.message}`)));\n req.end(body);\n });\n}\n\n/** Seconds since the epoch at which a JWT expires, or null if it cannot be read. */\nfunction jwtExp(token: string): number | null {\n try {\n const payload = JSON.parse(Buffer.from(token.split(\".\")[1] ?? \"\", \"base64url\").toString(\"utf8\"));\n return typeof payload.exp === \"number\" ? payload.exp : null;\n } catch {\n return null;\n }\n}\n\nexport function createTicketClient(options: TicketClientOptions = {}): TicketClient {\n const issuer = (options.issuer ?? DEFAULT_ISSUER).replace(/\\/+$/, \"\");\n const renewBeforeSec = options.renewBeforeSec ?? 30;\n const env = options.env ?? process.env;\n const fetchImpl = options.fetchImpl ?? fetch;\n const now = options.now ?? (() => Date.now());\n const flyOidc = options.flyOidc ?? flyOidcOverSocket;\n const onFly = options.onFly ?? (() => !!env.FLY_APP_NAME && existsSync(FLY_SOCKET));\n\n const cache = new Map<string, { token: string; exp: number }>();\n const inFlight = new Map<string, Promise<string>>();\n let dpopKey: Promise<DpopKey> | null = null;\n const ownKey = () => (dpopKey ??= createDpopKey());\n\n async function platformToken(): Promise<string> {\n if (onFly()) return flyOidc(issuer);\n const url = env.ACTIONS_ID_TOKEN_REQUEST_URL;\n const bearer = env.ACTIONS_ID_TOKEN_REQUEST_TOKEN;\n if (url && bearer) {\n let res: Response;\n try {\n res = await fetchImpl(`${url}&audience=${encodeURIComponent(issuer)}`, { headers: { authorization: `Bearer ${bearer}` } });\n } catch (e) {\n throw new TicketUnavailableError(`GitHub OIDC endpoint unreachable: ${e instanceof Error ? e.message : String(e)}`);\n }\n if (!res.ok) throw new TicketUnavailableError(`GitHub OIDC endpoint answered ${res.status}`);\n const { value } = (await res.json()) as { value?: string };\n if (!value) throw new TicketUnavailableError(\"GitHub OIDC endpoint returned no token\");\n return value;\n }\n throw new NoWorkloadIdentityError(\n \"No workload identity to exchange for a ticket: not on a Fly machine (FLY_APP_NAME + /.fly/api) and not in a GitHub Actions job \" +\n \"(ACTIONS_ID_TOKEN_REQUEST_URL/_TOKEN — add `permissions: id-token: write`). A Mac session keeps using its session key.\",\n );\n }\n\n async function exchange(audience: string, scope: string | undefined): Promise<{ token: string; exp: number }> {\n const subject = await platformToken();\n const form = new URLSearchParams({\n grant_type: \"urn:ietf:params:oauth:grant-type:token-exchange\",\n subject_token: subject,\n subject_token_type: \"urn:ietf:params:oauth:token-type:jwt\",\n audience,\n });\n if (scope) form.set(\"scope\", scope);\n let res: Response;\n try {\n const tokenUrl = `${issuer}/oauth2/token`;\n const headers: Record<string, string> = { \"content-type\": \"application/x-www-form-urlencoded\" };\n if (options.dpop) headers.dpop = await createDpopProof(await ownKey(), { method: \"POST\", url: tokenUrl, now });\n res = await fetchImpl(tokenUrl, { method: \"POST\", headers, body: form });\n } catch (e) {\n throw new TicketUnavailableError(`${issuer} unreachable: ${e instanceof Error ? e.message : String(e)}`);\n }\n let body: { access_token?: string; expires_in?: number; error?: string; error_description?: string } = {};\n try {\n body = (await res.json()) as typeof body;\n } catch {\n /* a non-JSON answer is handled by the status checks below */\n }\n if (res.status >= 500) throw new TicketUnavailableError(`${issuer} answered ${res.status}`);\n if (!res.ok || !body.access_token) {\n const desc = body.error_description ?? \"\";\n const code = desc.includes(\":\") ? desc.slice(0, desc.indexOf(\":\")).trim() : body.error ?? \"exchange_refused\";\n throw new TicketExchangeError(`BrobergID refused the ticket for ${audience}: ${desc || body.error || res.status}`, code, res.status);\n }\n const nowSec = Math.floor(now() / 1000);\n const exp = jwtExp(body.access_token) ?? nowSec + (body.expires_in ?? 300);\n return { token: body.access_token, exp };\n }\n\n const client: TicketClient = {\n async authHeaders({ audience, scope, method, url }) {\n const ticket = await client.get({ audience, scope });\n if (!options.dpop) return { authorization: `Bearer ${ticket}` };\n return { authorization: `DPoP ${ticket}`, dpop: await createDpopProof(await ownKey(), { method, url, ticket, now }) };\n },\n async get({ audience, scope }) {\n const key = `${audience} ${scope ?? \"\"}`;\n const hit = cache.get(key);\n if (hit && hit.exp - renewBeforeSec > now() / 1000) return hit.token;\n const pending = inFlight.get(key);\n if (pending) return pending;\n const p = exchange(audience, scope)\n .then((t) => {\n cache.set(key, t);\n return t.token;\n })\n .finally(() => inFlight.delete(key));\n inFlight.set(key, p);\n return p;\n },\n };\n return client;\n}\n\nlet shared: TicketClient | null = null;\n/** A ticket from the process-wide client (one cache per process). */\nexport function fetchTicket(opts: { audience: string; scope?: string }): Promise<string> {\n shared ??= createTicketClient();\n return shared.get(opts);\n}\n","/**\n * F084.153 — verify a BrobergID ticket LOCALLY (broberg-id-F087.4).\n *\n * A ticket is how one service or agent proves who it is to another without a\n * shared secret: BrobergID signs a short-lived JWT, the receiver checks it\n * against BID's PUBLIC keys. Nothing secret lives at the receiver.\n *\n * Format: broberg-id docs/features/F087.1-identitetsmodel.md §3 (draft, 8/10).\n * iss = the issuer · aud = the receiver's URL · scope = space-separated\n * sub = client_id = the caller · principal_type = human | service | agent\n * F084.159 — a USER ticket (BID F087.37): an app swapped its user's BID login\n * for a ticket to one receiver. sub = the USER, client_id/azp = the app,\n * principal_type = user. The app is mandatory there and never read from sub.\n * org · act {sub} only on delegation (RFC 8693) · exp/iat/jti\n *\n * This is deliberately NOT a method on createSsoClient: a service that only\n * RECEIVES tickets is not a login client — it has no client_id, no redirect,\n * no session. It needs the issuer, its own audience, and the key set.\n *\n * TWO FAILURES, TWO ANSWERS — keep them apart in the caller:\n * JwksUnavailableError → we could not ask BID right now. Answer 503 and let\n * the caller retry; the ticket may be perfectly valid.\n * SsoError → the ticket is not acceptable. Answer 401/403.\n * A known key is served from cache, so a ticket signed with it verifies while\n * BID is briefly unreachable.\n */\nimport { decodeProtectedHeader, jwtVerify, type JWTPayload } from \"jose\";\nimport { ALLOWED_ALGS, SsoError } from \"./client.js\";\nimport { createJwksCache, JwksUnavailableError, type JwksCache } from \"./jwks.js\";\nimport { createMemoryReplayStore, verifyDpopProof, type ReplayStore } from \"./dpop.js\";\n\nexport type PrincipalType = \"human\" | \"service\" | \"agent\" | \"user\";\nconst PRINCIPAL_TYPES: readonly PrincipalType[] = [\"human\", \"service\", \"agent\", \"user\"];\n\n/**\n * F084.156 — one link of an RFC 8693 delegation chain. `act` is the next link\n * outward: agent-b acting for agent-a acting for user-1 reads\n * `{ sub: \"agent-a\", act: { sub: \"user-1\" } }`. `act.sub` alone is the old shape.\n */\nexport interface TicketActor {\n sub: string;\n act?: TicketActor;\n}\n\n/** The newest ticket format version this package understands (BID sets `ver`). */\nexport const TICKET_FORMAT_VERSION = 1;\n/** Delegation deeper than this is refused rather than shortened. */\nexport const MAX_ACT_DEPTH = 5;\n\n/** What a verified ticket tells the receiver — a small, typed principal, never the raw payload. */\nexport interface TicketPrincipal {\n /** Who is calling: the ticket's `sub` — a client id such as `svc-trail`, or on a user ticket the USER's id. */\n principal: string;\n type: PrincipalType;\n /**\n * The client the ticket was issued to. Machine tickets: `client_id`, falling back to `sub`.\n * User tickets: `client_id`, falling back to `azp` — never `sub`, which is the user.\n */\n clientId: string;\n /** The organisation, when BID stated one. */\n org: string | null;\n /** On delegation: who the caller is acting for (RFC 8693 `act`), the WHOLE chain. */\n act: TicketActor | null;\n /** The ticket format version (`ver`); 0 for a ticket issued before BID set one. */\n version: number;\n /**\n * F084.156 — the DPoP key thumbprint when the ticket is sender-constrained.\n * Since 0.16.0 (F084.157) a ticket with cnf.jkt is only accepted together with\n * a valid DPoP proof for that key — see `verify(token, { dpop })`.\n */\n cnf: { jkt: string } | null;\n scopes: string[];\n /** Seconds since the epoch. */\n exp: number;\n jti: string;\n}\n\nexport interface TicketVerifierOptions {\n /** BID's issuer, exactly as it signs `iss` — e.g. `https://id.broberg.ai`. */\n issuer: string;\n /** THIS receiver's audience — its own URL, e.g. `https://discovery.broberg.ai`. */\n audience: string;\n /** The key set URL. Omitted: read once from the issuer's discovery document. */\n jwksUri?: string;\n /**\n * The longest lifetime (exp − iat) a ticket may claim. BID issues 5 min\n * (service) and 15 min (agent); anything longer was not minted by the policy\n * we were told about, so it is refused rather than trusted for longer.\n */\n maxLifetimeSec?: number;\n /** Seconds of clock skew to allow on exp/iat. Default 30. */\n clockToleranceSec?: number;\n /** Fetch the key set at construction, so the first caller does not wait. */\n warmUp?: boolean;\n fetchImpl?: typeof fetch;\n minRefetchIntervalMs?: number;\n /**\n * F084.157 — refuse UNBOUND tickets (bearer). Off by default during the\n * rollout. A BOUND ticket (cnf.jkt) needs a valid proof either way.\n */\n requireDpop?: boolean;\n /** Where used proof ids are remembered. Default in-memory — ONE machine only; share one across machines. */\n replayStore?: ReplayStore;\n /** How far a proof's iat may be from now. Default 60 s. */\n dpopIatWindowSec?: number;\n /** Injectable clock for the DPoP checks (ms). */\n now?: () => number;\n}\n\n/** The DPoP half of a request: the `DPoP` header, and the method + PUBLIC URL the receiver was called on. */\nexport interface DpopRequest {\n proof: string | null | undefined;\n method: string;\n url: string;\n}\n\nexport interface TicketVerifier {\n /**\n * Verify a ticket; with `scope`, also require that scope to be granted. Pass\n * `dpop` with the request's DPoP header, method and public URL — a bound ticket\n * is refused without it.\n */\n verify(token: string, options?: { scope?: string | string[]; dpop?: DpopRequest }): Promise<TicketPrincipal>;\n}\n\nexport function createTicketVerifier(options: TicketVerifierOptions): TicketVerifier {\n const {\n issuer,\n audience,\n maxLifetimeSec = 15 * 60,\n clockToleranceSec = 30,\n fetchImpl = fetch,\n requireDpop = false,\n dpopIatWindowSec = 60,\n now = () => Date.now(),\n } = options;\n const replayStore = options.replayStore ?? createMemoryReplayStore(now);\n if (!issuer) throw new SsoError(\"createTicketVerifier needs an issuer\");\n if (!audience) throw new SsoError(\"createTicketVerifier needs this receiver's audience\");\n\n let cachePromise: Promise<JwksCache> | null = null;\n const cacheFor = (jwksUri: string) =>\n createJwksCache({\n jwksUri,\n fetchImpl,\n ...(options.warmUp ? { warmUp: true } : {}),\n ...(options.minRefetchIntervalMs !== undefined ? { minRefetchIntervalMs: options.minRefetchIntervalMs } : {}),\n });\n\n async function keys(): Promise<JwksCache> {\n cachePromise ??= (async () => {\n if (options.jwksUri) return cacheFor(options.jwksUri);\n const url = `${issuer}/.well-known/openid-configuration`;\n let doc: { issuer?: string; jwks_uri?: string };\n try {\n const res = await fetchImpl(url);\n if (!res.ok) throw new Error(`answered ${res.status}`);\n doc = (await res.json()) as typeof doc;\n } catch (cause) {\n // Reached nothing usable: transient, the same class a key-set outage gets.\n throw new JwksUnavailableError(`${url}: ${cause instanceof Error ? cause.message : String(cause)}`);\n }\n if (doc.issuer !== issuer) {\n throw new SsoError(`issuer is ${issuer} but ${url} says ${doc.issuer} — they must match exactly`);\n }\n if (!doc.jwks_uri) throw new SsoError(`${url} names no jwks_uri`);\n return cacheFor(doc.jwks_uri);\n })().catch((err) => {\n cachePromise = null; // a later call retries instead of caching the failure\n throw err;\n });\n return cachePromise;\n }\n if (options.warmUp) void keys().catch(() => {});\n\n return {\n async verify(token, opts = {}) {\n let header;\n try {\n header = decodeProtectedHeader(token);\n } catch {\n throw new SsoError(\"ticket is not a JWS\");\n }\n if (!header.kid) throw new SsoError(\"ticket has no kid — cannot pick a signing key\");\n if (header.typ === \"logout+jwt\") throw new SsoError(\"a logout token is not a ticket\");\n\n const cache = await keys();\n let payload: JWTPayload;\n try {\n ({ payload } = await jwtVerify(token, async () => cache.getKey(header.kid!, header.alg ?? \"EdDSA\"), {\n issuer,\n audience,\n algorithms: ALLOWED_ALGS,\n clockTolerance: clockToleranceSec,\n requiredClaims: [\"exp\", \"iat\", \"jti\", \"sub\"],\n }));\n } catch (e) {\n // A key-set outage must surface as itself (→ 503), never as \"rejected\".\n if (e instanceof JwksUnavailableError) throw e;\n throw new SsoError(`ticket rejected: ${e instanceof Error ? e.message : String(e)}`);\n }\n\n // An ID token or a logout token must never pass as a ticket. They carry\n // no principal_type; a logout token carries events, an ID token a nonce.\n if (\"events\" in payload) throw new SsoError(\"a logout token is not a ticket\");\n if (\"nonce\" in payload) throw new SsoError(\"an ID token is not a ticket\");\n\n const type = payload.principal_type;\n if (typeof type !== \"string\" || !PRINCIPAL_TYPES.includes(type as PrincipalType)) {\n throw new SsoError(`ticket has no valid principal_type (got ${JSON.stringify(type)})`);\n }\n const lifetime = payload.exp! - payload.iat!;\n if (lifetime > maxLifetimeSec) {\n throw new SsoError(`ticket claims a ${lifetime}s lifetime; at most ${maxLifetimeSec}s is accepted`);\n }\n if (typeof payload.sub !== \"string\" || payload.sub === \"\") throw new SsoError(\"ticket has no sub\");\n\n const scopes = typeof payload.scope === \"string\" ? payload.scope.split(\" \").filter(Boolean) : [];\n const required = opts.scope === undefined ? [] : Array.isArray(opts.scope) ? opts.scope : [opts.scope];\n const missing = required.filter((s) => !scopes.includes(s));\n if (missing.length) throw new SsoError(`ticket lacks scope ${missing.join(\", \")}`);\n\n // F084.156 — ver: unknown future formats are refused by name, never read\n // with today's rules.\n const ver = payload.ver === undefined ? 0 : payload.ver;\n if (typeof ver !== \"number\" || !Number.isInteger(ver) || ver < 0) {\n throw new SsoError(`ticket has an invalid ver (got ${JSON.stringify(payload.ver)})`);\n }\n if (ver > TICKET_FORMAT_VERSION) {\n throw new SsoError(`ticket format version ${ver} is newer than this @broberg/sso understands (${TICKET_FORMAT_VERSION}) — upgrade @broberg/sso`);\n }\n // The whole chain, or a refusal. 0.14.2 kept only act.sub, cutting a chain\n // to its first link, and read a malformed act as \"no delegation\" — both in\n // the direction where the caller looks like it acts for fewer people.\n const act = payload.act === undefined ? null : readActor(payload.act, 1);\n const cnfRaw = payload.cnf as { jkt?: unknown } | undefined;\n const cnf = cnfRaw && typeof cnfRaw.jkt === \"string\" && cnfRaw.jkt ? { jkt: cnfRaw.jkt } : null;\n // F084.157 — a bound ticket needs its proof, always; requireDpop only\n // decides about unbound ones (and then a cnf it cannot read is refused too).\n if (cnf) {\n if (!opts.dpop?.proof) throw new SsoError(\"ticket is DPoP-bound (cnf.jkt) but no DPoP proof was presented\");\n await verifyDpopProof(opts.dpop.proof, {\n method: opts.dpop.method,\n url: opts.dpop.url,\n ticket: token,\n jkt: cnf.jkt,\n replay: replayStore,\n iatWindowSec: dpopIatWindowSec,\n now,\n });\n } else if (requireDpop) {\n throw new SsoError(cnfRaw !== undefined ? \"ticket has a cnf without a string jkt — DPoP is required here\" : \"this receiver requires DPoP; the ticket is not bound (no cnf.jkt)\");\n }\n // F084.159 — on a user ticket sub is the USER. Falling back to it would turn a\n // user id into an app id, so a receiver that requires clientId === \"trail-clipper\"\n // could be satisfied by a user who happens to be called that.\n const named = (v: unknown) => (typeof v === \"string\" && v ? v : null);\n const clientId =\n type === \"user\"\n ? named(payload.client_id) ?? named(payload.azp)\n : named(payload.client_id) ?? payload.sub;\n if (clientId === null) throw new SsoError(\"a user ticket names no app (no client_id or azp)\");\n return {\n principal: payload.sub,\n type: type as PrincipalType,\n clientId,\n org: typeof payload.org === \"string\" && payload.org ? payload.org : null,\n act,\n version: ver,\n cnf,\n scopes,\n exp: payload.exp!,\n jti: String(payload.jti),\n };\n },\n };\n}\n\nfunction readActor(raw: unknown, depth: number): TicketActor {\n if (depth > MAX_ACT_DEPTH) throw new SsoError(`ticket's delegation chain is deeper than ${MAX_ACT_DEPTH}`);\n const link = raw as { sub?: unknown; act?: unknown } | null;\n if (!link || typeof link !== \"object\" || typeof link.sub !== \"string\" || link.sub === \"\") {\n throw new SsoError(`ticket's act (link ${depth}) has no string sub`);\n }\n return link.act === undefined ? { sub: link.sub } : { sub: link.sub, act: readActor(link.act, depth + 1) };\n}\n"]}
1
+ {"version":3,"sources":["../src/dpop.ts","../src/fetch-ticket.ts","../src/ticket.ts"],"names":["generateKeyPair","exportJWK","calculateJwkThumbprint","SignJWT","decodeProtectedHeader","SsoError","importJWK","jwtVerify","request","existsSync","createJwksCache","JwksUnavailableError","ALLOWED_ALGS"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * F084.157 — DPoP (RFC 9449): a bound ticket works only for whoever holds the key\n * (broberg-id-F087.16, joint design #2572/#2574).\n *\n * A DPoP-bound ticket carries `cnf.jkt`, the thumbprint of the caller's public\n * key. With every request the caller signs a short PROOF (method, URL, time, a\n * hash of the ticket) with the matching private key. A ticket copied out of a log\n * is useless on another machine: it has the ticket, not the key.\n *\n * THE RULE THAT MAKES IT PROTECTION (agreed with broberg-id, (A) in #2574): once a\n * receiver verifies with this version, a ticket WITH cnf.jkt needs a valid proof —\n * also while DPoP is otherwise optional. `requireDpop` only decides whether\n * UNBOUND tickets are still accepted. Were bound tickets accepted without a proof\n * during the rollout, a stolen bound ticket would work as bearer the whole time.\n *\n * Not here yet: server nonces (RFC 9449 §8). The jti replay store covers replay\n * inside the iat window.\n */\nimport {\n SignJWT,\n calculateJwkThumbprint,\n decodeProtectedHeader,\n exportJWK,\n generateKeyPair,\n importJWK,\n jwtVerify,\n type JWK,\n} from \"jose\";\nimport { SsoError } from \"./client.js\";\n\n/** One process's DPoP key. The private half cannot be exported. */\nexport interface DpopKey {\n privateKey: CryptoKey;\n publicJwk: JWK;\n /** RFC 7638 thumbprint — what BID puts in the ticket's cnf.jkt. */\n jkt: string;\n}\n\n/** A fresh ES256 key pair, private key non-extractable, never written anywhere. */\nexport async function createDpopKey(): Promise<DpopKey> {\n const { privateKey, publicKey } = await generateKeyPair(\"ES256\", { extractable: false });\n const jwk = await exportJWK(publicKey); // a public key is always exportable\n const publicJwk: JWK = { kty: jwk.kty, crv: jwk.crv, x: jwk.x, y: jwk.y };\n return { privateKey, publicJwk, jkt: await calculateJwkThumbprint(publicJwk) };\n}\n\nconst enc = new TextEncoder();\nconst b64url = (bytes: ArrayBuffer) =>\n btoa(String.fromCharCode(...new Uint8Array(bytes))).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n\n/** `ath`: base64url(SHA-256(ticket)) — ties a proof to one ticket. */\nexport async function accessTokenHash(ticket: string): Promise<string> {\n return b64url(await crypto.subtle.digest(\"SHA-256\", enc.encode(ticket)));\n}\n\n/** RFC 9449 §4.3: htu is compared without query and fragment. */\nexport function normalizeHtu(url: string): string {\n const u = new URL(url);\n return `${u.protocol}//${u.host}${u.pathname}`;\n}\n\n/** Sign one proof. Pass `ticket` when calling a resource server (adds ath); omit it for BID's token endpoint. */\nexport async function createDpopProof(\n key: DpopKey,\n opts: { method: string; url: string; ticket?: string; now?: () => number },\n): Promise<string> {\n const payload: Record<string, unknown> = {\n jti: crypto.randomUUID(),\n htm: opts.method.toUpperCase(),\n htu: normalizeHtu(opts.url),\n iat: Math.floor((opts.now?.() ?? Date.now()) / 1000),\n };\n if (opts.ticket !== undefined) payload.ath = await accessTokenHash(opts.ticket);\n return new SignJWT(payload).setProtectedHeader({ typ: \"dpop+jwt\", alg: \"ES256\", jwk: key.publicJwk }).sign(key.privateKey);\n}\n\n/**\n * Remembers which proofs were already used. The default is in-memory, which\n * holds on ONE machine: a receiver running on two machines must pass a shared\n * store, or a proof replayed against the other machine inside the window passes.\n */\nexport interface ReplayStore {\n /** Record `key`; resolve true if it was already recorded within `ttlMs`. */\n seen(key: string, ttlMs: number): Promise<boolean>;\n}\n\nexport function createMemoryReplayStore(now: () => number = () => Date.now()): ReplayStore {\n const entries = new Map<string, number>();\n return {\n async seen(key, ttlMs) {\n const t = now();\n for (const [k, until] of entries) if (until <= t) entries.delete(k);\n if (entries.has(key)) return true;\n entries.set(key, t + ttlMs);\n return false;\n },\n };\n}\n\nexport interface VerifyProofOptions {\n method: string;\n /** The receiver's PUBLIC URL for this request (behind a proxy the process sees an internal one). */\n url: string;\n ticket: string;\n jkt: string;\n replay: ReplayStore;\n iatWindowSec: number;\n now: () => number;\n}\n\nconst ASYMMETRIC = new Set([\"ES256\", \"ES384\", \"ES512\", \"EdDSA\", \"PS256\", \"PS384\", \"PS512\", \"RS256\", \"RS384\", \"RS512\"]);\n\n/** Throws SsoError naming the first thing that is wrong. */\nexport async function verifyDpopProof(proof: string, o: VerifyProofOptions): Promise<void> {\n let header;\n try {\n header = decodeProtectedHeader(proof);\n } catch {\n throw new SsoError(\"DPoP proof is not a JWS\");\n }\n if (header.typ !== \"dpop+jwt\") throw new SsoError(`DPoP proof has typ ${JSON.stringify(header.typ)}, not \"dpop+jwt\"`);\n if (!header.alg || !ASYMMETRIC.has(header.alg)) throw new SsoError(`DPoP proof alg ${JSON.stringify(header.alg)} is not an accepted asymmetric algorithm`);\n const jwk = header.jwk as JWK | undefined;\n if (!jwk || typeof jwk !== \"object\") throw new SsoError(\"DPoP proof carries no jwk\");\n if (\"d\" in jwk) throw new SsoError(\"DPoP proof jwk contains a private key\");\n\n let payload;\n try {\n const key = await importJWK(jwk, header.alg);\n ({ payload } = await jwtVerify(proof, key, { typ: \"dpop+jwt\", algorithms: [header.alg] }));\n } catch (e) {\n throw new SsoError(`DPoP proof signature rejected: ${e instanceof Error ? e.message : String(e)}`);\n }\n\n if ((await calculateJwkThumbprint(jwk)) !== o.jkt) throw new SsoError(\"DPoP proof key does not match the ticket's cnf.jkt\");\n if (payload.htm !== o.method.toUpperCase()) throw new SsoError(`DPoP proof is for ${JSON.stringify(payload.htm)}, the request is ${o.method.toUpperCase()}`);\n let htu: string;\n try {\n htu = normalizeHtu(String(payload.htu));\n } catch {\n throw new SsoError(\"DPoP proof htu is not a URL\");\n }\n if (htu !== normalizeHtu(o.url)) throw new SsoError(`DPoP proof is for ${htu}, the request is ${normalizeHtu(o.url)}`);\n const nowSec = Math.floor(o.now() / 1000);\n if (typeof payload.iat !== \"number\" || Math.abs(nowSec - payload.iat) > o.iatWindowSec) {\n throw new SsoError(`DPoP proof iat is outside ±${o.iatWindowSec}s`);\n }\n if (payload.ath !== (await accessTokenHash(o.ticket))) throw new SsoError(\"DPoP proof ath does not match this ticket\");\n if (typeof payload.jti !== \"string\" || payload.jti === \"\") throw new SsoError(\"DPoP proof has no jti\");\n if (await o.replay.seen(`${o.jkt}:${payload.jti}`, o.iatWindowSec * 2 * 1000)) {\n throw new SsoError(\"DPoP proof was already used (jti replay)\");\n }\n}\n","/**\n * F084.154 — fetch a BrobergID ticket WITHOUT a key (broberg-id-F087.10/.11).\n *\n * The sending half of F084.153: a workload proves who it is with the identity its\n * platform already gives it, and BID exchanges that for a short-lived ticket\n * (RFC 8693 token exchange). No secret is stored anywhere.\n *\n * Fly.io POST unix:/.fly/api /v1/tokens/oidc {aud: issuer}\n * GitHub Actions GET $ACTIONS_ID_TOKEN_REQUEST_URL&audience=issuer\n * (needs `permissions: id-token: write` in the workflow)\n * then POST {issuer}/oauth2/token grant_type=…token-exchange\n *\n * Reference implementation: broberg-id/.github/workflows/ticket-probe.yml.\n * The ticket itself is never logged or put in an error message.\n */\nimport { existsSync } from \"node:fs\";\nimport { request } from \"node:http\";\nimport { createDpopKey, createDpopProof, type DpopKey } from \"./dpop.js\";\n\nexport const DEFAULT_ISSUER = \"https://id.broberg.ai\";\nconst FLY_SOCKET = \"/.fly/api\";\n\n/** No platform identity to exchange: not on Fly, not in a GitHub Actions job with id-token: write. */\nexport class NoWorkloadIdentityError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"NoWorkloadIdentityError\";\n }\n}\n\n/**\n * BID refused the exchange. `code` is BID's own error name (the part of\n * error_description before the colon, e.g. `no_rule_for_audience`), `status` the\n * HTTP status. A 4xx is PERMANENT for this request — fix the rule, do not retry.\n */\nexport class TicketExchangeError extends Error {\n constructor(message: string, readonly code: string, readonly status: number) {\n super(message);\n this.name = \"TicketExchangeError\";\n }\n}\n\n/** BID or the platform could not be reached, or answered 5xx. TRANSIENT — retry later. */\nexport class TicketUnavailableError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"TicketUnavailableError\";\n }\n}\n\nexport interface TicketClientOptions {\n issuer?: string;\n /** Renew this many seconds before exp. Default 30. */\n renewBeforeSec?: number;\n /** Injectable for tests. */\n env?: Record<string, string | undefined>;\n fetchImpl?: typeof fetch;\n now?: () => number;\n /** Ask Fly's machine API for an OIDC token. Default: POST over the /.fly/api unix socket. */\n flyOidc?: (aud: string) => Promise<string>;\n /** Whether the Fly socket is present. Default: checks /.fly/api. */\n onFly?: () => boolean;\n /**\n * F084.157 — ask BID for DPoP-BOUND tickets. One ES256 key per client\n * (non-extractable, never stored); every call then needs a proof, which\n * `authHeaders` makes. Default false: bearer tickets, exactly as before.\n */\n dpop?: boolean;\n}\n\n/** Headers for one call to a receiver. With `dpop`, `authorization` is `DPoP <ticket>` and `dpop` is the proof. */\nexport interface TicketAuthHeaders {\n authorization: string;\n dpop?: string;\n}\n\nexport interface TicketClient {\n /** A ticket for `audience` (BID's short name, e.g. \"discovery\"), from cache while it is fresh. */\n get(opts: { audience: string; scope?: string }): Promise<string>;\n /**\n * F084.157 — the headers for ONE request to a receiver: a ticket plus, with\n * `dpop`, a fresh proof bound to this method and URL (use it once). Without\n * `dpop`: `{ authorization: \"Bearer <ticket>\" }`.\n */\n authHeaders(opts: { audience: string; scope?: string; method: string; url: string }): Promise<TicketAuthHeaders>;\n}\n\nfunction flyOidcOverSocket(aud: string): Promise<string> {\n return new Promise((resolve, reject) => {\n const body = JSON.stringify({ aud });\n const req = request(\n { socketPath: FLY_SOCKET, path: \"/v1/tokens/oidc\", method: \"POST\", headers: { \"content-type\": \"application/json\", \"content-length\": Buffer.byteLength(body) } },\n (res) => {\n let data = \"\";\n res.setEncoding(\"utf8\");\n res.on(\"data\", (c) => (data += c));\n res.on(\"end\", () => {\n if ((res.statusCode ?? 0) >= 200 && (res.statusCode ?? 0) < 300) resolve(data.trim());\n else reject(new TicketUnavailableError(`Fly OIDC answered ${res.statusCode}`));\n });\n },\n );\n req.on(\"error\", (e) => reject(new TicketUnavailableError(`Fly OIDC socket: ${e.message}`)));\n req.end(body);\n });\n}\n\n/** Seconds since the epoch at which a JWT expires, or null if it cannot be read. */\nfunction jwtExp(token: string): number | null {\n try {\n const payload = JSON.parse(Buffer.from(token.split(\".\")[1] ?? \"\", \"base64url\").toString(\"utf8\"));\n return typeof payload.exp === \"number\" ? payload.exp : null;\n } catch {\n return null;\n }\n}\n\nexport function createTicketClient(options: TicketClientOptions = {}): TicketClient {\n const issuer = (options.issuer ?? DEFAULT_ISSUER).replace(/\\/+$/, \"\");\n const renewBeforeSec = options.renewBeforeSec ?? 30;\n const env = options.env ?? process.env;\n const fetchImpl = options.fetchImpl ?? fetch;\n const now = options.now ?? (() => Date.now());\n const flyOidc = options.flyOidc ?? flyOidcOverSocket;\n const onFly = options.onFly ?? (() => !!env.FLY_APP_NAME && existsSync(FLY_SOCKET));\n\n const cache = new Map<string, { token: string; exp: number }>();\n const inFlight = new Map<string, Promise<string>>();\n let dpopKey: Promise<DpopKey> | null = null;\n const ownKey = () => (dpopKey ??= createDpopKey());\n\n async function platformToken(): Promise<string> {\n if (onFly()) return flyOidc(issuer);\n const url = env.ACTIONS_ID_TOKEN_REQUEST_URL;\n const bearer = env.ACTIONS_ID_TOKEN_REQUEST_TOKEN;\n if (url && bearer) {\n let res: Response;\n try {\n res = await fetchImpl(`${url}&audience=${encodeURIComponent(issuer)}`, { headers: { authorization: `Bearer ${bearer}` } });\n } catch (e) {\n throw new TicketUnavailableError(`GitHub OIDC endpoint unreachable: ${e instanceof Error ? e.message : String(e)}`);\n }\n if (!res.ok) throw new TicketUnavailableError(`GitHub OIDC endpoint answered ${res.status}`);\n const { value } = (await res.json()) as { value?: string };\n if (!value) throw new TicketUnavailableError(\"GitHub OIDC endpoint returned no token\");\n return value;\n }\n throw new NoWorkloadIdentityError(\n \"No workload identity to exchange for a ticket: not on a Fly machine (FLY_APP_NAME + /.fly/api) and not in a GitHub Actions job \" +\n \"(ACTIONS_ID_TOKEN_REQUEST_URL/_TOKEN — add `permissions: id-token: write`). A Mac session keeps using its session key.\",\n );\n }\n\n async function exchange(audience: string, scope: string | undefined): Promise<{ token: string; exp: number }> {\n const subject = await platformToken();\n const form = new URLSearchParams({\n grant_type: \"urn:ietf:params:oauth:grant-type:token-exchange\",\n subject_token: subject,\n subject_token_type: \"urn:ietf:params:oauth:token-type:jwt\",\n audience,\n });\n if (scope) form.set(\"scope\", scope);\n let res: Response;\n try {\n const tokenUrl = `${issuer}/oauth2/token`;\n const headers: Record<string, string> = { \"content-type\": \"application/x-www-form-urlencoded\" };\n if (options.dpop) headers.dpop = await createDpopProof(await ownKey(), { method: \"POST\", url: tokenUrl, now });\n res = await fetchImpl(tokenUrl, { method: \"POST\", headers, body: form });\n } catch (e) {\n throw new TicketUnavailableError(`${issuer} unreachable: ${e instanceof Error ? e.message : String(e)}`);\n }\n let body: { access_token?: string; expires_in?: number; error?: string; error_description?: string } = {};\n try {\n body = (await res.json()) as typeof body;\n } catch {\n /* a non-JSON answer is handled by the status checks below */\n }\n if (res.status >= 500) throw new TicketUnavailableError(`${issuer} answered ${res.status}`);\n if (!res.ok || !body.access_token) {\n const desc = body.error_description ?? \"\";\n const code = desc.includes(\":\") ? desc.slice(0, desc.indexOf(\":\")).trim() : body.error ?? \"exchange_refused\";\n throw new TicketExchangeError(`BID refused the ticket for ${audience}: ${desc || body.error || res.status}`, code, res.status);\n }\n const nowSec = Math.floor(now() / 1000);\n const exp = jwtExp(body.access_token) ?? nowSec + (body.expires_in ?? 300);\n return { token: body.access_token, exp };\n }\n\n const client: TicketClient = {\n async authHeaders({ audience, scope, method, url }) {\n const ticket = await client.get({ audience, scope });\n if (!options.dpop) return { authorization: `Bearer ${ticket}` };\n return { authorization: `DPoP ${ticket}`, dpop: await createDpopProof(await ownKey(), { method, url, ticket, now }) };\n },\n async get({ audience, scope }) {\n const key = `${audience} ${scope ?? \"\"}`;\n const hit = cache.get(key);\n if (hit && hit.exp - renewBeforeSec > now() / 1000) return hit.token;\n const pending = inFlight.get(key);\n if (pending) return pending;\n const p = exchange(audience, scope)\n .then((t) => {\n cache.set(key, t);\n return t.token;\n })\n .finally(() => inFlight.delete(key));\n inFlight.set(key, p);\n return p;\n },\n };\n return client;\n}\n\nlet shared: TicketClient | null = null;\n/** A ticket from the process-wide client (one cache per process). */\nexport function fetchTicket(opts: { audience: string; scope?: string }): Promise<string> {\n shared ??= createTicketClient();\n return shared.get(opts);\n}\n","/**\n * F084.153 — verify a BrobergID ticket LOCALLY (broberg-id-F087.4).\n *\n * A ticket is how one service or agent proves who it is to another without a\n * shared secret: BrobergID signs a short-lived JWT, the receiver checks it\n * against BID's PUBLIC keys. Nothing secret lives at the receiver.\n *\n * Format: broberg-id docs/features/F087.1-identitetsmodel.md §3 (draft, 8/10).\n * iss = the issuer · aud = the receiver's URL · scope = space-separated\n * sub = client_id = the caller · principal_type = human | service | agent\n * F084.159 — a USER ticket (BID F087.37): an app swapped its user's BID login\n * for a ticket to one receiver. sub = the USER, client_id/azp = the app,\n * principal_type = user. The app is mandatory there and never read from sub.\n * org · act {sub} only on delegation (RFC 8693) · exp/iat/jti\n *\n * This is deliberately NOT a method on createSsoClient: a service that only\n * RECEIVES tickets is not a login client — it has no client_id, no redirect,\n * no session. It needs the issuer, its own audience, and the key set.\n *\n * TWO FAILURES, TWO ANSWERS — keep them apart in the caller:\n * JwksUnavailableError → we could not ask BID right now. Answer 503 and let\n * the caller retry; the ticket may be perfectly valid.\n * SsoError → the ticket is not acceptable. Answer 401/403.\n * A known key is served from cache, so a ticket signed with it verifies while\n * BID is briefly unreachable.\n */\nimport { decodeProtectedHeader, jwtVerify, type JWTPayload } from \"jose\";\nimport { ALLOWED_ALGS, SsoError } from \"./client.js\";\nimport { createJwksCache, JwksUnavailableError, type JwksCache } from \"./jwks.js\";\nimport { createMemoryReplayStore, verifyDpopProof, type ReplayStore } from \"./dpop.js\";\n\nexport type PrincipalType = \"human\" | \"service\" | \"agent\" | \"user\";\nconst PRINCIPAL_TYPES: readonly PrincipalType[] = [\"human\", \"service\", \"agent\", \"user\"];\n\n/**\n * F084.156 — one link of an RFC 8693 delegation chain. `act` is the next link\n * outward: agent-b acting for agent-a acting for user-1 reads\n * `{ sub: \"agent-a\", act: { sub: \"user-1\" } }`. `act.sub` alone is the old shape.\n */\nexport interface TicketActor {\n sub: string;\n act?: TicketActor;\n}\n\n/** The newest ticket format version this package understands (BID sets `ver`). */\nexport const TICKET_FORMAT_VERSION = 1;\n/** Delegation deeper than this is refused rather than shortened. */\nexport const MAX_ACT_DEPTH = 5;\n\n/** What a verified ticket tells the receiver — a small, typed principal, never the raw payload. */\nexport interface TicketPrincipal {\n /** Who is calling: the ticket's `sub` — a client id such as `svc-trail`, or on a user ticket the USER's id. */\n principal: string;\n type: PrincipalType;\n /**\n * The client the ticket was issued to. Machine tickets: `client_id`, falling back to `sub`.\n * User tickets: `client_id`, falling back to `azp` — never `sub`, which is the user.\n */\n clientId: string;\n /** The organisation, when BID stated one. */\n org: string | null;\n /** On delegation: who the caller is acting for (RFC 8693 `act`), the WHOLE chain. */\n act: TicketActor | null;\n /** The ticket format version (`ver`); 0 for a ticket issued before BID set one. */\n version: number;\n /**\n * F084.156 — the DPoP key thumbprint when the ticket is sender-constrained.\n * Since 0.16.0 (F084.157) a ticket with cnf.jkt is only accepted together with\n * a valid DPoP proof for that key — see `verify(token, { dpop })`.\n */\n cnf: { jkt: string } | null;\n scopes: string[];\n /** Seconds since the epoch. */\n exp: number;\n jti: string;\n}\n\nexport interface TicketVerifierOptions {\n /** BID's issuer, exactly as it signs `iss` — e.g. `https://id.broberg.ai`. */\n issuer: string;\n /** THIS receiver's audience — its own URL, e.g. `https://discovery.broberg.ai`. */\n audience: string;\n /** The key set URL. Omitted: read once from the issuer's discovery document. */\n jwksUri?: string;\n /**\n * The longest lifetime (exp − iat) a ticket may claim. BID issues 5 min\n * (service) and 15 min (agent); anything longer was not minted by the policy\n * we were told about, so it is refused rather than trusted for longer.\n */\n maxLifetimeSec?: number;\n /** Seconds of clock skew to allow on exp/iat. Default 30. */\n clockToleranceSec?: number;\n /** Fetch the key set at construction, so the first caller does not wait. */\n warmUp?: boolean;\n fetchImpl?: typeof fetch;\n minRefetchIntervalMs?: number;\n /**\n * F084.157 — refuse UNBOUND tickets (bearer). Off by default during the\n * rollout. A BOUND ticket (cnf.jkt) needs a valid proof either way.\n */\n requireDpop?: boolean;\n /** Where used proof ids are remembered. Default in-memory — ONE machine only; share one across machines. */\n replayStore?: ReplayStore;\n /** How far a proof's iat may be from now. Default 60 s. */\n dpopIatWindowSec?: number;\n /** Injectable clock for the DPoP checks (ms). */\n now?: () => number;\n}\n\n/** The DPoP half of a request: the `DPoP` header, and the method + PUBLIC URL the receiver was called on. */\nexport interface DpopRequest {\n proof: string | null | undefined;\n method: string;\n url: string;\n}\n\nexport interface TicketVerifier {\n /**\n * Verify a ticket; with `scope`, also require that scope to be granted. Pass\n * `dpop` with the request's DPoP header, method and public URL — a bound ticket\n * is refused without it.\n */\n verify(token: string, options?: { scope?: string | string[]; dpop?: DpopRequest }): Promise<TicketPrincipal>;\n}\n\nexport function createTicketVerifier(options: TicketVerifierOptions): TicketVerifier {\n const {\n issuer,\n audience,\n maxLifetimeSec = 15 * 60,\n clockToleranceSec = 30,\n fetchImpl = fetch,\n requireDpop = false,\n dpopIatWindowSec = 60,\n now = () => Date.now(),\n } = options;\n const replayStore = options.replayStore ?? createMemoryReplayStore(now);\n if (!issuer) throw new SsoError(\"createTicketVerifier needs an issuer\");\n if (!audience) throw new SsoError(\"createTicketVerifier needs this receiver's audience\");\n\n let cachePromise: Promise<JwksCache> | null = null;\n const cacheFor = (jwksUri: string) =>\n createJwksCache({\n jwksUri,\n fetchImpl,\n ...(options.warmUp ? { warmUp: true } : {}),\n ...(options.minRefetchIntervalMs !== undefined ? { minRefetchIntervalMs: options.minRefetchIntervalMs } : {}),\n });\n\n async function keys(): Promise<JwksCache> {\n cachePromise ??= (async () => {\n if (options.jwksUri) return cacheFor(options.jwksUri);\n const url = `${issuer}/.well-known/openid-configuration`;\n let doc: { issuer?: string; jwks_uri?: string };\n try {\n const res = await fetchImpl(url);\n if (!res.ok) throw new Error(`answered ${res.status}`);\n doc = (await res.json()) as typeof doc;\n } catch (cause) {\n // Reached nothing usable: transient, the same class a key-set outage gets.\n throw new JwksUnavailableError(`${url}: ${cause instanceof Error ? cause.message : String(cause)}`);\n }\n if (doc.issuer !== issuer) {\n throw new SsoError(`issuer is ${issuer} but ${url} says ${doc.issuer} — they must match exactly`);\n }\n if (!doc.jwks_uri) throw new SsoError(`${url} names no jwks_uri`);\n return cacheFor(doc.jwks_uri);\n })().catch((err) => {\n cachePromise = null; // a later call retries instead of caching the failure\n throw err;\n });\n return cachePromise;\n }\n if (options.warmUp) void keys().catch(() => {});\n\n return {\n async verify(token, opts = {}) {\n let header;\n try {\n header = decodeProtectedHeader(token);\n } catch {\n throw new SsoError(\"ticket is not a JWS\");\n }\n if (!header.kid) throw new SsoError(\"ticket has no kid — cannot pick a signing key\");\n if (header.typ === \"logout+jwt\") throw new SsoError(\"a logout token is not a ticket\");\n\n const cache = await keys();\n let payload: JWTPayload;\n try {\n ({ payload } = await jwtVerify(token, async () => cache.getKey(header.kid!, header.alg ?? \"EdDSA\"), {\n issuer,\n audience,\n algorithms: ALLOWED_ALGS,\n clockTolerance: clockToleranceSec,\n requiredClaims: [\"exp\", \"iat\", \"jti\", \"sub\"],\n }));\n } catch (e) {\n // A key-set outage must surface as itself (→ 503), never as \"rejected\".\n if (e instanceof JwksUnavailableError) throw e;\n throw new SsoError(`ticket rejected: ${e instanceof Error ? e.message : String(e)}`);\n }\n\n // An ID token or a logout token must never pass as a ticket. They carry\n // no principal_type; a logout token carries events, an ID token a nonce.\n if (\"events\" in payload) throw new SsoError(\"a logout token is not a ticket\");\n if (\"nonce\" in payload) throw new SsoError(\"an ID token is not a ticket\");\n\n const type = payload.principal_type;\n if (typeof type !== \"string\" || !PRINCIPAL_TYPES.includes(type as PrincipalType)) {\n throw new SsoError(`ticket has no valid principal_type (got ${JSON.stringify(type)})`);\n }\n const lifetime = payload.exp! - payload.iat!;\n if (lifetime > maxLifetimeSec) {\n throw new SsoError(`ticket claims a ${lifetime}s lifetime; at most ${maxLifetimeSec}s is accepted`);\n }\n if (typeof payload.sub !== \"string\" || payload.sub === \"\") throw new SsoError(\"ticket has no sub\");\n\n const scopes = typeof payload.scope === \"string\" ? payload.scope.split(\" \").filter(Boolean) : [];\n const required = opts.scope === undefined ? [] : Array.isArray(opts.scope) ? opts.scope : [opts.scope];\n const missing = required.filter((s) => !scopes.includes(s));\n if (missing.length) throw new SsoError(`ticket lacks scope ${missing.join(\", \")}`);\n\n // F084.156 — ver: unknown future formats are refused by name, never read\n // with today's rules.\n const ver = payload.ver === undefined ? 0 : payload.ver;\n if (typeof ver !== \"number\" || !Number.isInteger(ver) || ver < 0) {\n throw new SsoError(`ticket has an invalid ver (got ${JSON.stringify(payload.ver)})`);\n }\n if (ver > TICKET_FORMAT_VERSION) {\n throw new SsoError(`ticket format version ${ver} is newer than this @broberg/sso understands (${TICKET_FORMAT_VERSION}) — upgrade @broberg/sso`);\n }\n // The whole chain, or a refusal. 0.14.2 kept only act.sub, cutting a chain\n // to its first link, and read a malformed act as \"no delegation\" — both in\n // the direction where the caller looks like it acts for fewer people.\n const act = payload.act === undefined ? null : readActor(payload.act, 1);\n const cnfRaw = payload.cnf as { jkt?: unknown } | undefined;\n const cnf = cnfRaw && typeof cnfRaw.jkt === \"string\" && cnfRaw.jkt ? { jkt: cnfRaw.jkt } : null;\n // F084.157 — a bound ticket needs its proof, always; requireDpop only\n // decides about unbound ones (and then a cnf it cannot read is refused too).\n if (cnf) {\n if (!opts.dpop?.proof) throw new SsoError(\"ticket is DPoP-bound (cnf.jkt) but no DPoP proof was presented\");\n await verifyDpopProof(opts.dpop.proof, {\n method: opts.dpop.method,\n url: opts.dpop.url,\n ticket: token,\n jkt: cnf.jkt,\n replay: replayStore,\n iatWindowSec: dpopIatWindowSec,\n now,\n });\n } else if (requireDpop) {\n throw new SsoError(cnfRaw !== undefined ? \"ticket has a cnf without a string jkt — DPoP is required here\" : \"this receiver requires DPoP; the ticket is not bound (no cnf.jkt)\");\n }\n // F084.159 — on a user ticket sub is the USER. Falling back to it would turn a\n // user id into an app id, so a receiver that requires clientId === \"trail-clipper\"\n // could be satisfied by a user who happens to be called that.\n const named = (v: unknown) => (typeof v === \"string\" && v ? v : null);\n const clientId =\n type === \"user\"\n ? named(payload.client_id) ?? named(payload.azp)\n : named(payload.client_id) ?? payload.sub;\n if (clientId === null) throw new SsoError(\"a user ticket names no app (no client_id or azp)\");\n return {\n principal: payload.sub,\n type: type as PrincipalType,\n clientId,\n org: typeof payload.org === \"string\" && payload.org ? payload.org : null,\n act,\n version: ver,\n cnf,\n scopes,\n exp: payload.exp!,\n jti: String(payload.jti),\n };\n },\n };\n}\n\nfunction readActor(raw: unknown, depth: number): TicketActor {\n if (depth > MAX_ACT_DEPTH) throw new SsoError(`ticket's delegation chain is deeper than ${MAX_ACT_DEPTH}`);\n const link = raw as { sub?: unknown; act?: unknown } | null;\n if (!link || typeof link !== \"object\" || typeof link.sub !== \"string\" || link.sub === \"\") {\n throw new SsoError(`ticket's act (link ${depth}) has no string sub`);\n }\n return link.act === undefined ? { sub: link.sub } : { sub: link.sub, act: readActor(link.act, depth + 1) };\n}\n"]}
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { SsoError, ALLOWED_ALGS, JwksUnavailableError, createJwksCache } from './chunk-RWTUJPV3.js';
2
- export { AVATAR_TYPES, DEFAULT_SESSION_MAX_AGE, JwksError, JwksUnavailableError, JwksUnknownKeyError, MAX_AVATAR_BYTES, MAX_INVITATIONS, SsoAppApiError, SsoAvatarRejectedError, SsoConfigError, SsoError, SsoInsufficientScopeError, SsoIntrospectionUnavailableError, SsoReauthError, SsoTokenInactiveError, cookieHeader, createJwksCache, createSsoClient, loadSsoConfig, memoryTokenStore, readCookie, signSession, signValue, verifySession, verifyValue } from './chunk-RWTUJPV3.js';
1
+ import { SsoError, ALLOWED_ALGS, JwksUnavailableError, createJwksCache } from './chunk-XKKKS2RO.js';
2
+ export { AVATAR_TYPES, DEFAULT_SESSION_MAX_AGE, JwksError, JwksUnavailableError, JwksUnknownKeyError, MAX_AVATAR_BYTES, MAX_INVITATIONS, SsoAppApiError, SsoAvatarRejectedError, SsoConfigError, SsoError, SsoInsufficientScopeError, SsoIntrospectionUnavailableError, SsoReauthError, SsoTokenInactiveError, cookieHeader, createJwksCache, createSsoClient, loadSsoConfig, memoryTokenStore, readCookie, signSession, signValue, verifySession, verifyValue } from './chunk-XKKKS2RO.js';
3
3
  import { existsSync } from 'fs';
4
4
  import { request } from 'http';
5
5
  import { generateKeyPair, exportJWK, calculateJwkThumbprint, SignJWT, decodeProtectedHeader, importJWK, jwtVerify } from 'jose';
@@ -192,7 +192,7 @@ function createTicketClient(options = {}) {
192
192
  if (!res.ok || !body.access_token) {
193
193
  const desc = body.error_description ?? "";
194
194
  const code = desc.includes(":") ? desc.slice(0, desc.indexOf(":")).trim() : body.error ?? "exchange_refused";
195
- throw new TicketExchangeError(`BrobergID refused the ticket for ${audience}: ${desc || body.error || res.status}`, code, res.status);
195
+ throw new TicketExchangeError(`BID refused the ticket for ${audience}: ${desc || body.error || res.status}`, code, res.status);
196
196
  }
197
197
  const nowSec = Math.floor(now() / 1e3);
198
198
  const exp = jwtExp(body.access_token) ?? nowSec + (body.expires_in ?? 300);