@broberg/sso 0.18.3 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkCHRCHUZ3_cjs = require('./chunk-CHRCHUZ3.cjs');
3
+ var chunkMZE4TPFU_cjs = require('./chunk-MZE4TPFU.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 chunkCHRCHUZ3_cjs.SsoError("DPoP proof is not a JWS");
51
+ throw new chunkMZE4TPFU_cjs.SsoError("DPoP proof is not a JWS");
52
52
  }
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`);
53
+ if (header.typ !== "dpop+jwt") throw new chunkMZE4TPFU_cjs.SsoError(`DPoP proof has typ ${JSON.stringify(header.typ)}, not "dpop+jwt"`);
54
+ if (!header.alg || !ASYMMETRIC.has(header.alg)) throw new chunkMZE4TPFU_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 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");
56
+ if (!jwk || typeof jwk !== "object") throw new chunkMZE4TPFU_cjs.SsoError("DPoP proof carries no jwk");
57
+ if ("d" in jwk) throw new chunkMZE4TPFU_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 chunkCHRCHUZ3_cjs.SsoError(`DPoP proof signature rejected: ${e instanceof Error ? e.message : String(e)}`);
63
+ throw new chunkMZE4TPFU_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 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()}`);
65
+ if (await jose.calculateJwkThumbprint(jwk) !== o.jkt) throw new chunkMZE4TPFU_cjs.SsoError("DPoP proof key does not match the ticket's cnf.jkt");
66
+ if (payload.htm !== o.method.toUpperCase()) throw new chunkMZE4TPFU_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 chunkCHRCHUZ3_cjs.SsoError("DPoP proof htu is not a URL");
71
+ throw new chunkMZE4TPFU_cjs.SsoError("DPoP proof htu is not a URL");
72
72
  }
73
- if (htu !== normalizeHtu(o.url)) throw new chunkCHRCHUZ3_cjs.SsoError(`DPoP proof is for ${htu}, the request is ${normalizeHtu(o.url)}`);
73
+ if (htu !== normalizeHtu(o.url)) throw new chunkMZE4TPFU_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 chunkCHRCHUZ3_cjs.SsoError(`DPoP proof iat is outside \xB1${o.iatWindowSec}s`);
76
+ throw new chunkMZE4TPFU_cjs.SsoError(`DPoP proof iat is outside \xB1${o.iatWindowSec}s`);
77
77
  }
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");
78
+ if (payload.ath !== await accessTokenHash(o.ticket)) throw new chunkMZE4TPFU_cjs.SsoError("DPoP proof ath does not match this ticket");
79
+ if (typeof payload.jti !== "string" || payload.jti === "") throw new chunkMZE4TPFU_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 chunkCHRCHUZ3_cjs.SsoError("DPoP proof was already used (jti replay)");
81
+ throw new chunkMZE4TPFU_cjs.SsoError("DPoP proof was already used (jti replay)");
82
82
  }
83
83
  }
84
84
 
@@ -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 chunkCHRCHUZ3_cjs.SsoError("createTicketVerifier needs an issuer");
245
- if (!audience) throw new chunkCHRCHUZ3_cjs.SsoError("createTicketVerifier needs this receiver's audience");
244
+ if (!issuer) throw new chunkMZE4TPFU_cjs.SsoError("createTicketVerifier needs an issuer");
245
+ if (!audience) throw new chunkMZE4TPFU_cjs.SsoError("createTicketVerifier needs this receiver's audience");
246
246
  let cachePromise = null;
247
- const cacheFor = (jwksUri) => chunkCHRCHUZ3_cjs.createJwksCache({
247
+ const cacheFor = (jwksUri) => chunkMZE4TPFU_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 chunkCHRCHUZ3_cjs.JwksUnavailableError(`${url}: ${cause instanceof Error ? cause.message : String(cause)}`);
263
+ throw new chunkMZE4TPFU_cjs.JwksUnavailableError(`${url}: ${cause instanceof Error ? cause.message : String(cause)}`);
264
264
  }
265
265
  if (doc.issuer !== issuer) {
266
- throw new chunkCHRCHUZ3_cjs.SsoError(`issuer is ${issuer} but ${url} says ${doc.issuer} \u2014 they must match exactly`);
266
+ throw new chunkMZE4TPFU_cjs.SsoError(`issuer is ${issuer} but ${url} says ${doc.issuer} \u2014 they must match exactly`);
267
267
  }
268
- if (!doc.jwks_uri) throw new chunkCHRCHUZ3_cjs.SsoError(`${url} names no jwks_uri`);
268
+ if (!doc.jwks_uri) throw new chunkMZE4TPFU_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 chunkCHRCHUZ3_cjs.SsoError("ticket is not a JWS");
284
+ throw new chunkMZE4TPFU_cjs.SsoError("ticket is not a JWS");
285
285
  }
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");
286
+ if (!header.kid) throw new chunkMZE4TPFU_cjs.SsoError("ticket has no kid \u2014 cannot pick a signing key");
287
+ if (header.typ === "logout+jwt") throw new chunkMZE4TPFU_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: chunkCHRCHUZ3_cjs.ALLOWED_ALGS,
294
+ algorithms: chunkMZE4TPFU_cjs.ALLOWED_ALGS,
295
295
  clockTolerance: clockToleranceSec,
296
296
  requiredClaims: ["exp", "iat", "jti", "sub"]
297
297
  }));
298
298
  } catch (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)}`);
299
+ if (e instanceof chunkMZE4TPFU_cjs.JwksUnavailableError) throw e;
300
+ throw new chunkMZE4TPFU_cjs.SsoError(`ticket rejected: ${e instanceof Error ? e.message : String(e)}`);
301
301
  }
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");
302
+ if ("events" in payload) throw new chunkMZE4TPFU_cjs.SsoError("a logout token is not a ticket");
303
+ if ("nonce" in payload) throw new chunkMZE4TPFU_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 chunkCHRCHUZ3_cjs.SsoError(`ticket has no valid principal_type (got ${JSON.stringify(type)})`);
306
+ throw new chunkMZE4TPFU_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 chunkCHRCHUZ3_cjs.SsoError(`ticket claims a ${lifetime}s lifetime; at most ${maxLifetimeSec}s is accepted`);
310
+ throw new chunkMZE4TPFU_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 chunkCHRCHUZ3_cjs.SsoError("ticket has no sub");
312
+ if (typeof payload.sub !== "string" || payload.sub === "") throw new chunkMZE4TPFU_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 chunkCHRCHUZ3_cjs.SsoError(`ticket lacks scope ${missing.join(", ")}`);
316
+ if (missing.length) throw new chunkMZE4TPFU_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 chunkCHRCHUZ3_cjs.SsoError(`ticket has an invalid ver (got ${JSON.stringify(payload.ver)})`);
319
+ throw new chunkMZE4TPFU_cjs.SsoError(`ticket has an invalid ver (got ${JSON.stringify(payload.ver)})`);
320
320
  }
321
321
  if (ver > TICKET_FORMAT_VERSION) {
322
- throw new chunkCHRCHUZ3_cjs.SsoError(`ticket format version ${ver} is newer than this @broberg/sso understands (${TICKET_FORMAT_VERSION}) \u2014 upgrade @broberg/sso`);
322
+ throw new chunkMZE4TPFU_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 chunkCHRCHUZ3_cjs.SsoError("ticket is DPoP-bound (cnf.jkt) but no DPoP proof was presented");
328
+ if (!opts.dpop?.proof) throw new chunkMZE4TPFU_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 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)");
339
+ throw new chunkMZE4TPFU_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 chunkCHRCHUZ3_cjs.SsoError("a user ticket names no app (no client_id or azp)");
343
+ if (clientId === null) throw new chunkMZE4TPFU_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,125 @@ function createTicketVerifier(options) {
357
357
  };
358
358
  }
359
359
  function readActor(raw, depth) {
360
- if (depth > MAX_ACT_DEPTH) throw new chunkCHRCHUZ3_cjs.SsoError(`ticket's delegation chain is deeper than ${MAX_ACT_DEPTH}`);
360
+ if (depth > MAX_ACT_DEPTH) throw new chunkMZE4TPFU_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 chunkCHRCHUZ3_cjs.SsoError(`ticket's act (link ${depth}) has no string sub`);
363
+ throw new chunkMZE4TPFU_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 chunkCHRCHUZ3_cjs.AVATAR_TYPES; }
370
+ get: function () { return chunkMZE4TPFU_cjs.AVATAR_TYPES; }
371
371
  });
372
372
  Object.defineProperty(exports, "DEFAULT_SESSION_MAX_AGE", {
373
373
  enumerable: true,
374
- get: function () { return chunkCHRCHUZ3_cjs.DEFAULT_SESSION_MAX_AGE; }
374
+ get: function () { return chunkMZE4TPFU_cjs.DEFAULT_SESSION_MAX_AGE; }
375
+ });
376
+ Object.defineProperty(exports, "EMBEDDED_FLOW_MAX_AGE", {
377
+ enumerable: true,
378
+ get: function () { return chunkMZE4TPFU_cjs.EMBEDDED_FLOW_MAX_AGE; }
375
379
  });
376
380
  Object.defineProperty(exports, "JwksError", {
377
381
  enumerable: true,
378
- get: function () { return chunkCHRCHUZ3_cjs.JwksError; }
382
+ get: function () { return chunkMZE4TPFU_cjs.JwksError; }
379
383
  });
380
384
  Object.defineProperty(exports, "JwksUnavailableError", {
381
385
  enumerable: true,
382
- get: function () { return chunkCHRCHUZ3_cjs.JwksUnavailableError; }
386
+ get: function () { return chunkMZE4TPFU_cjs.JwksUnavailableError; }
383
387
  });
384
388
  Object.defineProperty(exports, "JwksUnknownKeyError", {
385
389
  enumerable: true,
386
- get: function () { return chunkCHRCHUZ3_cjs.JwksUnknownKeyError; }
390
+ get: function () { return chunkMZE4TPFU_cjs.JwksUnknownKeyError; }
387
391
  });
388
392
  Object.defineProperty(exports, "MAX_AVATAR_BYTES", {
389
393
  enumerable: true,
390
- get: function () { return chunkCHRCHUZ3_cjs.MAX_AVATAR_BYTES; }
394
+ get: function () { return chunkMZE4TPFU_cjs.MAX_AVATAR_BYTES; }
391
395
  });
392
396
  Object.defineProperty(exports, "MAX_INVITATIONS", {
393
397
  enumerable: true,
394
- get: function () { return chunkCHRCHUZ3_cjs.MAX_INVITATIONS; }
398
+ get: function () { return chunkMZE4TPFU_cjs.MAX_INVITATIONS; }
395
399
  });
396
400
  Object.defineProperty(exports, "SsoAppApiError", {
397
401
  enumerable: true,
398
- get: function () { return chunkCHRCHUZ3_cjs.SsoAppApiError; }
402
+ get: function () { return chunkMZE4TPFU_cjs.SsoAppApiError; }
399
403
  });
400
404
  Object.defineProperty(exports, "SsoAvatarRejectedError", {
401
405
  enumerable: true,
402
- get: function () { return chunkCHRCHUZ3_cjs.SsoAvatarRejectedError; }
406
+ get: function () { return chunkMZE4TPFU_cjs.SsoAvatarRejectedError; }
403
407
  });
404
408
  Object.defineProperty(exports, "SsoConfigError", {
405
409
  enumerable: true,
406
- get: function () { return chunkCHRCHUZ3_cjs.SsoConfigError; }
410
+ get: function () { return chunkMZE4TPFU_cjs.SsoConfigError; }
407
411
  });
408
412
  Object.defineProperty(exports, "SsoError", {
409
413
  enumerable: true,
410
- get: function () { return chunkCHRCHUZ3_cjs.SsoError; }
414
+ get: function () { return chunkMZE4TPFU_cjs.SsoError; }
411
415
  });
412
416
  Object.defineProperty(exports, "SsoInsufficientScopeError", {
413
417
  enumerable: true,
414
- get: function () { return chunkCHRCHUZ3_cjs.SsoInsufficientScopeError; }
418
+ get: function () { return chunkMZE4TPFU_cjs.SsoInsufficientScopeError; }
415
419
  });
416
420
  Object.defineProperty(exports, "SsoIntrospectionUnavailableError", {
417
421
  enumerable: true,
418
- get: function () { return chunkCHRCHUZ3_cjs.SsoIntrospectionUnavailableError; }
422
+ get: function () { return chunkMZE4TPFU_cjs.SsoIntrospectionUnavailableError; }
419
423
  });
420
424
  Object.defineProperty(exports, "SsoReauthError", {
421
425
  enumerable: true,
422
- get: function () { return chunkCHRCHUZ3_cjs.SsoReauthError; }
426
+ get: function () { return chunkMZE4TPFU_cjs.SsoReauthError; }
423
427
  });
424
428
  Object.defineProperty(exports, "SsoTokenInactiveError", {
425
429
  enumerable: true,
426
- get: function () { return chunkCHRCHUZ3_cjs.SsoTokenInactiveError; }
430
+ get: function () { return chunkMZE4TPFU_cjs.SsoTokenInactiveError; }
427
431
  });
428
432
  Object.defineProperty(exports, "cookieHeader", {
429
433
  enumerable: true,
430
- get: function () { return chunkCHRCHUZ3_cjs.cookieHeader; }
434
+ get: function () { return chunkMZE4TPFU_cjs.cookieHeader; }
431
435
  });
432
436
  Object.defineProperty(exports, "createJwksCache", {
433
437
  enumerable: true,
434
- get: function () { return chunkCHRCHUZ3_cjs.createJwksCache; }
438
+ get: function () { return chunkMZE4TPFU_cjs.createJwksCache; }
435
439
  });
436
440
  Object.defineProperty(exports, "createSsoClient", {
437
441
  enumerable: true,
438
- get: function () { return chunkCHRCHUZ3_cjs.createSsoClient; }
442
+ get: function () { return chunkMZE4TPFU_cjs.createSsoClient; }
439
443
  });
440
444
  Object.defineProperty(exports, "loadSsoConfig", {
441
445
  enumerable: true,
442
- get: function () { return chunkCHRCHUZ3_cjs.loadSsoConfig; }
446
+ get: function () { return chunkMZE4TPFU_cjs.loadSsoConfig; }
443
447
  });
444
448
  Object.defineProperty(exports, "memoryTokenStore", {
445
449
  enumerable: true,
446
- get: function () { return chunkCHRCHUZ3_cjs.memoryTokenStore; }
450
+ get: function () { return chunkMZE4TPFU_cjs.memoryTokenStore; }
451
+ });
452
+ Object.defineProperty(exports, "openEmbeddedFlow", {
453
+ enumerable: true,
454
+ get: function () { return chunkMZE4TPFU_cjs.openEmbeddedFlow; }
447
455
  });
448
456
  Object.defineProperty(exports, "readCookie", {
449
457
  enumerable: true,
450
- get: function () { return chunkCHRCHUZ3_cjs.readCookie; }
458
+ get: function () { return chunkMZE4TPFU_cjs.readCookie; }
459
+ });
460
+ Object.defineProperty(exports, "sealEmbeddedFlow", {
461
+ enumerable: true,
462
+ get: function () { return chunkMZE4TPFU_cjs.sealEmbeddedFlow; }
451
463
  });
452
464
  Object.defineProperty(exports, "signSession", {
453
465
  enumerable: true,
454
- get: function () { return chunkCHRCHUZ3_cjs.signSession; }
466
+ get: function () { return chunkMZE4TPFU_cjs.signSession; }
455
467
  });
456
468
  Object.defineProperty(exports, "signValue", {
457
469
  enumerable: true,
458
- get: function () { return chunkCHRCHUZ3_cjs.signValue; }
470
+ get: function () { return chunkMZE4TPFU_cjs.signValue; }
459
471
  });
460
472
  Object.defineProperty(exports, "verifySession", {
461
473
  enumerable: true,
462
- get: function () { return chunkCHRCHUZ3_cjs.verifySession; }
474
+ get: function () { return chunkMZE4TPFU_cjs.verifySession; }
463
475
  });
464
476
  Object.defineProperty(exports, "verifyValue", {
465
477
  enumerable: true,
466
- get: function () { return chunkCHRCHUZ3_cjs.verifyValue; }
478
+ get: function () { return chunkMZE4TPFU_cjs.verifyValue; }
467
479
  });
468
480
  exports.DEFAULT_ISSUER = DEFAULT_ISSUER;
469
481
  exports.MAX_ACT_DEPTH = MAX_ACT_DEPTH;
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- export { A as AVATAR_TYPES, c as AddressOwnership, B as BeginLoginOptions, d as BidProfile, C as CreateSsoClientOptions, D as DEFAULT_SESSION_MAX_AGE, e as Discovery, I as IntrospectOptions, f as IntrospectedToken, g as InvitationOutcome, h as InvitationResult, i as InviteUsersInput, J as JwksCache, j as JwksCacheOptions, k as JwksError, l as JwksUnavailableError, m as JwksUnknownKeyError, L as LoginResult, n as LoginStart, o as LogoutToken, M as MAX_AVATAR_BYTES, p as MAX_INVITATIONS, q as MigrationState, r as MigrationStatus, b as SessionPayload, s as SsoAppApiError, t as SsoAvatarRejectedError, u as SsoClaims, S as SsoClient, a as SsoConfig, v as SsoConfigError, w as SsoError, x as SsoInsufficientScopeError, y as SsoIntrospectionUnavailableError, z as SsoReauthError, E as SsoTokenInactiveError, F as TokenSet, T as TokenStore, G as cookieHeader, H as createJwksCache, K as createSsoClient, N as loadSsoConfig, O as memoryTokenStore, P as readCookie, Q as signSession, R as signValue, U as verifySession, V as verifyValue } from './session-eya6Bon5.cjs';
1
+ export { A as AVATAR_TYPES, c as AddressOwnership, B as BeginLoginOptions, d as BidProfile, C as CreateSsoClientOptions, D as DEFAULT_SESSION_MAX_AGE, e as Discovery, E as EMBEDDED_FLOW_MAX_AGE, f as EmbeddedClient, g as EmbeddedError, h as EmbeddedFlow, i as EmbeddedStart, j as EmbeddedStartInput, k as EmbeddedStep, l as EmbeddedTerms, I as IntrospectOptions, m as IntrospectedToken, n as InvitationOutcome, o as InvitationResult, p as InviteUsersInput, J as JwksCache, q as JwksCacheOptions, r as JwksError, s as JwksUnavailableError, t as JwksUnknownKeyError, L as LoginResult, u as LoginStart, v as LogoutToken, M as MAX_AVATAR_BYTES, w as MAX_INVITATIONS, x as MigrationState, y as MigrationStatus, b as SessionPayload, z as SsoAppApiError, F as SsoAvatarRejectedError, G as SsoClaims, S as SsoClient, a as SsoConfig, H as SsoConfigError, K as SsoError, N as SsoInsufficientScopeError, O as SsoIntrospectionUnavailableError, P as SsoReauthError, Q as SsoTokenInactiveError, R as TokenSet, T as TokenStore, U as cookieHeader, V as createJwksCache, W as createSsoClient, X as loadSsoConfig, Y as memoryTokenStore, Z as openEmbeddedFlow, _ as readCookie, $ as sealEmbeddedFlow, a0 as signSession, a1 as signValue, a2 as verifySession, a3 as verifyValue } from './session-qvhMg3ID.cjs';
2
2
  import { JWK } from 'jose';
3
3
 
4
4
  declare const DEFAULT_ISSUER = "https://id.broberg.ai";
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { A as AVATAR_TYPES, c as AddressOwnership, B as BeginLoginOptions, d as BidProfile, C as CreateSsoClientOptions, D as DEFAULT_SESSION_MAX_AGE, e as Discovery, I as IntrospectOptions, f as IntrospectedToken, g as InvitationOutcome, h as InvitationResult, i as InviteUsersInput, J as JwksCache, j as JwksCacheOptions, k as JwksError, l as JwksUnavailableError, m as JwksUnknownKeyError, L as LoginResult, n as LoginStart, o as LogoutToken, M as MAX_AVATAR_BYTES, p as MAX_INVITATIONS, q as MigrationState, r as MigrationStatus, b as SessionPayload, s as SsoAppApiError, t as SsoAvatarRejectedError, u as SsoClaims, S as SsoClient, a as SsoConfig, v as SsoConfigError, w as SsoError, x as SsoInsufficientScopeError, y as SsoIntrospectionUnavailableError, z as SsoReauthError, E as SsoTokenInactiveError, F as TokenSet, T as TokenStore, G as cookieHeader, H as createJwksCache, K as createSsoClient, N as loadSsoConfig, O as memoryTokenStore, P as readCookie, Q as signSession, R as signValue, U as verifySession, V as verifyValue } from './session-eya6Bon5.js';
1
+ export { A as AVATAR_TYPES, c as AddressOwnership, B as BeginLoginOptions, d as BidProfile, C as CreateSsoClientOptions, D as DEFAULT_SESSION_MAX_AGE, e as Discovery, E as EMBEDDED_FLOW_MAX_AGE, f as EmbeddedClient, g as EmbeddedError, h as EmbeddedFlow, i as EmbeddedStart, j as EmbeddedStartInput, k as EmbeddedStep, l as EmbeddedTerms, I as IntrospectOptions, m as IntrospectedToken, n as InvitationOutcome, o as InvitationResult, p as InviteUsersInput, J as JwksCache, q as JwksCacheOptions, r as JwksError, s as JwksUnavailableError, t as JwksUnknownKeyError, L as LoginResult, u as LoginStart, v as LogoutToken, M as MAX_AVATAR_BYTES, w as MAX_INVITATIONS, x as MigrationState, y as MigrationStatus, b as SessionPayload, z as SsoAppApiError, F as SsoAvatarRejectedError, G as SsoClaims, S as SsoClient, a as SsoConfig, H as SsoConfigError, K as SsoError, N as SsoInsufficientScopeError, O as SsoIntrospectionUnavailableError, P as SsoReauthError, Q as SsoTokenInactiveError, R as TokenSet, T as TokenStore, U as cookieHeader, V as createJwksCache, W as createSsoClient, X as loadSsoConfig, Y as memoryTokenStore, Z as openEmbeddedFlow, _ as readCookie, $ as sealEmbeddedFlow, a0 as signSession, a1 as signValue, a2 as verifySession, a3 as verifyValue } from './session-qvhMg3ID.js';
2
2
  import { JWK } from 'jose';
3
3
 
4
4
  declare const DEFAULT_ISSUER = "https://id.broberg.ai";
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
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';
1
+ import { SsoError, ALLOWED_ALGS, JwksUnavailableError, createJwksCache } from './chunk-PQTT74BA.js';
2
+ export { AVATAR_TYPES, DEFAULT_SESSION_MAX_AGE, EMBEDDED_FLOW_MAX_AGE, JwksError, JwksUnavailableError, JwksUnknownKeyError, MAX_AVATAR_BYTES, MAX_INVITATIONS, SsoAppApiError, SsoAvatarRejectedError, SsoConfigError, SsoError, SsoInsufficientScopeError, SsoIntrospectionUnavailableError, SsoReauthError, SsoTokenInactiveError, cookieHeader, createJwksCache, createSsoClient, loadSsoConfig, memoryTokenStore, openEmbeddedFlow, readCookie, sealEmbeddedFlow, signSession, signValue, verifySession, verifyValue } from './chunk-PQTT74BA.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';
@@ -57,6 +57,105 @@ interface SsoConfig {
57
57
  declare const DEFAULT_SESSION_MAX_AGE: number;
58
58
  declare function loadSsoConfig(env?: NodeJS.ProcessEnv): SsoConfig;
59
59
 
60
+ /** What a step can answer, as data the app can word itself (the contract's error table). */
61
+ type EmbeddedError = {
62
+ kind: "invalid_code";
63
+ attemptsLeft?: number;
64
+ } | {
65
+ kind: "expired";
66
+ } | {
67
+ kind: "locked";
68
+ retryAfter?: number;
69
+ } | {
70
+ kind: "too_many_requests";
71
+ retryAfter?: number;
72
+ } | {
73
+ kind: "not_embedded";
74
+ } | {
75
+ kind: "signup_not_enabled";
76
+ } | {
77
+ kind: "terms_outdated";
78
+ version?: string;
79
+ } | {
80
+ kind: "invalid_request";
81
+ } | {
82
+ kind: "unavailable";
83
+ message: string;
84
+ };
85
+ /** The server-side state of one embedded login: keep it in a signed cookie (sealEmbeddedFlow). */
86
+ interface EmbeddedFlow {
87
+ flowId: string;
88
+ codeVerifier: string;
89
+ nonce: string;
90
+ email: string;
91
+ }
92
+ interface EmbeddedStartInput {
93
+ email: string;
94
+ /** "signup" creates the account at verify (BID F084.167); needs `name` and the current `termsVersion`. */
95
+ intent?: "login" | "signup";
96
+ name?: string;
97
+ termsVersion?: string;
98
+ /** The user's IP, for BID's per-IP limit. Without it, BID counts your server's IP. */
99
+ endUserIp?: string;
100
+ }
101
+ type EmbeddedStart = {
102
+ ok: true;
103
+ flow: EmbeddedFlow;
104
+ expiresIn: number;
105
+ } | {
106
+ ok: false;
107
+ error: EmbeddedError;
108
+ };
109
+ /** After a code: signed in (the same result as completeLogin), a second factor, or an error. */
110
+ type EmbeddedStep = {
111
+ kind: "done";
112
+ result: LoginResult;
113
+ } | {
114
+ kind: "second_factor";
115
+ methods: ("totp" | "sms")[];
116
+ } | {
117
+ kind: "error";
118
+ error: EmbeddedError;
119
+ };
120
+ interface EmbeddedTerms {
121
+ version: string;
122
+ /** Show it VERBATIM at the button — BID owns the text. */
123
+ text: string;
124
+ links: {
125
+ label: string;
126
+ url: string;
127
+ }[];
128
+ }
129
+ interface EmbeddedClient {
130
+ start(input: EmbeddedStartInput): Promise<EmbeddedStart>;
131
+ verify(flow: EmbeddedFlow, code: string): Promise<EmbeddedStep>;
132
+ sendSms(flow: EmbeddedFlow): Promise<{
133
+ ok: true;
134
+ } | {
135
+ ok: false;
136
+ error: EmbeddedError;
137
+ }>;
138
+ verifySecondFactor(flow: EmbeddedFlow, method: "totp" | "sms", code: string): Promise<EmbeddedStep>;
139
+ /** BID's consent text for signup, current version. Throws SsoError if BID does not answer it. */
140
+ terms(lang: "da" | "en"): Promise<EmbeddedTerms>;
141
+ }
142
+ /** A flow lives as long as BID's code does (10 min). */
143
+ declare const EMBEDDED_FLOW_MAX_AGE = 600;
144
+ /** Seal the flow for a signed, httpOnly cookie (same signing as the login transaction). */
145
+ declare function sealEmbeddedFlow(flow: EmbeddedFlow, secret: string, options?: {
146
+ now?: () => number;
147
+ }): Promise<string>;
148
+ /** Read it back: the flow, or why not — "absent" (no cookie), "expired" (too old), "unreadable" (not ours / tampered). */
149
+ declare function openEmbeddedFlow(raw: string | undefined | null, secret: string, options?: {
150
+ now?: () => number;
151
+ }): Promise<{
152
+ ok: true;
153
+ flow: EmbeddedFlow;
154
+ } | {
155
+ ok: false;
156
+ reason: "absent" | "expired" | "unreadable";
157
+ }>;
158
+
60
159
  /**
61
160
  * The signing-key cache.
62
161
  *
@@ -357,6 +456,12 @@ interface SsoClient {
357
456
  verifyIdToken(idToken: string, options?: {
358
457
  nonce?: string;
359
458
  }): Promise<SsoClaims>;
459
+ /**
460
+ * components-F084.165 — the embedded login and signup (BID F084.166 v1.1 + F084.167), called
461
+ * from YOUR SERVER as a confidential client (needs `clientSecret`). Ends in the same
462
+ * LoginResult as completeLogin. Keep the returned flow in a cookie with sealEmbeddedFlow.
463
+ */
464
+ embedded: EmbeddedClient;
360
465
  logoutUrl(options?: {
361
466
  idTokenHint?: string;
362
467
  postLogoutRedirectUri?: string;
@@ -623,4 +728,4 @@ declare function cookieHeader(name: string, value: string, opts: {
623
728
  }): string;
624
729
  declare function readCookie(header: string | null | undefined, name: string): string | undefined;
625
730
 
626
- export { AVATAR_TYPES as A, type BeginLoginOptions as B, type CreateSsoClientOptions as C, DEFAULT_SESSION_MAX_AGE as D, SsoTokenInactiveError as E, type TokenSet as F, cookieHeader as G, createJwksCache as H, type IntrospectOptions as I, type JwksCache as J, createSsoClient as K, type LoginResult as L, MAX_AVATAR_BYTES as M, loadSsoConfig as N, memoryTokenStore as O, readCookie as P, signSession as Q, signValue as R, type SsoClient as S, type TokenStore as T, verifySession as U, verifyValue as V, type SsoConfig as a, type SessionPayload as b, type AddressOwnership as c, type BidProfile as d, type Discovery as e, type IntrospectedToken as f, type InvitationOutcome as g, type InvitationResult as h, type InviteUsersInput as i, type JwksCacheOptions as j, JwksError as k, JwksUnavailableError as l, JwksUnknownKeyError as m, type LoginStart as n, type LogoutToken as o, MAX_INVITATIONS as p, type MigrationState as q, type MigrationStatus as r, SsoAppApiError as s, SsoAvatarRejectedError as t, type SsoClaims as u, SsoConfigError as v, SsoError as w, SsoInsufficientScopeError as x, SsoIntrospectionUnavailableError as y, SsoReauthError as z };
731
+ export { sealEmbeddedFlow as $, AVATAR_TYPES as A, type BeginLoginOptions as B, type CreateSsoClientOptions as C, DEFAULT_SESSION_MAX_AGE as D, EMBEDDED_FLOW_MAX_AGE as E, SsoAvatarRejectedError as F, type SsoClaims as G, SsoConfigError as H, type IntrospectOptions as I, type JwksCache as J, SsoError as K, type LoginResult as L, MAX_AVATAR_BYTES as M, SsoInsufficientScopeError as N, SsoIntrospectionUnavailableError as O, SsoReauthError as P, SsoTokenInactiveError as Q, type TokenSet as R, type SsoClient as S, type TokenStore as T, cookieHeader as U, createJwksCache as V, createSsoClient as W, loadSsoConfig as X, memoryTokenStore as Y, openEmbeddedFlow as Z, readCookie as _, type SsoConfig as a, signSession as a0, signValue as a1, verifySession as a2, verifyValue as a3, type SessionPayload as b, type AddressOwnership as c, type BidProfile as d, type Discovery as e, type EmbeddedClient as f, type EmbeddedError as g, type EmbeddedFlow as h, type EmbeddedStart as i, type EmbeddedStartInput as j, type EmbeddedStep as k, type EmbeddedTerms as l, type IntrospectedToken as m, type InvitationOutcome as n, type InvitationResult as o, type InviteUsersInput as p, type JwksCacheOptions as q, JwksError as r, JwksUnavailableError as s, JwksUnknownKeyError as t, type LoginStart as u, type LogoutToken as v, MAX_INVITATIONS as w, type MigrationState as x, type MigrationStatus as y, SsoAppApiError as z };
@@ -57,6 +57,105 @@ interface SsoConfig {
57
57
  declare const DEFAULT_SESSION_MAX_AGE: number;
58
58
  declare function loadSsoConfig(env?: NodeJS.ProcessEnv): SsoConfig;
59
59
 
60
+ /** What a step can answer, as data the app can word itself (the contract's error table). */
61
+ type EmbeddedError = {
62
+ kind: "invalid_code";
63
+ attemptsLeft?: number;
64
+ } | {
65
+ kind: "expired";
66
+ } | {
67
+ kind: "locked";
68
+ retryAfter?: number;
69
+ } | {
70
+ kind: "too_many_requests";
71
+ retryAfter?: number;
72
+ } | {
73
+ kind: "not_embedded";
74
+ } | {
75
+ kind: "signup_not_enabled";
76
+ } | {
77
+ kind: "terms_outdated";
78
+ version?: string;
79
+ } | {
80
+ kind: "invalid_request";
81
+ } | {
82
+ kind: "unavailable";
83
+ message: string;
84
+ };
85
+ /** The server-side state of one embedded login: keep it in a signed cookie (sealEmbeddedFlow). */
86
+ interface EmbeddedFlow {
87
+ flowId: string;
88
+ codeVerifier: string;
89
+ nonce: string;
90
+ email: string;
91
+ }
92
+ interface EmbeddedStartInput {
93
+ email: string;
94
+ /** "signup" creates the account at verify (BID F084.167); needs `name` and the current `termsVersion`. */
95
+ intent?: "login" | "signup";
96
+ name?: string;
97
+ termsVersion?: string;
98
+ /** The user's IP, for BID's per-IP limit. Without it, BID counts your server's IP. */
99
+ endUserIp?: string;
100
+ }
101
+ type EmbeddedStart = {
102
+ ok: true;
103
+ flow: EmbeddedFlow;
104
+ expiresIn: number;
105
+ } | {
106
+ ok: false;
107
+ error: EmbeddedError;
108
+ };
109
+ /** After a code: signed in (the same result as completeLogin), a second factor, or an error. */
110
+ type EmbeddedStep = {
111
+ kind: "done";
112
+ result: LoginResult;
113
+ } | {
114
+ kind: "second_factor";
115
+ methods: ("totp" | "sms")[];
116
+ } | {
117
+ kind: "error";
118
+ error: EmbeddedError;
119
+ };
120
+ interface EmbeddedTerms {
121
+ version: string;
122
+ /** Show it VERBATIM at the button — BID owns the text. */
123
+ text: string;
124
+ links: {
125
+ label: string;
126
+ url: string;
127
+ }[];
128
+ }
129
+ interface EmbeddedClient {
130
+ start(input: EmbeddedStartInput): Promise<EmbeddedStart>;
131
+ verify(flow: EmbeddedFlow, code: string): Promise<EmbeddedStep>;
132
+ sendSms(flow: EmbeddedFlow): Promise<{
133
+ ok: true;
134
+ } | {
135
+ ok: false;
136
+ error: EmbeddedError;
137
+ }>;
138
+ verifySecondFactor(flow: EmbeddedFlow, method: "totp" | "sms", code: string): Promise<EmbeddedStep>;
139
+ /** BID's consent text for signup, current version. Throws SsoError if BID does not answer it. */
140
+ terms(lang: "da" | "en"): Promise<EmbeddedTerms>;
141
+ }
142
+ /** A flow lives as long as BID's code does (10 min). */
143
+ declare const EMBEDDED_FLOW_MAX_AGE = 600;
144
+ /** Seal the flow for a signed, httpOnly cookie (same signing as the login transaction). */
145
+ declare function sealEmbeddedFlow(flow: EmbeddedFlow, secret: string, options?: {
146
+ now?: () => number;
147
+ }): Promise<string>;
148
+ /** Read it back: the flow, or why not — "absent" (no cookie), "expired" (too old), "unreadable" (not ours / tampered). */
149
+ declare function openEmbeddedFlow(raw: string | undefined | null, secret: string, options?: {
150
+ now?: () => number;
151
+ }): Promise<{
152
+ ok: true;
153
+ flow: EmbeddedFlow;
154
+ } | {
155
+ ok: false;
156
+ reason: "absent" | "expired" | "unreadable";
157
+ }>;
158
+
60
159
  /**
61
160
  * The signing-key cache.
62
161
  *
@@ -357,6 +456,12 @@ interface SsoClient {
357
456
  verifyIdToken(idToken: string, options?: {
358
457
  nonce?: string;
359
458
  }): Promise<SsoClaims>;
459
+ /**
460
+ * components-F084.165 — the embedded login and signup (BID F084.166 v1.1 + F084.167), called
461
+ * from YOUR SERVER as a confidential client (needs `clientSecret`). Ends in the same
462
+ * LoginResult as completeLogin. Keep the returned flow in a cookie with sealEmbeddedFlow.
463
+ */
464
+ embedded: EmbeddedClient;
360
465
  logoutUrl(options?: {
361
466
  idTokenHint?: string;
362
467
  postLogoutRedirectUri?: string;
@@ -623,4 +728,4 @@ declare function cookieHeader(name: string, value: string, opts: {
623
728
  }): string;
624
729
  declare function readCookie(header: string | null | undefined, name: string): string | undefined;
625
730
 
626
- export { AVATAR_TYPES as A, type BeginLoginOptions as B, type CreateSsoClientOptions as C, DEFAULT_SESSION_MAX_AGE as D, SsoTokenInactiveError as E, type TokenSet as F, cookieHeader as G, createJwksCache as H, type IntrospectOptions as I, type JwksCache as J, createSsoClient as K, type LoginResult as L, MAX_AVATAR_BYTES as M, loadSsoConfig as N, memoryTokenStore as O, readCookie as P, signSession as Q, signValue as R, type SsoClient as S, type TokenStore as T, verifySession as U, verifyValue as V, type SsoConfig as a, type SessionPayload as b, type AddressOwnership as c, type BidProfile as d, type Discovery as e, type IntrospectedToken as f, type InvitationOutcome as g, type InvitationResult as h, type InviteUsersInput as i, type JwksCacheOptions as j, JwksError as k, JwksUnavailableError as l, JwksUnknownKeyError as m, type LoginStart as n, type LogoutToken as o, MAX_INVITATIONS as p, type MigrationState as q, type MigrationStatus as r, SsoAppApiError as s, SsoAvatarRejectedError as t, type SsoClaims as u, SsoConfigError as v, SsoError as w, SsoInsufficientScopeError as x, SsoIntrospectionUnavailableError as y, SsoReauthError as z };
731
+ export { sealEmbeddedFlow as $, AVATAR_TYPES as A, type BeginLoginOptions as B, type CreateSsoClientOptions as C, DEFAULT_SESSION_MAX_AGE as D, EMBEDDED_FLOW_MAX_AGE as E, SsoAvatarRejectedError as F, type SsoClaims as G, SsoConfigError as H, type IntrospectOptions as I, type JwksCache as J, SsoError as K, type LoginResult as L, MAX_AVATAR_BYTES as M, SsoInsufficientScopeError as N, SsoIntrospectionUnavailableError as O, SsoReauthError as P, SsoTokenInactiveError as Q, type TokenSet as R, type SsoClient as S, type TokenStore as T, cookieHeader as U, createJwksCache as V, createSsoClient as W, loadSsoConfig as X, memoryTokenStore as Y, openEmbeddedFlow as Z, readCookie as _, type SsoConfig as a, signSession as a0, signValue as a1, verifySession as a2, verifyValue as a3, type SessionPayload as b, type AddressOwnership as c, type BidProfile as d, type Discovery as e, type EmbeddedClient as f, type EmbeddedError as g, type EmbeddedFlow as h, type EmbeddedStart as i, type EmbeddedStartInput as j, type EmbeddedStep as k, type EmbeddedTerms as l, type IntrospectedToken as m, type InvitationOutcome as n, type InvitationResult as o, type InviteUsersInput as p, type JwksCacheOptions as q, JwksError as r, JwksUnavailableError as s, JwksUnknownKeyError as t, type LoginStart as u, type LogoutToken as v, MAX_INVITATIONS as w, type MigrationState as x, type MigrationStatus as y, SsoAppApiError as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@broberg/sso",
3
- "version": "0.18.3",
3
+ "version": "0.19.0",
4
4
  "description": "The thin client for BrobergID — send a user to central login, verify the ID token against JWKS, keep a local session. Public client + PKCE only: no passwords, no passkeys, no client secret can live in an app.",
5
5
  "type": "module",
6
6
  "license": "MIT",