@turnkey/react-wallet-kit 2.3.1 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/components/auth/OTP.d.ts.map +1 -1
  2. package/dist/components/auth/OTP.js +12 -8
  3. package/dist/components/auth/OTP.js.map +1 -1
  4. package/dist/components/auth/OTP.mjs +12 -8
  5. package/dist/components/auth/OTP.mjs.map +1 -1
  6. package/dist/components/auth/TurnstileWidget.d.ts +6 -0
  7. package/dist/components/auth/TurnstileWidget.d.ts.map +1 -1
  8. package/dist/components/auth/TurnstileWidget.js +44 -2
  9. package/dist/components/auth/TurnstileWidget.js.map +1 -1
  10. package/dist/components/auth/TurnstileWidget.mjs +73 -2
  11. package/dist/components/auth/TurnstileWidget.mjs.map +1 -1
  12. package/dist/providers/client/Provider.d.ts.map +1 -1
  13. package/dist/providers/client/Provider.js +157 -77
  14. package/dist/providers/client/Provider.js.map +1 -1
  15. package/dist/providers/client/Provider.mjs +1303 -1107
  16. package/dist/providers/client/Provider.mjs.map +1 -1
  17. package/dist/providers/client/Types.d.ts +15 -1
  18. package/dist/providers/client/Types.d.ts.map +1 -1
  19. package/dist/providers/client/Types.js.map +1 -1
  20. package/dist/providers/client/Types.mjs.map +1 -1
  21. package/dist/utils/oauth/config.d.ts +7 -1
  22. package/dist/utils/oauth/config.d.ts.map +1 -1
  23. package/dist/utils/oauth/config.js +11 -1
  24. package/dist/utils/oauth/config.js.map +1 -1
  25. package/dist/utils/oauth/config.mjs +12 -2
  26. package/dist/utils/oauth/config.mjs.map +1 -1
  27. package/dist/utils/oauth/url.d.ts +3 -0
  28. package/dist/utils/oauth/url.d.ts.map +1 -1
  29. package/dist/utils/oauth/url.js +47 -0
  30. package/dist/utils/oauth/url.js.map +1 -1
  31. package/dist/utils/oauth/url.mjs +65 -3
  32. package/dist/utils/oauth/url.mjs.map +1 -1
  33. package/package.json +4 -4
@@ -5,7 +5,7 @@ var jsxRuntime = require('react/jsx-runtime');
5
5
  var sha2 = require('@noble/hashes/sha2');
6
6
  var utils$1 = require('@noble/hashes/utils');
7
7
  var storage = require('../../utils/oauth/storage.js');
8
- require('../../utils/oauth/config.js');
8
+ var config = require('../../utils/oauth/config.js');
9
9
  var url = require('../../utils/oauth/url.js');
10
10
  var completion = require('../../utils/oauth/completion.js');
11
11
  var pkce = require('../../utils/oauth/pkce.js');
@@ -69,7 +69,7 @@ var Turnstile = require('../../components/auth/Turnstile.js');
69
69
  * @returns A React context provider exposing authentication, wallet, and user management methods and state.
70
70
  */
71
71
  const ClientProvider = ({
72
- config,
72
+ config: config$1,
73
73
  children,
74
74
  callbacks
75
75
  }) => {
@@ -88,13 +88,16 @@ const ClientProvider = ({
88
88
  }, []);
89
89
  // if there is no authProxyConfigId or if autoFetchWalletKitConfig is specifically
90
90
  // set to false, we don't need to fetch the config
91
- const shouldFetchWalletKitConfig = !!config.authProxyConfigId && (config.autoFetchWalletKitConfig ?? true);
91
+ const shouldFetchWalletKitConfig = !!config$1.authProxyConfigId && (config$1.autoFetchWalletKitConfig ?? true);
92
92
  // we use this custom hook to only update the state if the value is different
93
93
  // this is so our useEffect that calls `initializeWalletProviderListeners()` only runs when it needs to
94
94
  const [walletProviders, setWalletProviders] = utils.useWalletProviderState();
95
95
  const expiryTimeoutsRef = react.useRef({});
96
96
  const proxyAuthConfigRef = react.useRef(null);
97
97
  const clientParamsRef = react.useRef(null);
98
+ // Stores the developer's custom MFA handler set via setMfaHandler.
99
+ // When unset, the default httpClient MFA behavior is used (no onMfaRequired callback).
100
+ const mfaHandlerRef = react.useRef(undefined);
98
101
  const [allSessions, setAllSessions] = react.useState(undefined);
99
102
  const {
100
103
  isMobile,
@@ -410,115 +413,115 @@ const ClientProvider = ({
410
413
  const buildConfig = (proxyAuthConfig, clientParams) => {
411
414
  // Juggle the local overrides with the values set in the dashboard (proxyAuthConfig).
412
415
  const resolvedMethods = {
413
- emailOtpAuthEnabled: config.ui?.authModal?.methods?.emailOtpAuthEnabled ?? proxyAuthConfig?.enabledProviders.includes("email"),
414
- smsOtpAuthEnabled: config.ui?.authModal?.methods?.smsOtpAuthEnabled ?? proxyAuthConfig?.enabledProviders.includes("sms"),
415
- passkeyAuthEnabled: config.ui?.authModal?.methods?.passkeyAuthEnabled ?? proxyAuthConfig?.enabledProviders.includes("passkey"),
416
- walletAuthEnabled: config.ui?.authModal?.methods?.walletAuthEnabled ?? proxyAuthConfig?.enabledProviders.includes("wallet"),
417
- googleOauthEnabled: config.ui?.authModal?.methods?.googleOauthEnabled ?? proxyAuthConfig?.enabledProviders.includes("google"),
418
- xOauthEnabled: config.ui?.authModal?.methods?.xOauthEnabled ?? proxyAuthConfig?.enabledProviders.includes("x"),
419
- discordOauthEnabled: config.ui?.authModal?.methods?.discordOauthEnabled ?? proxyAuthConfig?.enabledProviders.includes("discord"),
420
- appleOauthEnabled: config.ui?.authModal?.methods?.appleOauthEnabled ?? proxyAuthConfig?.enabledProviders.includes("apple"),
421
- facebookOauthEnabled: config.ui?.authModal?.methods?.facebookOauthEnabled ?? proxyAuthConfig?.enabledProviders.includes("facebook")
416
+ emailOtpAuthEnabled: config$1.ui?.authModal?.methods?.emailOtpAuthEnabled ?? proxyAuthConfig?.enabledProviders.includes("email"),
417
+ smsOtpAuthEnabled: config$1.ui?.authModal?.methods?.smsOtpAuthEnabled ?? proxyAuthConfig?.enabledProviders.includes("sms"),
418
+ passkeyAuthEnabled: config$1.ui?.authModal?.methods?.passkeyAuthEnabled ?? proxyAuthConfig?.enabledProviders.includes("passkey"),
419
+ walletAuthEnabled: config$1.ui?.authModal?.methods?.walletAuthEnabled ?? proxyAuthConfig?.enabledProviders.includes("wallet"),
420
+ googleOauthEnabled: config$1.ui?.authModal?.methods?.googleOauthEnabled ?? proxyAuthConfig?.enabledProviders.includes("google"),
421
+ xOauthEnabled: config$1.ui?.authModal?.methods?.xOauthEnabled ?? proxyAuthConfig?.enabledProviders.includes("x"),
422
+ discordOauthEnabled: config$1.ui?.authModal?.methods?.discordOauthEnabled ?? proxyAuthConfig?.enabledProviders.includes("discord"),
423
+ appleOauthEnabled: config$1.ui?.authModal?.methods?.appleOauthEnabled ?? proxyAuthConfig?.enabledProviders.includes("apple"),
424
+ facebookOauthEnabled: config$1.ui?.authModal?.methods?.facebookOauthEnabled ?? proxyAuthConfig?.enabledProviders.includes("facebook")
422
425
  };
423
426
  const resolvedOauthProviders = {
424
427
  google: {
425
- primaryClientId: config.auth?.oauthConfig?.google?.primaryClientId ?? proxyAuthConfig?.oauthClientIds?.google,
426
- secondaryClientIds: config.auth?.oauthConfig?.google?.secondaryClientIds ?? []
428
+ primaryClientId: config$1.auth?.oauthConfig?.google?.primaryClientId ?? proxyAuthConfig?.oauthClientIds?.google,
429
+ secondaryClientIds: config$1.auth?.oauthConfig?.google?.secondaryClientIds ?? []
427
430
  },
428
431
  apple: {
429
- primaryClientId: config.auth?.oauthConfig?.apple?.primaryClientId ?? proxyAuthConfig?.oauthClientIds?.apple,
430
- secondaryClientIds: config.auth?.oauthConfig?.apple?.secondaryClientIds ?? []
432
+ primaryClientId: config$1.auth?.oauthConfig?.apple?.primaryClientId ?? proxyAuthConfig?.oauthClientIds?.apple,
433
+ secondaryClientIds: config$1.auth?.oauthConfig?.apple?.secondaryClientIds ?? []
431
434
  },
432
435
  facebook: {
433
- primaryClientId: config.auth?.oauthConfig?.facebook?.primaryClientId ?? proxyAuthConfig?.oauthClientIds?.facebook,
434
- secondaryClientIds: config.auth?.oauthConfig?.facebook?.secondaryClientIds ?? []
436
+ primaryClientId: config$1.auth?.oauthConfig?.facebook?.primaryClientId ?? proxyAuthConfig?.oauthClientIds?.facebook,
437
+ secondaryClientIds: config$1.auth?.oauthConfig?.facebook?.secondaryClientIds ?? []
435
438
  },
436
439
  x: {
437
- primaryClientId: config.auth?.oauthConfig?.x?.primaryClientId ?? proxyAuthConfig?.oauthClientIds?.x,
438
- secondaryClientIds: config.auth?.oauthConfig?.x?.secondaryClientIds ?? []
440
+ primaryClientId: config$1.auth?.oauthConfig?.x?.primaryClientId ?? proxyAuthConfig?.oauthClientIds?.x,
441
+ secondaryClientIds: config$1.auth?.oauthConfig?.x?.secondaryClientIds ?? []
439
442
  },
440
443
  discord: {
441
- primaryClientId: config.auth?.oauthConfig?.discord?.primaryClientId ?? proxyAuthConfig?.oauthClientIds?.discord,
442
- secondaryClientIds: config.auth?.oauthConfig?.discord?.secondaryClientIds ?? []
444
+ primaryClientId: config$1.auth?.oauthConfig?.discord?.primaryClientId ?? proxyAuthConfig?.oauthClientIds?.discord,
445
+ secondaryClientIds: config$1.auth?.oauthConfig?.discord?.secondaryClientIds ?? []
443
446
  }
444
447
  };
445
- const redirectUrl = config.auth?.oauthConfig?.oauthRedirectUri ?? proxyAuthConfig?.oauthRedirectUrl;
448
+ const redirectUrl = config$1.auth?.oauthConfig?.oauthRedirectUri ?? proxyAuthConfig?.oauthRedirectUrl;
446
449
  // Set a default ordering for the oAuth methods
447
- const oauthOrder = config.ui?.authModal?.oauthOrder ?? ["google", "apple", "x", "discord", "facebook"].filter(provider => resolvedMethods[`${provider}OauthEnabled`]);
450
+ const oauthOrder = config$1.ui?.authModal?.oauthOrder ?? ["google", "apple", "x", "discord", "facebook"].filter(provider => resolvedMethods[`${provider}OauthEnabled`]);
448
451
  // Set a default ordering for the overall auth methods
449
- const methodOrder = config.ui?.authModal?.methodOrder ?? [oauthOrder.length > 0 ? "socials" : null, resolvedMethods.emailOtpAuthEnabled ? "email" : null, resolvedMethods.smsOtpAuthEnabled ? "sms" : null, resolvedMethods.passkeyAuthEnabled ? "passkey" : null, resolvedMethods.walletAuthEnabled ? "wallet" : null].filter(Boolean);
452
+ const methodOrder = config$1.ui?.authModal?.methodOrder ?? [oauthOrder.length > 0 ? "socials" : null, resolvedMethods.emailOtpAuthEnabled ? "email" : null, resolvedMethods.smsOtpAuthEnabled ? "sms" : null, resolvedMethods.passkeyAuthEnabled ? "passkey" : null, resolvedMethods.walletAuthEnabled ? "wallet" : null].filter(Boolean);
450
453
  // Warn if they are trying to set auth proxy only settings directly
451
454
  if (proxyAuthConfig) {
452
- if (config.auth?.sessionExpirationSeconds) {
455
+ if (config$1.auth?.sessionExpirationSeconds) {
453
456
  console.warn("Turnkey SDK warning. You have set sessionExpirationSeconds directly in the TurnkeyProvider. This setting will be ignored because you are using an auth proxy. Please configure session expiration in the Turnkey dashboard.");
454
457
  }
455
- if (config.auth?.otpAlphanumeric !== undefined) {
458
+ if (config$1.auth?.otpAlphanumeric !== undefined) {
456
459
  console.warn("Turnkey SDK warning. You have set otpAlphanumeric directly in the TurnkeyProvider. This setting will be ignored because you are using an auth proxy. Please configure OTP settings in the Turnkey dashboard.");
457
460
  }
458
- if (config.auth?.otpLength) {
461
+ if (config$1.auth?.otpLength) {
459
462
  console.warn("Turnkey SDK warning. You have set otpLength directly in the TurnkeyProvider. This setting will be ignored because you are using an auth proxy. Please configure OTP settings in the Turnkey dashboard.");
460
463
  }
461
464
  }
462
465
  // These are settings that, if using the auth proxy, must be set in the dashboard. They override any local settings unless they are not using auth proxy or are not fetching the auth proxy config.
463
466
  const authProxyPrioSettings = {
464
- sessionExpirationSeconds: proxyAuthConfig?.sessionExpirationSeconds ?? config.auth?.sessionExpirationSeconds,
465
- otpAlphanumeric: proxyAuthConfig?.otpAlphanumeric ?? config.auth?.otpAlphanumeric ?? true,
466
- otpLength: proxyAuthConfig?.otpLength ?? config.auth?.otpLength ?? "6"
467
+ sessionExpirationSeconds: proxyAuthConfig?.sessionExpirationSeconds ?? config$1.auth?.sessionExpirationSeconds,
468
+ otpAlphanumeric: proxyAuthConfig?.otpAlphanumeric ?? config$1.auth?.otpAlphanumeric ?? true,
469
+ otpLength: proxyAuthConfig?.otpLength ?? config$1.auth?.otpLength ?? "6"
467
470
  };
468
- const scopePasskeyToUser = config.auth?.scopePasskeyToUser ?? true;
471
+ const scopePasskeyToUser = config$1.auth?.scopePasskeyToUser ?? true;
469
472
  return {
470
- ...config,
473
+ ...config$1,
471
474
  scopePasskeyToUser,
472
475
  // Overrides:
473
476
  auth: {
474
- ...config.auth,
477
+ ...config$1.auth,
475
478
  ...authProxyPrioSettings,
476
479
  oauthConfig: {
477
- ...config.auth?.oauthConfig,
480
+ ...config$1.auth?.oauthConfig,
478
481
  ...resolvedOauthProviders,
479
482
  oauthRedirectUri: redirectUrl,
480
483
  // on mobile we default to true since many mobile browsers
481
484
  // (e.g. Safari) block popups
482
- openOauthInPage: isMobile ? true : config.auth?.oauthConfig?.openOauthInPage
485
+ openOauthInPage: isMobile ? true : config$1.auth?.oauthConfig?.openOauthInPage
483
486
  },
484
- autoRefreshSession: config.auth?.autoRefreshSession ?? true,
487
+ autoRefreshSession: config$1.auth?.autoRefreshSession ?? true,
485
488
  scopePasskeyToUser
486
489
  },
487
490
  ui: {
488
- ...config.ui,
491
+ ...config$1.ui,
489
492
  authModal: {
490
- ...config.ui?.authModal,
493
+ ...config$1.ui?.authModal,
491
494
  methods: resolvedMethods,
492
495
  methodOrder,
493
496
  oauthOrder
494
497
  }
495
498
  },
496
- autoRefreshManagedState: config.autoRefreshManagedState ?? true,
499
+ autoRefreshManagedState: config$1.autoRefreshManagedState ?? true,
497
500
  walletConfig: {
498
- ...config.walletConfig,
501
+ ...config$1.walletConfig,
499
502
  features: {
500
- ...config.walletConfig?.features,
503
+ ...config$1.walletConfig?.features,
501
504
  auth:
502
505
  // If walletAuthEnabled is not set, default to true. Wallet auth can be enabled/disabled in the dashboard or by explicitly changing the walletAuthEnabled / walletConfig auth feature.
503
- resolvedMethods.walletAuthEnabled ?? config.walletConfig?.features?.auth ?? true,
504
- connecting: config.walletConfig?.features?.connecting ?? true // Default connecting to true if not set. We don't care about auth settings here.
506
+ resolvedMethods.walletAuthEnabled ?? config$1.walletConfig?.features?.auth ?? true,
507
+ connecting: config$1.walletConfig?.features?.connecting ?? true // Default connecting to true if not set. We don't care about auth settings here.
505
508
  },
506
509
  chains: {
507
- ...config.walletConfig?.chains,
510
+ ...config$1.walletConfig?.chains,
508
511
  ethereum: {
509
- ...config.walletConfig?.chains?.ethereum,
512
+ ...config$1.walletConfig?.chains?.ethereum,
510
513
  // keep user's value if provided; default only when undefined
511
- native: config.walletConfig?.chains?.ethereum?.native ?? true
514
+ native: config$1.walletConfig?.chains?.ethereum?.native ?? true
512
515
  },
513
516
  solana: {
514
- ...config.walletConfig?.chains?.solana,
517
+ ...config$1.walletConfig?.chains?.solana,
515
518
  // keep user's value if provided; default only when undefined
516
- native: config.walletConfig?.chains?.solana?.native ?? true
519
+ native: config$1.walletConfig?.chains?.solana?.native ?? true
517
520
  }
518
521
  }
519
522
  },
520
- importIframeUrl: config.importIframeUrl ?? "https://import.turnkey.com",
521
- exportIframeUrl: config.exportIframeUrl ?? "https://export.turnkey.com",
523
+ importIframeUrl: config$1.importIframeUrl ?? "https://import.turnkey.com",
524
+ exportIframeUrl: config$1.exportIframeUrl ?? "https://export.turnkey.com",
522
525
  turnstileSiteKey: clientParams?.turnstileSiteKey
523
526
  };
524
527
  };
@@ -883,6 +886,12 @@ const ClientProvider = ({
883
886
  }
884
887
  return client.overridePasskeyStamper(params);
885
888
  }, [client]);
889
+ const overrideAttestedStamper = react.useCallback(params => {
890
+ if (!client) {
891
+ throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
892
+ }
893
+ return client.overrideAttestedStamper(params);
894
+ }, [client]);
886
895
  const getActiveSessionKey = react.useCallback(async () => {
887
896
  if (!client) throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
888
897
  return utils.withTurnkeyErrorHandling(() => client.getActiveSessionKey(), undefined, callbacks, "Failed to get active session key");
@@ -1367,13 +1376,23 @@ const ClientProvider = ({
1367
1376
  if (!client) {
1368
1377
  throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
1369
1378
  }
1370
- return utils.withTurnkeyErrorHandling(() => client.verifyOtp(params), undefined, callbacks, "Failed to verify OTP");
1379
+ const res = await utils.withTurnkeyErrorHandling(() => client.verifyOtp(params), undefined, callbacks, "Failed to verify OTP");
1380
+ // Automatically override the attested stamper with the verification token
1381
+ await client.overrideAttestedStamper({
1382
+ verificationToken: res.verificationToken,
1383
+ publicKey: res.publicKey
1384
+ });
1385
+ return res;
1371
1386
  }, [client, callbacks]);
1372
1387
  const loginWithOtp = react.useCallback(async params => {
1373
1388
  if (!client) {
1374
1389
  throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
1375
1390
  }
1376
- const res = await utils.withTurnkeyErrorHandling(() => client.loginWithOtp(params), undefined, callbacks, "Failed to login with OTP");
1391
+ const expirationSeconds = params?.expirationSeconds ?? masterConfig?.auth?.sessionExpirationSeconds ?? core.DEFAULT_SESSION_EXPIRATION_IN_SECONDS;
1392
+ const res = await utils.withTurnkeyErrorHandling(() => client.loginWithOtp({
1393
+ ...params,
1394
+ expirationSeconds
1395
+ }), undefined, callbacks, "Failed to login with OTP");
1377
1396
  if (res) {
1378
1397
  await handlePostAuth({
1379
1398
  method: base.AuthMethod.Otp,
@@ -1383,7 +1402,7 @@ const ClientProvider = ({
1383
1402
  });
1384
1403
  }
1385
1404
  return res;
1386
- }, [client, callbacks, handlePostAuth]);
1405
+ }, [client, callbacks, masterConfig, handlePostAuth]);
1387
1406
  const signUpWithOtp = react.useCallback(async params => {
1388
1407
  if (!client) {
1389
1408
  throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
@@ -1454,7 +1473,11 @@ const ClientProvider = ({
1454
1473
  if (!client) {
1455
1474
  throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
1456
1475
  }
1457
- const res = await utils.withTurnkeyErrorHandling(() => client.loginWithOauth(params), undefined, callbacks, "Failed to login with OAuth");
1476
+ const expirationSeconds = params?.expirationSeconds ?? masterConfig?.auth?.sessionExpirationSeconds ?? core.DEFAULT_SESSION_EXPIRATION_IN_SECONDS;
1477
+ const res = await utils.withTurnkeyErrorHandling(() => client.loginWithOauth({
1478
+ ...params,
1479
+ expirationSeconds
1480
+ }), undefined, callbacks, "Failed to login with OAuth");
1458
1481
  if (res) {
1459
1482
  await handlePostAuth({
1460
1483
  method: base.AuthMethod.Oauth,
@@ -1464,7 +1487,7 @@ const ClientProvider = ({
1464
1487
  });
1465
1488
  }
1466
1489
  return res;
1467
- }, [client, callbacks, handlePostAuth]);
1490
+ }, [client, callbacks, masterConfig, handlePostAuth]);
1468
1491
  const signUpWithOauth = react.useCallback(async params => {
1469
1492
  if (!client) {
1470
1493
  throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
@@ -1840,10 +1863,9 @@ const ClientProvider = ({
1840
1863
  }, [client, callbacks, logout, clearSessionTimeouts, masterConfig?.passkeyConfig]);
1841
1864
  const setActiveSession = react.useCallback(async params => {
1842
1865
  if (!client) throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
1843
- const session = await utils.withTurnkeyErrorHandling(() => client.getSession({
1866
+ const s = await getSession({
1844
1867
  sessionKey: params.sessionKey
1845
- }), () => logout(), callbacks, "Failed to get session");
1846
- const s = await getSession();
1868
+ });
1847
1869
  if (!s) {
1848
1870
  throw new sdkTypes.TurnkeyError("Session not found.", sdkTypes.TurnkeyErrorCodes.NOT_FOUND);
1849
1871
  }
@@ -1884,6 +1906,17 @@ const ClientProvider = ({
1884
1906
  if (!client) throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
1885
1907
  return utils.withTurnkeyErrorHandling(() => client.verifyAppProofs(params), () => logout(), callbacks, "Failed to verify app proofs");
1886
1908
  }, [client, callbacks, logout]);
1909
+ const setMfaHandler = react.useCallback(handler => {
1910
+ mfaHandlerRef.current = handler;
1911
+ // Apply immediately if the client is ready.
1912
+ // When a custom handler is set, route the httpClient's MFA callback to it.
1913
+ // When cleared, restore the default httpClient behavior (no onMfaRequired callback).
1914
+ if (client) {
1915
+ client.httpClient.config.onMfaRequired = handler ? async ctx => {
1916
+ await handler(ctx);
1917
+ } : undefined;
1918
+ }
1919
+ }, [client]);
1887
1920
  const handleDiscordOauth = react.useCallback(async params => {
1888
1921
  const {
1889
1922
  primaryClientId = masterConfig?.auth?.oauthConfig?.discord?.primaryClientId,
@@ -1945,7 +1978,7 @@ const ClientProvider = ({
1945
1978
  }
1946
1979
  authWindow.location.href = authUrl;
1947
1980
  return new Promise((resolve, reject) => {
1948
- const interval = setInterval(() => {
1981
+ const interval = setInterval(async () => {
1949
1982
  try {
1950
1983
  if (authWindow.closed) {
1951
1984
  clearInterval(interval);
@@ -1953,7 +1986,7 @@ const ClientProvider = ({
1953
1986
  return;
1954
1987
  }
1955
1988
  const url$1 = authWindow.location.href || "";
1956
- if (url$1.startsWith(window.location.origin)) {
1989
+ if (url.isExpectedOAuthRedirectUrl(url$1, redirectUri, config.OAUTH_PROVIDER_CONFIGS[provider].expectedResponseMode)) {
1957
1990
  const result = url.parseOAuthResponse(url$1, provider);
1958
1991
  if (result) {
1959
1992
  authWindow.close();
@@ -1987,7 +2020,15 @@ const ClientProvider = ({
1987
2020
  clientId,
1988
2021
  nonce
1989
2022
  });
1990
- return resp?.oidcToken ?? "";
2023
+ const oidcToken = resp?.oidcToken ?? "";
2024
+ // Set the attested stamper with the oidcToken
2025
+ if (oidcToken) {
2026
+ await client?.overrideAttestedStamper({
2027
+ oidcToken,
2028
+ publicKey
2029
+ });
2030
+ }
2031
+ return oidcToken;
1991
2032
  }
1992
2033
  }).then(() => resolve()).catch(reject);
1993
2034
  }
@@ -2062,7 +2103,7 @@ const ClientProvider = ({
2062
2103
  }
2063
2104
  authWindow.location.href = authUrl;
2064
2105
  return new Promise((resolve, reject) => {
2065
- const interval = setInterval(() => {
2106
+ const interval = setInterval(async () => {
2066
2107
  try {
2067
2108
  if (authWindow.closed) {
2068
2109
  clearInterval(interval);
@@ -2070,7 +2111,7 @@ const ClientProvider = ({
2070
2111
  return;
2071
2112
  }
2072
2113
  const url$1 = authWindow.location.href || "";
2073
- if (url$1.startsWith(window.location.origin)) {
2114
+ if (url.isExpectedOAuthRedirectUrl(url$1, redirectUri, config.OAUTH_PROVIDER_CONFIGS[provider].expectedResponseMode)) {
2074
2115
  const result = url.parseOAuthResponse(url$1, provider);
2075
2116
  if (result) {
2076
2117
  authWindow.close();
@@ -2104,7 +2145,15 @@ const ClientProvider = ({
2104
2145
  clientId,
2105
2146
  nonce
2106
2147
  });
2107
- return resp?.oidcToken ?? "";
2148
+ const oidcToken = resp?.oidcToken ?? "";
2149
+ // Set the attested stamper with the oidcToken
2150
+ if (oidcToken) {
2151
+ await client?.overrideAttestedStamper({
2152
+ oidcToken,
2153
+ publicKey
2154
+ });
2155
+ }
2156
+ return oidcToken;
2108
2157
  }
2109
2158
  }).then(() => resolve()).catch(reject);
2110
2159
  }
@@ -2173,7 +2222,7 @@ const ClientProvider = ({
2173
2222
  }
2174
2223
  authWindow.location.href = authUrl;
2175
2224
  return new Promise((resolve, reject) => {
2176
- const interval = setInterval(() => {
2225
+ const interval = setInterval(async () => {
2177
2226
  try {
2178
2227
  if (authWindow.closed) {
2179
2228
  clearInterval(interval);
@@ -2181,11 +2230,18 @@ const ClientProvider = ({
2181
2230
  return;
2182
2231
  }
2183
2232
  const url$1 = authWindow.location.href || "";
2184
- if (url$1.startsWith(window.location.origin)) {
2233
+ if (url.isExpectedOAuthRedirectUrl(url$1, redirectUri, config.OAUTH_PROVIDER_CONFIGS[provider].expectedResponseMode)) {
2185
2234
  const result = url.parseOAuthResponse(url$1, provider);
2186
2235
  if (result) {
2187
2236
  authWindow.close();
2188
2237
  clearInterval(interval);
2238
+ // Set the attested stamper with the oidcToken
2239
+ if (result.idToken) {
2240
+ await client?.overrideAttestedStamper({
2241
+ oidcToken: result.idToken,
2242
+ publicKey
2243
+ });
2244
+ }
2189
2245
  completion.completeOAuthPopup({
2190
2246
  provider,
2191
2247
  publicKey,
@@ -2273,7 +2329,7 @@ const ClientProvider = ({
2273
2329
  }
2274
2330
  authWindow.location.href = authUrl;
2275
2331
  return new Promise((resolve, reject) => {
2276
- const interval = setInterval(() => {
2332
+ const interval = setInterval(async () => {
2277
2333
  try {
2278
2334
  if (authWindow.closed) {
2279
2335
  clearInterval(interval);
@@ -2281,11 +2337,18 @@ const ClientProvider = ({
2281
2337
  return;
2282
2338
  }
2283
2339
  const url$1 = authWindow.location.href || "";
2284
- if (url$1.startsWith(window.location.origin)) {
2340
+ if (url.isExpectedOAuthRedirectUrl(url$1, redirectUri, config.OAUTH_PROVIDER_CONFIGS[provider].expectedResponseMode)) {
2285
2341
  const result = url.parseOAuthResponse(url$1, provider);
2286
2342
  if (result) {
2287
2343
  authWindow.close();
2288
2344
  clearInterval(interval);
2345
+ // Set the attested stamper with the oidcToken
2346
+ if (result.idToken) {
2347
+ await client?.overrideAttestedStamper({
2348
+ oidcToken: result.idToken,
2349
+ publicKey
2350
+ });
2351
+ }
2289
2352
  completion.completeOAuthPopup({
2290
2353
  provider,
2291
2354
  publicKey,
@@ -2379,7 +2442,7 @@ const ClientProvider = ({
2379
2442
  }
2380
2443
  authWindow.location.href = authUrl;
2381
2444
  return new Promise((resolve, reject) => {
2382
- const interval = setInterval(() => {
2445
+ const interval = setInterval(async () => {
2383
2446
  try {
2384
2447
  if (authWindow.closed) {
2385
2448
  clearInterval(interval);
@@ -2387,7 +2450,7 @@ const ClientProvider = ({
2387
2450
  return;
2388
2451
  }
2389
2452
  const url$1 = authWindow.location.href || "";
2390
- if (url$1.startsWith(window.location.origin)) {
2453
+ if (url.isExpectedOAuthRedirectUrl(url$1, redirectUri, config.OAUTH_PROVIDER_CONFIGS[provider].expectedResponseMode)) {
2391
2454
  const result = url.parseOAuthResponse(url$1, provider);
2392
2455
  if (result) {
2393
2456
  authWindow.close();
@@ -2414,7 +2477,15 @@ const ClientProvider = ({
2414
2477
  onOauthSuccess: params?.onOauthSuccess,
2415
2478
  exchangeCodeForToken: async codeVerifier => {
2416
2479
  const tokenData = await pkce.exchangeFacebookCodeForToken(clientId, redirectUri, result.authCode, codeVerifier);
2417
- return tokenData.id_token;
2480
+ const oidcToken = tokenData.id_token;
2481
+ // Set the attested stamper with the oidcToken
2482
+ if (oidcToken) {
2483
+ await client?.overrideAttestedStamper({
2484
+ oidcToken,
2485
+ publicKey
2486
+ });
2487
+ }
2488
+ return oidcToken;
2418
2489
  }
2419
2490
  }).then(() => resolve()).catch(reject);
2420
2491
  }
@@ -3975,12 +4046,12 @@ const ClientProvider = ({
3975
4046
  let clientParams;
3976
4047
  const promises = [];
3977
4048
  if (shouldFetchWalletKitConfig) {
3978
- promises.push(core.getAuthProxyConfig(config.authProxyConfigId, config.authProxyUrl).then(result => {
4049
+ promises.push(core.getAuthProxyConfig(config$1.authProxyConfigId, config$1.authProxyUrl).then(result => {
3979
4050
  proxyAuthConfig = result;
3980
4051
  }));
3981
4052
  }
3982
- if (config.authProxyConfigId) {
3983
- promises.push(core.getClientParams(config.authProxyConfigId, config.authProxyUrl).then(result => {
4053
+ if (config$1.authProxyConfigId) {
4054
+ promises.push(core.getClientParams(config$1.authProxyConfigId, config$1.authProxyUrl).then(result => {
3984
4055
  clientParams = result;
3985
4056
  }));
3986
4057
  }
@@ -4010,7 +4081,7 @@ const ClientProvider = ({
4010
4081
  // If shouldFetchWalletKitConfig is false, we'll never have a proxyAuthConfig to build the master config with, so this useEffect should always run.
4011
4082
  if (!proxyAuthConfigRef.current && shouldFetchWalletKitConfig) return;
4012
4083
  setMasterConfig(buildConfig(proxyAuthConfigRef.current ?? undefined, clientParamsRef.current ?? undefined));
4013
- }, [config, proxyAuthConfigRef.current]);
4084
+ }, [config$1, proxyAuthConfigRef.current]);
4014
4085
  /**
4015
4086
  * @internal
4016
4087
  * We create `debouncedRefreshWallets()` so that multiple rapid wallet events
@@ -4059,8 +4130,8 @@ const ClientProvider = ({
4059
4130
  }
4060
4131
  }, [session]);
4061
4132
  react.useEffect(() => {
4062
- // This will handle any redirect based oAuth. It then initializes the session. This is the last step before client is considered "ready"
4063
4133
  if (!client || !masterConfig) return;
4134
+ // This will handle any redirect based oAuth. It then initializes the session. This is the last step before client is considered "ready"
4064
4135
  completeRedirectOauth().finally(() => {
4065
4136
  clearSessionTimeouts();
4066
4137
  // if auth or wallet connecting features are enabled, we want to fetch
@@ -4073,6 +4144,13 @@ const ClientProvider = ({
4073
4144
  setClientState(base.ClientState.Ready);
4074
4145
  });
4075
4146
  });
4147
+ // Only set the onMfaRequired handler if we have a mfaHandler set.
4148
+ const mfaHandler = mfaHandlerRef.current;
4149
+ if (mfaHandler) {
4150
+ client.httpClient.config.onMfaRequired = async ctx => {
4151
+ await mfaHandler(ctx);
4152
+ };
4153
+ }
4076
4154
  return () => {
4077
4155
  clearSessionTimeouts();
4078
4156
  };
@@ -4091,6 +4169,7 @@ const ClientProvider = ({
4091
4169
  createHttpClient,
4092
4170
  overrideApiKeyStamper,
4093
4171
  overridePasskeyStamper,
4172
+ overrideAttestedStamper,
4094
4173
  createPasskey,
4095
4174
  logout,
4096
4175
  loginWithPasskey,
@@ -4186,6 +4265,7 @@ const ClientProvider = ({
4186
4265
  handleOnRamp,
4187
4266
  handleSendTransaction,
4188
4267
  handleSendErc20Transfer,
4268
+ setMfaHandler,
4189
4269
  getTurnstileToken,
4190
4270
  setTurnstileToken
4191
4271
  },