@iqauth/sdk 2.7.0 → 2.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/dist/browser-session.d.mts +3 -3
  2. package/dist/browser-session.d.ts +3 -3
  3. package/dist/browser-session.js +31 -5
  4. package/dist/browser-session.mjs +1 -1
  5. package/dist/browser.d.mts +3 -3
  6. package/dist/browser.d.ts +3 -3
  7. package/dist/browser.js +23 -3
  8. package/dist/browser.mjs +1 -1
  9. package/dist/{chunk-YVALAG3B.mjs → chunk-25SSYDIP.mjs} +1 -1
  10. package/dist/{chunk-RTJAIBXY.mjs → chunk-4V7FKOTG.mjs} +23 -3
  11. package/dist/{chunk-SL3KRS4W.mjs → chunk-CIJORODR.mjs} +23 -1
  12. package/dist/chunk-JRDVUWAL.mjs +46 -0
  13. package/dist/{chunk-5T7GHBX6.mjs → chunk-TLET552H.mjs} +36 -0
  14. package/dist/{chunk-PMAFENVI.mjs → chunk-VYQ3ETCK.mjs} +27 -12
  15. package/dist/{chunk-RR2MGPTK.mjs → chunk-WHT6WKTY.mjs} +539 -83
  16. package/dist/{chunk-RUJXRTEW.mjs → chunk-WSH4SW7F.mjs} +122 -8
  17. package/dist/{chunk-JXQI62A7.mjs → chunk-ZLJPABB7.mjs} +31 -5
  18. package/dist/{client-BGFnBpfc.d.mts → client-D8L-PaWr.d.mts} +14 -4
  19. package/dist/{client-CDQ21LvW.d.ts → client-DkPL0EPZ.d.ts} +14 -4
  20. package/dist/{express-Piv2WhWM.d.ts → express-Budysq4h.d.ts} +2 -2
  21. package/dist/{express-CVNQEkOr.d.mts → express-DDTA3qV1.d.mts} +2 -2
  22. package/dist/express.d.mts +5 -5
  23. package/dist/express.d.ts +5 -5
  24. package/dist/express.js +217 -36
  25. package/dist/express.mjs +38 -26
  26. package/dist/fastify.d.mts +10 -2
  27. package/dist/fastify.d.ts +10 -2
  28. package/dist/fastify.js +260 -16
  29. package/dist/fastify.mjs +80 -5
  30. package/dist/hono.d.mts +10 -2
  31. package/dist/hono.d.ts +10 -2
  32. package/dist/hono.js +240 -16
  33. package/dist/hono.mjs +60 -5
  34. package/dist/{index-5KSZEnDe.d.ts → index-Cko-d5po.d.mts} +227 -5
  35. package/dist/{index-CKoZHAoc.d.mts → index-RNqwEcmY.d.ts} +227 -5
  36. package/dist/index.d.mts +5 -5
  37. package/dist/index.d.ts +5 -5
  38. package/dist/index.js +149 -26
  39. package/dist/index.mjs +5 -5
  40. package/dist/locales.d.mts +1 -1
  41. package/dist/locales.d.ts +1 -1
  42. package/dist/locales.js +36 -0
  43. package/dist/locales.mjs +1 -1
  44. package/dist/mobile.d.mts +3 -3
  45. package/dist/mobile.d.ts +3 -3
  46. package/dist/mobile.js +31 -5
  47. package/dist/mobile.mjs +1 -1
  48. package/dist/next.d.mts +10 -2
  49. package/dist/next.d.ts +10 -2
  50. package/dist/next.js +212 -11
  51. package/dist/next.mjs +62 -4
  52. package/dist/{provisioningBridge-M5G47LWO.d.mts → provisioningBridge-BXPMZCLe.d.ts} +30 -2
  53. package/dist/{provisioningBridge-CGpMRie4.d.ts → provisioningBridge-IEycmsgb.d.mts} +30 -2
  54. package/dist/react-permissions.d.mts +4 -4
  55. package/dist/react-permissions.d.ts +4 -4
  56. package/dist/react-permissions.mjs +4 -3
  57. package/dist/react.d.mts +4 -4
  58. package/dist/react.d.ts +4 -4
  59. package/dist/react.js +570 -41
  60. package/dist/react.mjs +19 -5
  61. package/dist/server/handlers.d.mts +56 -5
  62. package/dist/server/handlers.d.ts +56 -5
  63. package/dist/server/handlers.js +123 -8
  64. package/dist/server/handlers.mjs +3 -1
  65. package/dist/server.d.mts +28 -8
  66. package/dist/server.d.ts +28 -8
  67. package/dist/server.js +176 -14
  68. package/dist/server.mjs +9 -4
  69. package/dist/service.d.mts +3 -3
  70. package/dist/service.d.ts +3 -3
  71. package/dist/service.js +31 -5
  72. package/dist/service.mjs +1 -1
  73. package/dist/{signIn-T-CZ6t6r.d.mts → signIn-CReqfXsh.d.mts} +18 -1
  74. package/dist/{signIn-BLFnz8SV.d.ts → signIn-Cfa1GTpO.d.ts} +18 -1
  75. package/dist/{tokens-Bqhmqq_R.d.ts → tokens-9F6ETrzk.d.ts} +1 -1
  76. package/dist/{tokens-CITeoG6P.d.mts → tokens-B06VtvUi.d.mts} +1 -1
  77. package/dist/{types-XOV9XPVi.d.mts → types-Bn8O-OEd.d.mts} +66 -2
  78. package/dist/{types-XOV9XPVi.d.ts → types-Bn8O-OEd.d.ts} +66 -2
  79. package/dist/{types-BdQ2lqfT.d.mts → types-DnU2LhXR.d.mts} +6 -0
  80. package/dist/{types-BdQ2lqfT.d.ts → types-DnU2LhXR.d.ts} +6 -0
  81. package/dist/webhooks.d.mts +22 -9
  82. package/dist/webhooks.d.ts +22 -9
  83. package/dist/webhooks.js +27 -12
  84. package/dist/webhooks.mjs +1 -1
  85. package/dist/ws.d.mts +2 -2
  86. package/dist/ws.d.ts +2 -2
  87. package/docs/guides/invitations.md +65 -0
  88. package/package.json +7 -2
package/dist/next.js CHANGED
@@ -357,7 +357,11 @@ async function buildUserinfoResponse(claims, opts = {}) {
357
357
  tenantId: claims.tenantId,
358
358
  vendorId: claims.vendorId,
359
359
  roles: claims.roles ?? [],
360
- entitlements: claims.entitlements ?? []
360
+ entitlements: claims.entitlements ?? [],
361
+ // Task #171 — project the active source/client scope onto the userinfo
362
+ // payload so server handlers (`getSessionUser`, `/api/iqauth/userinfo`)
363
+ // expose it without consumers having to re-decode the JWT.
364
+ ...claims.scopeContext !== void 0 ? { scopeContext: claims.scopeContext } : {}
361
365
  };
362
366
  const enriched = opts.enrich ? await opts.enrich(claims) : null;
363
367
  const user = enriched ? { ...baseUser, ...enriched } : baseUser;
@@ -402,19 +406,62 @@ function shouldClearCookiesOnFailure(policy, status, errorCode) {
402
406
  }
403
407
  var ACCESS_TOKEN_TTL_SECONDS = 60 * 15;
404
408
  var REFRESH_TOKEN_TTL_SECONDS = 60 * 60 * 24 * 30;
409
+ function assertCookiePrefixInvariants(name, secure, path, domain) {
410
+ if (name.startsWith("__Host-")) {
411
+ if (!secure) {
412
+ throw new IQAuthError(
413
+ "config_invalid",
414
+ `Cookie "${name}" uses the __Host- prefix, which browsers only accept on a Secure cookie. Set secure:true (and serve over HTTPS).`
415
+ );
416
+ }
417
+ if (path !== "/") {
418
+ throw new IQAuthError(
419
+ "config_invalid",
420
+ `Cookie "${name}" uses the __Host- prefix, which requires Path=/ (got "${path}"). Remove cookiePath or set it to "/".`
421
+ );
422
+ }
423
+ if (domain) {
424
+ throw new IQAuthError(
425
+ "config_invalid",
426
+ `Cookie "${name}" uses the __Host- prefix, which forbids a Domain attribute (the cookie is host-locked). Remove cookieDomain.`
427
+ );
428
+ }
429
+ } else if (name.startsWith("__Secure-") && !secure) {
430
+ throw new IQAuthError(
431
+ "config_invalid",
432
+ `Cookie "${name}" uses the __Secure- prefix, which browsers only accept on a Secure cookie. Set secure:true (and serve over HTTPS).`
433
+ );
434
+ }
435
+ }
405
436
  function resolve(config) {
406
437
  const parsed = assertPublishableKey(config.publishableKey, { context: "@iqauth/sdk helpers" });
407
438
  const inferredIssuer = parsed.iss.startsWith("http") ? parsed.iss : `https://${parsed.iss}`;
439
+ maybeWarnDefaultSignoutRegistry(config);
440
+ const secure = config.secure ?? true;
441
+ if (config.secure === false && config.allowInsecureCookies !== true) {
442
+ throw new IQAuthError(
443
+ "config_invalid",
444
+ "Refusing to issue auth cookies with secure:false \u2014 this exposes session cookies over plaintext HTTP. For local HTTP development, set allowInsecureCookies:true to acknowledge the risk. Production MUST use HTTPS with secure cookies."
445
+ );
446
+ }
447
+ const accessCookieName = config.accessCookieName ?? config.cookieNames?.access ?? "iqauth_at";
448
+ const refreshCookieName = config.refreshCookieName ?? config.cookieNames?.refresh ?? "iqauth_rt";
449
+ const stateCookieName = config.stateCookieName ?? "iqauth_state";
450
+ const cookiePath = config.cookiePath ?? "/";
451
+ const cookieDomain = config.cookieDomain;
452
+ for (const name of [accessCookieName, refreshCookieName, stateCookieName]) {
453
+ assertCookiePrefixInvariants(name, secure, cookiePath, cookieDomain);
454
+ }
408
455
  return {
409
456
  publishableKey: config.publishableKey,
410
457
  secretKey: config.secretKey,
411
458
  issuer: (config.issuer ?? inferredIssuer).replace(/\/+$/, ""),
412
- accessCookieName: config.accessCookieName ?? config.cookieNames?.access ?? "iqauth_at",
413
- refreshCookieName: config.refreshCookieName ?? config.cookieNames?.refresh ?? "iqauth_rt",
414
- cookieDomain: config.cookieDomain,
459
+ accessCookieName,
460
+ refreshCookieName,
461
+ cookieDomain,
415
462
  sameSite: config.sameSite ?? "lax",
416
- secure: config.secure ?? true,
417
- cookiePath: config.cookiePath ?? "/",
463
+ secure,
464
+ cookiePath,
418
465
  tokenPath: config.tokenPath ?? "/oidc/token",
419
466
  refreshPath: config.refreshPath ?? "/api/v1/auth/refresh",
420
467
  logoutPath: config.logoutPath ?? "/api/v1/auth/logout",
@@ -427,9 +474,19 @@ function resolve(config) {
427
474
  debug: config.debug,
428
475
  onTimingEvent: config.onTimingEvent,
429
476
  signoutRegistry: config.signoutRegistry ?? defaultSignoutRegistry,
430
- signoutMarkerTtlMs: config.signoutMarkerTtlMs ?? DEFAULT_SIGNOUT_TTL_MS
477
+ signoutMarkerTtlMs: config.signoutMarkerTtlMs ?? DEFAULT_SIGNOUT_TTL_MS,
478
+ requireOAuthState: config.requireOAuthState ?? true,
479
+ stateCookieName: config.stateCookieName ?? "iqauth_state"
431
480
  };
432
481
  }
482
+ function timingSafeEqualStr(a, b) {
483
+ const len = Math.max(a.length, b.length);
484
+ let diff = a.length ^ b.length;
485
+ for (let i = 0; i < len; i++) {
486
+ diff |= (a.charCodeAt(i) || 0) ^ (b.charCodeAt(i) || 0);
487
+ }
488
+ return diff === 0;
489
+ }
433
490
  function makeCookie(cfg, name, value, maxAge, httpOnly = true) {
434
491
  return {
435
492
  name,
@@ -448,6 +505,9 @@ function clearCookies(cfg) {
448
505
  { ...makeCookie(cfg, cfg.refreshCookieName, "", 0), clear: true }
449
506
  ];
450
507
  }
508
+ function clearStateCookie(cfg) {
509
+ return { ...makeCookie(cfg, cfg.stateCookieName, "", 0, false), clear: true };
510
+ }
451
511
  var DEFAULT_SIGNOUT_TTL_MS = 6e4;
452
512
  var inMemorySignoutMarkers = /* @__PURE__ */ new Map();
453
513
  function pruneInMemoryMarkers(now) {
@@ -473,6 +533,15 @@ var defaultSignoutRegistry = {
473
533
  return true;
474
534
  }
475
535
  };
536
+ var warnedDefaultSignoutRegistry = false;
537
+ function maybeWarnDefaultSignoutRegistry(config) {
538
+ if (warnedDefaultSignoutRegistry) return;
539
+ if (config.signoutRegistry) return;
540
+ warnedDefaultSignoutRegistry = true;
541
+ console.warn(
542
+ "[IQAuth] Using the in-memory signout registry (process-local). Signout idempotency is NOT shared across instances \u2014 in a multi-replica deployment a /refresh racing a /signout on another replica can reissue cookies after sign-out. Plug a shared backend (e.g. Redis) into IQAuthHelperConfig.signoutRegistry to fix this and silence this warning."
543
+ );
544
+ }
476
545
  function serializeCookie(d) {
477
546
  const parts = [`${d.name}=${encodeURIComponent(d.value)}`];
478
547
  parts.push(`Path=${d.path}`);
@@ -495,6 +564,23 @@ async function handleCallback(config, input) {
495
564
  cookies: []
496
565
  };
497
566
  }
567
+ const provided = input.state;
568
+ const expected = input.expectedState;
569
+ const stateOk = cfg.requireOAuthState ? !!expected && !!provided && timingSafeEqualStr(provided, expected) : !expected || !!provided && timingSafeEqualStr(provided, expected);
570
+ if (!stateOk) {
571
+ emitTiming(cfg, { phase: "callback", durationMs: Date.now() - t0, ok: false, code: "STATE_MISMATCH" });
572
+ return {
573
+ status: 400,
574
+ body: {
575
+ success: false,
576
+ error: {
577
+ code: "STATE_MISMATCH",
578
+ message: "OAuth state validation failed; the sign-in could not be verified as originating from this browser."
579
+ }
580
+ },
581
+ cookies: [clearStateCookie(cfg)]
582
+ };
583
+ }
498
584
  if (!cfg.secretKey) {
499
585
  emitTiming(cfg, { phase: "callback", durationMs: Date.now() - t0, ok: false, code: "INTERNAL_ERROR" });
500
586
  return {
@@ -533,6 +619,26 @@ async function handleCallback(config, input) {
533
619
  cookies: []
534
620
  };
535
621
  }
622
+ try {
623
+ await getTokensFor(cfg.issuer).verify(json.access_token, {
624
+ issuer: cfg.issuer,
625
+ ...config.verify
626
+ });
627
+ } catch (err) {
628
+ const code = err instanceof IQAuthError ? err.code : err.code || "TOKEN_INVALID";
629
+ emitTiming(cfg, { phase: "callback", durationMs: Date.now() - t0, ok: false, code });
630
+ return {
631
+ status: 502,
632
+ body: {
633
+ success: false,
634
+ error: {
635
+ code: "ACCESS_TOKEN_VERIFICATION_FAILED",
636
+ message: "The issuer returned an access token that failed verification; no session was established."
637
+ }
638
+ },
639
+ cookies: []
640
+ };
641
+ }
536
642
  const cookies = [];
537
643
  cookies.push(
538
644
  makeCookie(cfg, cfg.accessCookieName, json.access_token, json.expires_in ?? ACCESS_TOKEN_TTL_SECONDS)
@@ -540,6 +646,7 @@ async function handleCallback(config, input) {
540
646
  if (json.refresh_token) {
541
647
  cookies.push(makeCookie(cfg, cfg.refreshCookieName, json.refresh_token, REFRESH_TOKEN_TTL_SECONDS));
542
648
  }
649
+ cookies.push(clearStateCookie(cfg));
543
650
  emitTiming(cfg, { phase: "callback", durationMs: Date.now() - t0, ok: true });
544
651
  return {
545
652
  status: 200,
@@ -661,7 +768,10 @@ async function handleUserinfo(config, input) {
661
768
  }
662
769
  let claims;
663
770
  try {
664
- claims = await getTokensFor(cfg.issuer).verify(input.accessToken, config.verify);
771
+ claims = await getTokensFor(cfg.issuer).verify(input.accessToken, {
772
+ issuer: cfg.issuer,
773
+ ...config.verify
774
+ });
665
775
  } catch (err) {
666
776
  const code = err instanceof IQAuthError ? err.code : err.code || "TOKEN_INVALID";
667
777
  const message = err instanceof Error ? err.message : "Access token verification failed";
@@ -681,7 +791,44 @@ async function handleUserinfo(config, input) {
681
791
  };
682
792
  }
683
793
 
794
+ // src/browser/returnTo.ts
795
+ function normalizeOrigin(o) {
796
+ try {
797
+ return new URL(o).origin;
798
+ } catch {
799
+ return o.replace(/\/+$/, "");
800
+ }
801
+ }
802
+ function sanitizeReturnTo(input, options = {}) {
803
+ const fallback = options.fallback ?? "/";
804
+ if (!input || typeof input !== "string") return fallback;
805
+ const trimmed = input.trim();
806
+ if (!trimmed) return fallback;
807
+ if (trimmed.includes("\\")) return fallback;
808
+ if (trimmed.startsWith("//")) return fallback;
809
+ if (trimmed.startsWith("/") || trimmed.startsWith("#") || trimmed.startsWith("?")) {
810
+ return trimmed;
811
+ }
812
+ if (!/^[a-z][a-z0-9+\-.]*:/i.test(trimmed)) {
813
+ return trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
814
+ }
815
+ let parsed;
816
+ try {
817
+ parsed = new URL(trimmed);
818
+ } catch {
819
+ return fallback;
820
+ }
821
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return fallback;
822
+ const currentOrigin = options.currentOrigin ?? (typeof window !== "undefined" ? window.location.origin : "");
823
+ const allowed = /* @__PURE__ */ new Set();
824
+ if (currentOrigin) allowed.add(normalizeOrigin(currentOrigin));
825
+ for (const o of options.allowedOrigins ?? []) allowed.add(normalizeOrigin(o));
826
+ if (allowed.has(parsed.origin)) return parsed.toString();
827
+ return fallback;
828
+ }
829
+
684
830
  // src/next.ts
831
+ var PKCE_COOKIE = "iqauth_pkce";
685
832
  function readCookieFromHeader(header, name) {
686
833
  if (!header) return void 0;
687
834
  const target = `${name}=`;
@@ -702,12 +849,43 @@ function toResponse(hr) {
702
849
  for (const c of hr.cookies) headers.append("set-cookie", serializeCookie(c));
703
850
  return new Response(JSON.stringify(hr.body), { status: hr.status, headers });
704
851
  }
852
+ function callbackResponse(hr, requestOrigin, returnToCookieValue, returnToCookieName) {
853
+ const returnTo = sanitizeReturnTo(
854
+ returnToCookieValue || hr.body?.returnTo,
855
+ { currentOrigin: requestOrigin, fallback: "/" }
856
+ );
857
+ const headers = new Headers({ "Content-Type": "application/json" });
858
+ for (const c of hr.cookies) headers.append("set-cookie", serializeCookie(c));
859
+ if (hr.status < 400) {
860
+ headers.append("set-cookie", `${returnToCookieName}=; Path=/; Max-Age=0; SameSite=Lax`);
861
+ }
862
+ const body = { ...hr.body, returnTo };
863
+ return new Response(JSON.stringify(body), { status: hr.status, headers });
864
+ }
865
+ function callbackRedirectResponse(hr, requestOrigin, returnToCookieValue, cookieNames) {
866
+ const headers = new Headers();
867
+ for (const c of hr.cookies) headers.append("set-cookie", serializeCookie(c));
868
+ headers.append("set-cookie", `${cookieNames.state}=; Path=/; Max-Age=0; SameSite=Lax`);
869
+ headers.append("set-cookie", `${cookieNames.pkce}=; Path=/; Max-Age=0; SameSite=Lax`);
870
+ if (hr.status >= 400) {
871
+ headers.set("Location", "/");
872
+ return new Response(null, { status: 302, headers });
873
+ }
874
+ const dest = sanitizeReturnTo(returnToCookieValue, {
875
+ currentOrigin: requestOrigin,
876
+ fallback: "/"
877
+ });
878
+ headers.append("set-cookie", `${cookieNames.returnTo}=; Path=/; Max-Age=0; SameSite=Lax`);
879
+ headers.set("Location", dest);
880
+ return new Response(null, { status: 302, headers });
881
+ }
705
882
  function handler(options) {
706
883
  const parsed = assertPublishableKey(options.publishableKey, { context: "@iqauth/sdk/next handler" });
707
884
  const issuer = (options.issuer ?? (parsed.iss.startsWith("http") ? parsed.iss : `https://${parsed.iss}`)).replace(/\/+$/, "");
708
885
  const helperConfig = { ...options, issuer };
709
886
  const accessCookie = options.accessCookieName ?? "iqauth_at";
710
887
  const refreshCookie = options.refreshCookieName ?? "iqauth_rt";
888
+ const returnToCookie = options.returnToCookieName ?? "iqauth_return_to";
711
889
  return async (req) => {
712
890
  const url = new URL(req.url);
713
891
  const action = url.pathname.split("/").pop();
@@ -723,13 +901,36 @@ function handler(options) {
723
901
  const accessToken = auth && auth.replace(/^Bearer /i, "") || readCookieFromHeader(cookieHeader, accessCookie);
724
902
  return toResponse(await handleUserinfo(helperConfig, { accessToken, req }));
725
903
  }
904
+ const stateCookie = helperConfig.stateCookieName ?? "iqauth_state";
905
+ if (action === "callback" && req.method === "GET") {
906
+ const code = url.searchParams.get("code") ?? void 0;
907
+ const state = url.searchParams.get("state") ?? void 0;
908
+ const redirectUri = `${url.origin}${url.pathname}`;
909
+ const hr = await handleCallback(helperConfig, {
910
+ code,
911
+ codeVerifier: readCookieFromHeader(cookieHeader, PKCE_COOKIE),
912
+ redirectUri,
913
+ state,
914
+ expectedState: readCookieFromHeader(cookieHeader, stateCookie)
915
+ });
916
+ return callbackRedirectResponse(
917
+ hr,
918
+ url.origin,
919
+ readCookieFromHeader(cookieHeader, returnToCookie),
920
+ { returnTo: returnToCookie, state: stateCookie, pkce: PKCE_COOKIE }
921
+ );
922
+ }
726
923
  const body = await req.json().catch(() => ({}));
727
924
  if (action === "callback") {
728
- return toResponse(await handleCallback(helperConfig, {
925
+ const hr = await handleCallback(helperConfig, {
729
926
  code: body.code,
730
927
  codeVerifier: body.codeVerifier,
731
- redirectUri: body.redirectUri
732
- }));
928
+ redirectUri: body.redirectUri,
929
+ // M-2: bind callback to this browser; handleCallback fails closed.
930
+ state: body.state,
931
+ expectedState: readCookieFromHeader(cookieHeader, helperConfig.stateCookieName ?? "iqauth_state")
932
+ });
933
+ return callbackResponse(hr, url.origin, readCookieFromHeader(cookieHeader, returnToCookie), returnToCookie);
733
934
  }
734
935
  if (action === "refresh") {
735
936
  const refreshToken = body.refreshToken || readCookieFromHeader(cookieHeader, refreshCookie);
package/dist/next.mjs CHANGED
@@ -1,10 +1,13 @@
1
+ import {
2
+ sanitizeReturnTo
3
+ } from "./chunk-JRDVUWAL.mjs";
1
4
  import {
2
5
  handleCallback,
3
6
  handleRefresh,
4
7
  handleSignout,
5
8
  handleUserinfo,
6
9
  serializeCookie
7
- } from "./chunk-RUJXRTEW.mjs";
10
+ } from "./chunk-WSH4SW7F.mjs";
8
11
  import {
9
12
  assertPublishableKey
10
13
  } from "./chunk-HVHNYPDC.mjs";
@@ -15,6 +18,7 @@ import "./chunk-6PJRLRB4.mjs";
15
18
  import "./chunk-Y6FXYEAI.mjs";
16
19
 
17
20
  // src/next.ts
21
+ var PKCE_COOKIE = "iqauth_pkce";
18
22
  function readCookieFromHeader(header, name) {
19
23
  if (!header) return void 0;
20
24
  const target = `${name}=`;
@@ -35,12 +39,43 @@ function toResponse(hr) {
35
39
  for (const c of hr.cookies) headers.append("set-cookie", serializeCookie(c));
36
40
  return new Response(JSON.stringify(hr.body), { status: hr.status, headers });
37
41
  }
42
+ function callbackResponse(hr, requestOrigin, returnToCookieValue, returnToCookieName) {
43
+ const returnTo = sanitizeReturnTo(
44
+ returnToCookieValue || hr.body?.returnTo,
45
+ { currentOrigin: requestOrigin, fallback: "/" }
46
+ );
47
+ const headers = new Headers({ "Content-Type": "application/json" });
48
+ for (const c of hr.cookies) headers.append("set-cookie", serializeCookie(c));
49
+ if (hr.status < 400) {
50
+ headers.append("set-cookie", `${returnToCookieName}=; Path=/; Max-Age=0; SameSite=Lax`);
51
+ }
52
+ const body = { ...hr.body, returnTo };
53
+ return new Response(JSON.stringify(body), { status: hr.status, headers });
54
+ }
55
+ function callbackRedirectResponse(hr, requestOrigin, returnToCookieValue, cookieNames) {
56
+ const headers = new Headers();
57
+ for (const c of hr.cookies) headers.append("set-cookie", serializeCookie(c));
58
+ headers.append("set-cookie", `${cookieNames.state}=; Path=/; Max-Age=0; SameSite=Lax`);
59
+ headers.append("set-cookie", `${cookieNames.pkce}=; Path=/; Max-Age=0; SameSite=Lax`);
60
+ if (hr.status >= 400) {
61
+ headers.set("Location", "/");
62
+ return new Response(null, { status: 302, headers });
63
+ }
64
+ const dest = sanitizeReturnTo(returnToCookieValue, {
65
+ currentOrigin: requestOrigin,
66
+ fallback: "/"
67
+ });
68
+ headers.append("set-cookie", `${cookieNames.returnTo}=; Path=/; Max-Age=0; SameSite=Lax`);
69
+ headers.set("Location", dest);
70
+ return new Response(null, { status: 302, headers });
71
+ }
38
72
  function handler(options) {
39
73
  const parsed = assertPublishableKey(options.publishableKey, { context: "@iqauth/sdk/next handler" });
40
74
  const issuer = (options.issuer ?? (parsed.iss.startsWith("http") ? parsed.iss : `https://${parsed.iss}`)).replace(/\/+$/, "");
41
75
  const helperConfig = { ...options, issuer };
42
76
  const accessCookie = options.accessCookieName ?? "iqauth_at";
43
77
  const refreshCookie = options.refreshCookieName ?? "iqauth_rt";
78
+ const returnToCookie = options.returnToCookieName ?? "iqauth_return_to";
44
79
  return async (req) => {
45
80
  const url = new URL(req.url);
46
81
  const action = url.pathname.split("/").pop();
@@ -56,13 +91,36 @@ function handler(options) {
56
91
  const accessToken = auth && auth.replace(/^Bearer /i, "") || readCookieFromHeader(cookieHeader, accessCookie);
57
92
  return toResponse(await handleUserinfo(helperConfig, { accessToken, req }));
58
93
  }
94
+ const stateCookie = helperConfig.stateCookieName ?? "iqauth_state";
95
+ if (action === "callback" && req.method === "GET") {
96
+ const code = url.searchParams.get("code") ?? void 0;
97
+ const state = url.searchParams.get("state") ?? void 0;
98
+ const redirectUri = `${url.origin}${url.pathname}`;
99
+ const hr = await handleCallback(helperConfig, {
100
+ code,
101
+ codeVerifier: readCookieFromHeader(cookieHeader, PKCE_COOKIE),
102
+ redirectUri,
103
+ state,
104
+ expectedState: readCookieFromHeader(cookieHeader, stateCookie)
105
+ });
106
+ return callbackRedirectResponse(
107
+ hr,
108
+ url.origin,
109
+ readCookieFromHeader(cookieHeader, returnToCookie),
110
+ { returnTo: returnToCookie, state: stateCookie, pkce: PKCE_COOKIE }
111
+ );
112
+ }
59
113
  const body = await req.json().catch(() => ({}));
60
114
  if (action === "callback") {
61
- return toResponse(await handleCallback(helperConfig, {
115
+ const hr = await handleCallback(helperConfig, {
62
116
  code: body.code,
63
117
  codeVerifier: body.codeVerifier,
64
- redirectUri: body.redirectUri
65
- }));
118
+ redirectUri: body.redirectUri,
119
+ // M-2: bind callback to this browser; handleCallback fails closed.
120
+ state: body.state,
121
+ expectedState: readCookieFromHeader(cookieHeader, helperConfig.stateCookieName ?? "iqauth_state")
122
+ });
123
+ return callbackResponse(hr, url.origin, readCookieFromHeader(cookieHeader, returnToCookie), returnToCookie);
66
124
  }
67
125
  if (action === "refresh") {
68
126
  const refreshToken = body.refreshToken || readCookieFromHeader(cookieHeader, refreshCookie);
@@ -1,4 +1,4 @@
1
- import { J as JwtClaims } from './types-XOV9XPVi.mjs';
1
+ import { J as JwtClaims } from './types-Bn8O-OEd.js';
2
2
 
3
3
  /**
4
4
  * createProvisioningBridge — server-side helper that lifts the
@@ -21,6 +21,17 @@ import { J as JwtClaims } from './types-XOV9XPVi.mjs';
21
21
  * your local user table. See the JSDoc on each adapter for the contract.
22
22
  */
23
23
 
24
+ /**
25
+ * Thrown when the bridge refuses to adopt a pre-existing local account because
26
+ * the IQAuth claims do not assert a verified email (`email_verified !== true`)
27
+ * and the integrator has not opted in via `allowUnverifiedEmailAdopt`. Carries
28
+ * a stable `.code` so callers can branch (e.g. provision a brand-new row under
29
+ * a different identity instead of adopting the email-matched one).
30
+ */
31
+ declare class ProvisioningError extends Error {
32
+ code: string;
33
+ constructor(code: string, message: string);
34
+ }
24
35
  interface ProvisioningContext<TUser> {
25
36
  claims: JwtClaims;
26
37
  /** The local user record, looked up or freshly inserted. */
@@ -59,6 +70,23 @@ interface ProvisioningBridgeOptions<TUser> {
59
70
  * Defaults to checking for Postgres `23505` and SQLite `SQLITE_CONSTRAINT_UNIQUE`.
60
71
  */
61
72
  isUniqueViolation?: (err: unknown) => boolean;
73
+ /**
74
+ * Security gate (H-4): adopting a pre-existing local row matched by email is
75
+ * only performed when the IQAuth claims assert a verified email
76
+ * (`claims.email_verified === true`). When the claim is absent/false and a
77
+ * local row matches the email, the bridge **refuses to adopt** and throws
78
+ * `ProvisioningError("UNVERIFIED_EMAIL_ADOPT_REFUSED")` (fail closed) so an
79
+ * IdP that does not assert email verification cannot silently take over an
80
+ * existing account.
81
+ *
82
+ * Brand-new users (no email-matched row) are unaffected — there is nothing
83
+ * to take over, so they are inserted regardless of verification status.
84
+ *
85
+ * Set `true` ONLY when your issuer is trusted to never emit an unverified
86
+ * email for adoption (or you have a compensating control). Defaults to
87
+ * `false` (secure).
88
+ */
89
+ allowUnverifiedEmailAdopt?: boolean;
62
90
  }
63
91
  interface ProvisioningBridge<TUser> {
64
92
  /**
@@ -83,4 +111,4 @@ interface ProvisioningBridge<TUser> {
83
111
  */
84
112
  declare function createProvisioningBridge<TUser>(options: ProvisioningBridgeOptions<TUser>): ProvisioningBridge<TUser>;
85
113
 
86
- export { type ProvisioningBridge as P, type ProvisioningBridgeOptions as a, type ProvisioningStorage as b, createProvisioningBridge as c, type ProvisioningContext as d };
114
+ export { type ProvisioningBridge as P, type ProvisioningBridgeOptions as a, type ProvisioningStorage as b, createProvisioningBridge as c, type ProvisioningContext as d, ProvisioningError as e };
@@ -1,4 +1,4 @@
1
- import { J as JwtClaims } from './types-XOV9XPVi.js';
1
+ import { J as JwtClaims } from './types-Bn8O-OEd.mjs';
2
2
 
3
3
  /**
4
4
  * createProvisioningBridge — server-side helper that lifts the
@@ -21,6 +21,17 @@ import { J as JwtClaims } from './types-XOV9XPVi.js';
21
21
  * your local user table. See the JSDoc on each adapter for the contract.
22
22
  */
23
23
 
24
+ /**
25
+ * Thrown when the bridge refuses to adopt a pre-existing local account because
26
+ * the IQAuth claims do not assert a verified email (`email_verified !== true`)
27
+ * and the integrator has not opted in via `allowUnverifiedEmailAdopt`. Carries
28
+ * a stable `.code` so callers can branch (e.g. provision a brand-new row under
29
+ * a different identity instead of adopting the email-matched one).
30
+ */
31
+ declare class ProvisioningError extends Error {
32
+ code: string;
33
+ constructor(code: string, message: string);
34
+ }
24
35
  interface ProvisioningContext<TUser> {
25
36
  claims: JwtClaims;
26
37
  /** The local user record, looked up or freshly inserted. */
@@ -59,6 +70,23 @@ interface ProvisioningBridgeOptions<TUser> {
59
70
  * Defaults to checking for Postgres `23505` and SQLite `SQLITE_CONSTRAINT_UNIQUE`.
60
71
  */
61
72
  isUniqueViolation?: (err: unknown) => boolean;
73
+ /**
74
+ * Security gate (H-4): adopting a pre-existing local row matched by email is
75
+ * only performed when the IQAuth claims assert a verified email
76
+ * (`claims.email_verified === true`). When the claim is absent/false and a
77
+ * local row matches the email, the bridge **refuses to adopt** and throws
78
+ * `ProvisioningError("UNVERIFIED_EMAIL_ADOPT_REFUSED")` (fail closed) so an
79
+ * IdP that does not assert email verification cannot silently take over an
80
+ * existing account.
81
+ *
82
+ * Brand-new users (no email-matched row) are unaffected — there is nothing
83
+ * to take over, so they are inserted regardless of verification status.
84
+ *
85
+ * Set `true` ONLY when your issuer is trusted to never emit an unverified
86
+ * email for adoption (or you have a compensating control). Defaults to
87
+ * `false` (secure).
88
+ */
89
+ allowUnverifiedEmailAdopt?: boolean;
62
90
  }
63
91
  interface ProvisioningBridge<TUser> {
64
92
  /**
@@ -83,4 +111,4 @@ interface ProvisioningBridge<TUser> {
83
111
  */
84
112
  declare function createProvisioningBridge<TUser>(options: ProvisioningBridgeOptions<TUser>): ProvisioningBridge<TUser>;
85
113
 
86
- export { type ProvisioningBridge as P, type ProvisioningBridgeOptions as a, type ProvisioningStorage as b, createProvisioningBridge as c, type ProvisioningContext as d };
114
+ export { type ProvisioningBridge as P, type ProvisioningBridgeOptions as a, type ProvisioningStorage as b, createProvisioningBridge as c, type ProvisioningContext as d, ProvisioningError as e };
@@ -1,11 +1,11 @@
1
- import { S as SessionError } from './index-CKoZHAoc.mjs';
1
+ import { S as SessionError } from './index-Cko-d5po.mjs';
2
2
  import 'csstype';
3
3
  import 'react/jsx-runtime';
4
4
  import 'react';
5
- import './signIn-T-CZ6t6r.mjs';
5
+ import './signIn-CReqfXsh.mjs';
6
6
  import './publishableKey-f2kq-rKw.mjs';
7
- import './types-XOV9XPVi.mjs';
8
- import './types-BdQ2lqfT.mjs';
7
+ import './types-Bn8O-OEd.mjs';
8
+ import './types-DnU2LhXR.mjs';
9
9
 
10
10
  interface UseEffectivePermissionsOptions {
11
11
  /**
@@ -1,11 +1,11 @@
1
- import { S as SessionError } from './index-5KSZEnDe.js';
1
+ import { S as SessionError } from './index-RNqwEcmY.js';
2
2
  import 'csstype';
3
3
  import 'react/jsx-runtime';
4
4
  import 'react';
5
- import './signIn-BLFnz8SV.js';
5
+ import './signIn-Cfa1GTpO.js';
6
6
  import './publishableKey-f2kq-rKw.js';
7
- import './types-XOV9XPVi.js';
8
- import './types-BdQ2lqfT.js';
7
+ import './types-Bn8O-OEd.js';
8
+ import './types-DnU2LhXR.js';
9
9
 
10
10
  interface UseEffectivePermissionsOptions {
11
11
  /**
@@ -1,15 +1,16 @@
1
1
  import {
2
2
  __useIQAuthInternal
3
- } from "./chunk-RR2MGPTK.mjs";
4
- import "./chunk-RTJAIBXY.mjs";
3
+ } from "./chunk-WHT6WKTY.mjs";
4
+ import "./chunk-4V7FKOTG.mjs";
5
5
  import "./chunk-GN37E64I.mjs";
6
6
  import "./chunk-C2ZTBOAC.mjs";
7
+ import "./chunk-JRDVUWAL.mjs";
7
8
  import {
8
9
  expandPermissions,
9
10
  hasPermission
10
11
  } from "./chunk-GLXSIGVS.mjs";
11
12
  import "./chunk-HVHNYPDC.mjs";
12
- import "./chunk-5T7GHBX6.mjs";
13
+ import "./chunk-TLET552H.mjs";
13
14
  import "./chunk-6PJRLRB4.mjs";
14
15
  import "./chunk-Y6FXYEAI.mjs";
15
16
 
package/dist/react.d.mts CHANGED
@@ -1,11 +1,11 @@
1
- export { A as AccountSummary, K as AuthCallback, J as AuthCallbackProps, af as CreateOrganization, ad as CreateOrganizationProps, a as IQAuthAppearance, I as IQAuthAppearanceElements, L as IQAuthBranding, x as IQAuthLoaded, w as IQAuthLoading, c as IQAuthProvider, b as IQAuthProviderProps, G as IQAuthReturnToBouncer, F as IQAuthReturnToBouncerProps, N as IQAuthSignInContext, aa as ImpersonationBanner, a9 as ImpersonationBannerProps, a7 as ImpersonationInfo, ax as LinkedAccounts, aw as LinkedAccountsProps, at as MagicLinkSignInForm, as as MagicLinkSignInFormProps, M as MultisessionAppSupport, aj as OrganizationList, ai as OrganizationListProps, ah as OrganizationProfile, ag as OrganizationProfileProps, a6 as OrganizationSwitcher, a5 as OrganizationSwitcherProps, av as PasskeySignInButton, au as PasskeySignInButtonProps, z as Protect, P as ProtectProps, y as RedirectToSignIn, R as RedirectToSignInProps, C as RedirectToSignedIn, B as RedirectToSignedInProps, S as SessionError, m as SessionListItem, O as SharedComponentProps, Y as SignIn, W as SignInProps, $ as SignUp, Z as SignUpProps, t as SignedIn, v as SignedOut, q as UseAccountSwitcherResult, h as UseAuthResult, aq as UseLinkedIdentitiesResult, am as UseMagicLinkResult, j as UseOrganizationResult, ao as UsePasskeyResult, D as UseReturnToOptions, ab as UseReverificationOptions, n as UseSessionListResult, f as UseSessionResult, U as UseUserResult, a2 as UserButton, a1 as UserButtonProps, a4 as UserProfile, a3 as UserProfileProps, a0 as UserSummary, al as Waitlist, ak as WaitlistProps, _ as __useIQAuthInternal, ay as __version__, X as isSilentSsoEligible, H as preflightReturnTo, r as revokeSession, T as sanitizeBrandCss, ae as slugify, p as useAccountList, s as useAccountSwitcher, i as useAuth, l as useAuthFetch, Q as useIQAuthSignInContext, a8 as useImpersonation, ar as useLinkedIdentities, u as useLocale, an as useMagicLink, k as useOrganization, ap as usePasskey, V as useResolvedSdkBranding, E as useReturnTo, ac as useReverification, g as useSession, o as useSessionList, d as useT, e as useUser } from './index-CKoZHAoc.mjs';
2
- export { I as IQAuthLocaleBundle, a as IQAuthLocaleKey, b as IQAuthLocaleOverride } from './types-BdQ2lqfT.mjs';
1
+ export { A as AccountSummary, Q as AuthCallback, O as AuthCallbackProps, aq as CreateOrganization, ao as CreateOrganizationProps, a as IQAuthAppearance, I as IQAuthAppearanceElements, V as IQAuthBranding, x as IQAuthLoaded, w as IQAuthLoading, c as IQAuthProvider, b as IQAuthProviderProps, L as IQAuthReturnToBouncer, K as IQAuthReturnToBouncerProps, W as IQAuthSignInContext, al as ImpersonationBanner, ak as ImpersonationBannerProps, ai as ImpersonationInfo, aI as LinkedAccounts, aH as LinkedAccountsProps, aE as MagicLinkSignInForm, aD as MagicLinkSignInFormProps, M as MultisessionAppSupport, au as OrganizationList, at as OrganizationListProps, as as OrganizationProfile, ar as OrganizationProfileProps, ac as OrganizationSwitcher, ab as OrganizationSwitcherProps, aG as PasskeySignInButton, aF as PasskeySignInButtonProps, E as Protect, P as ProtectProps, y as RedirectToSignIn, R as RedirectToSignInProps, G as RedirectToSignedIn, F as RedirectToSignedInProps, C as ScopeRequirement, ah as ScopeSwitcher, ag as ScopeSwitcherProps, ad as ScopedMembership, S as SessionError, m as SessionListItem, X as SharedComponentProps, a3 as SignIn, a0 as SignInProps, a5 as SignUp, a4 as SignUpProps, t as SignedIn, v as SignedOut, T as TenantSwitchResult, q as UseAccountSwitcherResult, h as UseAuthResult, aB as UseLinkedIdentitiesResult, ax as UseMagicLinkResult, ae as UseMembershipsResult, j as UseOrganizationResult, az as UsePasskeyResult, H as UseReturnToOptions, am as UseReverificationOptions, n as UseSessionListResult, f as UseSessionResult, U as UseUserResult, a8 as UserButton, a7 as UserButtonProps, aa as UserProfile, a9 as UserProfileProps, a6 as UserSummary, aw as Waitlist, av as WaitlistProps, _ as __useIQAuthInternal, aJ as __version__, D as claimSatisfiesScope, a1 as isSilentSsoEligible, z as performScopeSwitch, B as performTenantSwitch, N as preflightReturnTo, a2 as resolveAfterSignInDestination, r as revokeSession, Z as sanitizeBrandCss, ap as slugify, p as useAccountList, s as useAccountSwitcher, i as useAuth, l as useAuthFetch, Y as useIQAuthSignInContext, aj as useImpersonation, aC as useLinkedIdentities, u as useLocale, ay as useMagicLink, af as useMemberships, k as useOrganization, aA as usePasskey, $ as useResolvedSdkBranding, J as useReturnTo, an as useReverification, g as useSession, o as useSessionList, d as useT, e as useUser } from './index-Cko-d5po.mjs';
2
+ export { I as IQAuthLocaleBundle, a as IQAuthLocaleKey, b as IQAuthLocaleOverride } from './types-DnU2LhXR.mjs';
3
3
  import 'csstype';
4
4
  import 'react/jsx-runtime';
5
5
  import 'react';
6
- import './signIn-T-CZ6t6r.mjs';
6
+ import './signIn-CReqfXsh.mjs';
7
7
  import './publishableKey-f2kq-rKw.mjs';
8
- import './types-XOV9XPVi.mjs';
8
+ import './types-Bn8O-OEd.mjs';
9
9
 
10
10
  /**
11
11
  * F4 — return-to URL handling.
package/dist/react.d.ts CHANGED
@@ -1,11 +1,11 @@
1
- export { A as AccountSummary, K as AuthCallback, J as AuthCallbackProps, af as CreateOrganization, ad as CreateOrganizationProps, a as IQAuthAppearance, I as IQAuthAppearanceElements, L as IQAuthBranding, x as IQAuthLoaded, w as IQAuthLoading, c as IQAuthProvider, b as IQAuthProviderProps, G as IQAuthReturnToBouncer, F as IQAuthReturnToBouncerProps, N as IQAuthSignInContext, aa as ImpersonationBanner, a9 as ImpersonationBannerProps, a7 as ImpersonationInfo, ax as LinkedAccounts, aw as LinkedAccountsProps, at as MagicLinkSignInForm, as as MagicLinkSignInFormProps, M as MultisessionAppSupport, aj as OrganizationList, ai as OrganizationListProps, ah as OrganizationProfile, ag as OrganizationProfileProps, a6 as OrganizationSwitcher, a5 as OrganizationSwitcherProps, av as PasskeySignInButton, au as PasskeySignInButtonProps, z as Protect, P as ProtectProps, y as RedirectToSignIn, R as RedirectToSignInProps, C as RedirectToSignedIn, B as RedirectToSignedInProps, S as SessionError, m as SessionListItem, O as SharedComponentProps, Y as SignIn, W as SignInProps, $ as SignUp, Z as SignUpProps, t as SignedIn, v as SignedOut, q as UseAccountSwitcherResult, h as UseAuthResult, aq as UseLinkedIdentitiesResult, am as UseMagicLinkResult, j as UseOrganizationResult, ao as UsePasskeyResult, D as UseReturnToOptions, ab as UseReverificationOptions, n as UseSessionListResult, f as UseSessionResult, U as UseUserResult, a2 as UserButton, a1 as UserButtonProps, a4 as UserProfile, a3 as UserProfileProps, a0 as UserSummary, al as Waitlist, ak as WaitlistProps, _ as __useIQAuthInternal, ay as __version__, X as isSilentSsoEligible, H as preflightReturnTo, r as revokeSession, T as sanitizeBrandCss, ae as slugify, p as useAccountList, s as useAccountSwitcher, i as useAuth, l as useAuthFetch, Q as useIQAuthSignInContext, a8 as useImpersonation, ar as useLinkedIdentities, u as useLocale, an as useMagicLink, k as useOrganization, ap as usePasskey, V as useResolvedSdkBranding, E as useReturnTo, ac as useReverification, g as useSession, o as useSessionList, d as useT, e as useUser } from './index-5KSZEnDe.js';
2
- export { I as IQAuthLocaleBundle, a as IQAuthLocaleKey, b as IQAuthLocaleOverride } from './types-BdQ2lqfT.js';
1
+ export { A as AccountSummary, Q as AuthCallback, O as AuthCallbackProps, aq as CreateOrganization, ao as CreateOrganizationProps, a as IQAuthAppearance, I as IQAuthAppearanceElements, V as IQAuthBranding, x as IQAuthLoaded, w as IQAuthLoading, c as IQAuthProvider, b as IQAuthProviderProps, L as IQAuthReturnToBouncer, K as IQAuthReturnToBouncerProps, W as IQAuthSignInContext, al as ImpersonationBanner, ak as ImpersonationBannerProps, ai as ImpersonationInfo, aI as LinkedAccounts, aH as LinkedAccountsProps, aE as MagicLinkSignInForm, aD as MagicLinkSignInFormProps, M as MultisessionAppSupport, au as OrganizationList, at as OrganizationListProps, as as OrganizationProfile, ar as OrganizationProfileProps, ac as OrganizationSwitcher, ab as OrganizationSwitcherProps, aG as PasskeySignInButton, aF as PasskeySignInButtonProps, E as Protect, P as ProtectProps, y as RedirectToSignIn, R as RedirectToSignInProps, G as RedirectToSignedIn, F as RedirectToSignedInProps, C as ScopeRequirement, ah as ScopeSwitcher, ag as ScopeSwitcherProps, ad as ScopedMembership, S as SessionError, m as SessionListItem, X as SharedComponentProps, a3 as SignIn, a0 as SignInProps, a5 as SignUp, a4 as SignUpProps, t as SignedIn, v as SignedOut, T as TenantSwitchResult, q as UseAccountSwitcherResult, h as UseAuthResult, aB as UseLinkedIdentitiesResult, ax as UseMagicLinkResult, ae as UseMembershipsResult, j as UseOrganizationResult, az as UsePasskeyResult, H as UseReturnToOptions, am as UseReverificationOptions, n as UseSessionListResult, f as UseSessionResult, U as UseUserResult, a8 as UserButton, a7 as UserButtonProps, aa as UserProfile, a9 as UserProfileProps, a6 as UserSummary, aw as Waitlist, av as WaitlistProps, _ as __useIQAuthInternal, aJ as __version__, D as claimSatisfiesScope, a1 as isSilentSsoEligible, z as performScopeSwitch, B as performTenantSwitch, N as preflightReturnTo, a2 as resolveAfterSignInDestination, r as revokeSession, Z as sanitizeBrandCss, ap as slugify, p as useAccountList, s as useAccountSwitcher, i as useAuth, l as useAuthFetch, Y as useIQAuthSignInContext, aj as useImpersonation, aC as useLinkedIdentities, u as useLocale, ay as useMagicLink, af as useMemberships, k as useOrganization, aA as usePasskey, $ as useResolvedSdkBranding, J as useReturnTo, an as useReverification, g as useSession, o as useSessionList, d as useT, e as useUser } from './index-RNqwEcmY.js';
2
+ export { I as IQAuthLocaleBundle, a as IQAuthLocaleKey, b as IQAuthLocaleOverride } from './types-DnU2LhXR.js';
3
3
  import 'csstype';
4
4
  import 'react/jsx-runtime';
5
5
  import 'react';
6
- import './signIn-BLFnz8SV.js';
6
+ import './signIn-Cfa1GTpO.js';
7
7
  import './publishableKey-f2kq-rKw.js';
8
- import './types-XOV9XPVi.js';
8
+ import './types-Bn8O-OEd.js';
9
9
 
10
10
  /**
11
11
  * F4 — return-to URL handling.