@turnkey/react-wallet-kit 1.11.1 → 2.0.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 (65) hide show
  1. package/dist/components/auth/OTP.d.ts +1 -0
  2. package/dist/components/auth/OTP.d.ts.map +1 -1
  3. package/dist/components/auth/OTP.js +8 -2
  4. package/dist/components/auth/OTP.js.map +1 -1
  5. package/dist/components/auth/OTP.mjs +21 -13
  6. package/dist/components/auth/OTP.mjs.map +1 -1
  7. package/dist/components/auth/index.d.ts.map +1 -1
  8. package/dist/components/auth/index.js +11 -3
  9. package/dist/components/auth/index.js.map +1 -1
  10. package/dist/components/auth/index.mjs +12 -5
  11. package/dist/components/auth/index.mjs.map +1 -1
  12. package/dist/components/user/UpdateEmail.js +6 -3
  13. package/dist/components/user/UpdateEmail.js.map +1 -1
  14. package/dist/components/user/UpdateEmail.mjs +6 -4
  15. package/dist/components/user/UpdateEmail.mjs.map +1 -1
  16. package/dist/components/user/UpdatePhoneNumber.js +6 -3
  17. package/dist/components/user/UpdatePhoneNumber.js.map +1 -1
  18. package/dist/components/user/UpdatePhoneNumber.mjs +6 -4
  19. package/dist/components/user/UpdatePhoneNumber.mjs.map +1 -1
  20. package/dist/index.d.ts +1 -3
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +8 -4
  23. package/dist/index.js.map +1 -1
  24. package/dist/index.mjs +1 -1
  25. package/dist/providers/TurnkeyProvider.d.ts.map +1 -1
  26. package/dist/providers/TurnkeyProvider.js +2 -1
  27. package/dist/providers/TurnkeyProvider.js.map +1 -1
  28. package/dist/providers/TurnkeyProvider.mjs +4 -3
  29. package/dist/providers/TurnkeyProvider.mjs.map +1 -1
  30. package/dist/providers/client/Provider.d.ts.map +1 -1
  31. package/dist/providers/client/Provider.js +319 -135
  32. package/dist/providers/client/Provider.js.map +1 -1
  33. package/dist/providers/client/Provider.mjs +1994 -1748
  34. package/dist/providers/client/Provider.mjs.map +1 -1
  35. package/dist/providers/client/Types.d.ts +14 -7
  36. package/dist/providers/client/Types.d.ts.map +1 -1
  37. package/dist/providers/client/Types.js.map +1 -1
  38. package/dist/providers/client/Types.mjs.map +1 -1
  39. package/dist/providers/theme/Overrides.d.ts +1 -0
  40. package/dist/providers/theme/Overrides.d.ts.map +1 -1
  41. package/dist/providers/theme/Overrides.js +3 -1
  42. package/dist/providers/theme/Overrides.js.map +1 -1
  43. package/dist/providers/theme/Overrides.mjs +3 -1
  44. package/dist/providers/theme/Overrides.mjs.map +1 -1
  45. package/dist/styles.css +1 -1
  46. package/dist/typedoc-entry/index.d.ts +1 -1
  47. package/dist/typedoc-entry/index.d.ts.map +1 -1
  48. package/dist/types/base.d.ts +40 -28
  49. package/dist/types/base.d.ts.map +1 -1
  50. package/dist/types/base.js.map +1 -1
  51. package/dist/types/base.mjs.map +1 -1
  52. package/dist/types/method-types.d.ts +12 -5
  53. package/dist/types/method-types.d.ts.map +1 -1
  54. package/dist/utils/oauth/storage.d.ts +11 -0
  55. package/dist/utils/oauth/storage.d.ts.map +1 -1
  56. package/dist/utils/oauth/storage.js +29 -0
  57. package/dist/utils/oauth/storage.js.map +1 -1
  58. package/dist/utils/oauth/storage.mjs +27 -1
  59. package/dist/utils/oauth/storage.mjs.map +1 -1
  60. package/dist/utils/oauth/url.d.ts.map +1 -1
  61. package/dist/utils/oauth/url.js +10 -1
  62. package/dist/utils/oauth/url.js.map +1 -1
  63. package/dist/utils/oauth/url.mjs +11 -2
  64. package/dist/utils/oauth/url.mjs.map +1 -1
  65. package/package.json +4 -4
@@ -191,10 +191,10 @@ const ClientProvider = ({
191
191
  const metadata = isAddProvider ? storage.getOAuthAddProviderMetadata() : null;
192
192
  /**
193
193
  * Helper to complete PKCE redirect flow with optional modal wrapper.
194
- * Uses completePKCEFlow from oauth utils for the core logic.
194
+ * Uses handlePKCEFlow from oauth utils for the core logic.
195
195
  * We put this in a separate function to avoid duplicating for each provider.
196
196
  */
197
- const completePKCERedirect = async (providerName, exchangeCodeFn) => {
197
+ const completePKCERedirect = async (providerName, exchangeCodeFn, secondaryClientIds) => {
198
198
  const action = async () => {
199
199
  try {
200
200
  await completion.completePKCEFlow({
@@ -202,13 +202,29 @@ const ClientProvider = ({
202
202
  providerName,
203
203
  sessionKey: sessionKey ?? undefined,
204
204
  callbacks,
205
- completeOauth,
205
+ completeOauth: completionParams => {
206
+ const existingCreateSubOrgParams = masterConfig?.auth?.createSuborgParams?.oauth;
207
+ const secondaryProviders = core.buildSecondaryOauthProviders(completionParams.oidcToken, completionParams.providerName ?? providerName, secondaryClientIds);
208
+ return completeOauth({
209
+ ...completionParams,
210
+ ...(secondaryProviders.length > 0 && {
211
+ createSubOrgParams: {
212
+ ...existingCreateSubOrgParams,
213
+ oauthProviders: [...(existingCreateSubOrgParams?.oauthProviders ?? []), ...secondaryProviders]
214
+ }
215
+ })
216
+ });
217
+ },
206
218
  onAddProvider:
207
219
  // Only set onAddProvider if we are adding a provider and have metadata
208
220
  isAddProvider && metadata ? async oidcToken => {
221
+ const oidcClaims = core.buildSecondaryOidcClaims(oidcToken, secondaryClientIds);
209
222
  await addOauthProvider({
210
223
  providerName: provider,
211
224
  oidcToken,
225
+ ...(oidcClaims.length > 0 && {
226
+ oidcClaims
227
+ }),
212
228
  organizationId: metadata.organizationId,
213
229
  userId: metadata.userId,
214
230
  ...(metadata.stampWith && {
@@ -238,7 +254,8 @@ const ClientProvider = ({
238
254
  };
239
255
  // FACEBOOK
240
256
  if (provider === sdkTypes.OAuthProviders.FACEBOOK) {
241
- const clientId = masterConfig?.auth?.oauthConfig?.facebookClientId;
257
+ const clientId = masterConfig?.auth?.oauthConfig?.facebook?.primaryClientId;
258
+ const secondaryClientIds = masterConfig?.auth?.oauthConfig?.facebook?.secondaryClientIds ?? [];
242
259
  const redirectURI = masterConfig?.auth?.oauthConfig?.oauthRedirectUri;
243
260
  const hasVerifier = storage.hasPKCEVerifier(sdkTypes.OAuthProviders.FACEBOOK);
244
261
  if (clientId && redirectURI && hasVerifier) {
@@ -249,13 +266,14 @@ const ClientProvider = ({
249
266
  throw new sdkTypes.TurnkeyError("Missing OIDC token", sdkTypes.TurnkeyErrorCodes.OAUTH_LOGIN_ERROR);
250
267
  }
251
268
  return oidcToken;
252
- });
269
+ }, secondaryClientIds);
253
270
  }
254
271
  return;
255
272
  }
256
273
  // DISCORD
257
274
  if (provider === sdkTypes.OAuthProviders.DISCORD) {
258
- const clientId = masterConfig?.auth?.oauthConfig?.discordClientId;
275
+ const clientId = masterConfig?.auth?.oauthConfig?.discord?.primaryClientId;
276
+ const secondaryClientIds = masterConfig?.auth?.oauthConfig?.discord?.secondaryClientIds ?? [];
259
277
  const redirectURI = masterConfig?.auth?.oauthConfig?.oauthRedirectUri;
260
278
  const hasVerifier = storage.hasPKCEVerifier(sdkTypes.OAuthProviders.DISCORD);
261
279
  if (clientId && redirectURI && hasVerifier && nonce) {
@@ -273,13 +291,14 @@ const ClientProvider = ({
273
291
  throw new sdkTypes.TurnkeyError("Missing OIDC token", sdkTypes.TurnkeyErrorCodes.OAUTH_LOGIN_ERROR);
274
292
  }
275
293
  return oidcToken;
276
- });
294
+ }, secondaryClientIds);
277
295
  }
278
296
  return;
279
297
  }
280
298
  // X (Twitter)
281
299
  if (provider === sdkTypes.OAuthProviders.X) {
282
- const clientId = masterConfig?.auth?.oauthConfig?.xClientId;
300
+ const clientId = masterConfig?.auth?.oauthConfig?.x?.primaryClientId;
301
+ const secondaryClientIds = masterConfig?.auth?.oauthConfig?.x?.secondaryClientIds ?? [];
283
302
  const redirectURI = masterConfig?.auth?.oauthConfig?.oauthRedirectUri;
284
303
  const hasVerifier = storage.hasPKCEVerifier(sdkTypes.OAuthProviders.X);
285
304
  if (clientId && redirectURI && hasVerifier && nonce) {
@@ -297,7 +316,7 @@ const ClientProvider = ({
297
316
  throw new sdkTypes.TurnkeyError("Missing OIDC token", sdkTypes.TurnkeyErrorCodes.OAUTH_LOGIN_ERROR);
298
317
  }
299
318
  return oidcToken;
300
- });
319
+ }, secondaryClientIds);
301
320
  }
302
321
  return;
303
322
  }
@@ -321,6 +340,8 @@ const ClientProvider = ({
321
340
  const isAddProvider = oauthIntent === storage.OAUTH_INTENT_ADD_PROVIDER;
322
341
  const metadata = isAddProvider ? storage.getOAuthAddProviderMetadata() : null;
323
342
  const resolvedProvider = provider || sdkTypes.OAuthProviders.GOOGLE;
343
+ // Grab Google/Apple secondary client IDs from config for use in completion
344
+ const secondaryClientIds = (resolvedProvider === sdkTypes.OAuthProviders.GOOGLE ? masterConfig?.auth?.oauthConfig?.google?.secondaryClientIds : resolvedProvider === sdkTypes.OAuthProviders.APPLE ? masterConfig?.auth?.oauthConfig?.apple?.secondaryClientIds : undefined) ?? [];
324
345
  // Use completeOAuthFlow from utils for the core completion logic
325
346
  const action = async () => {
326
347
  await completion.completeOAuthFlow({
@@ -329,11 +350,27 @@ const ClientProvider = ({
329
350
  oidcToken: idToken,
330
351
  sessionKey: sessionKey ?? undefined,
331
352
  callbacks,
332
- completeOauth,
353
+ completeOauth: completionParams => {
354
+ const existingCreateSubOrgParams = masterConfig?.auth?.createSuborgParams?.oauth;
355
+ const secondaryProviders = core.buildSecondaryOauthProviders(completionParams.oidcToken, completionParams.providerName ?? resolvedProvider, secondaryClientIds);
356
+ return completeOauth({
357
+ ...completionParams,
358
+ ...(secondaryProviders.length > 0 && {
359
+ createSubOrgParams: {
360
+ ...existingCreateSubOrgParams,
361
+ oauthProviders: [...(existingCreateSubOrgParams?.oauthProviders ?? []), ...secondaryProviders]
362
+ }
363
+ })
364
+ });
365
+ },
333
366
  onAddProvider: isAddProvider && metadata ? async oidcToken => {
367
+ const oidcClaims = core.buildSecondaryOidcClaims(oidcToken, secondaryClientIds);
334
368
  await addOauthProvider({
335
369
  providerName: resolvedProvider,
336
370
  oidcToken,
371
+ ...(oidcClaims.length > 0 && {
372
+ oidcClaims
373
+ }),
337
374
  organizationId: metadata.organizationId,
338
375
  userId: metadata.userId,
339
376
  ...(metadata.stampWith && {
@@ -360,28 +397,43 @@ const ClientProvider = ({
360
397
  const buildConfig = proxyAuthConfig => {
361
398
  // Juggle the local overrides with the values set in the dashboard (proxyAuthConfig).
362
399
  const resolvedMethods = {
363
- emailOtpAuthEnabled: config.auth?.methods?.emailOtpAuthEnabled ?? proxyAuthConfig?.enabledProviders.includes("email"),
364
- smsOtpAuthEnabled: config.auth?.methods?.smsOtpAuthEnabled ?? proxyAuthConfig?.enabledProviders.includes("sms"),
365
- passkeyAuthEnabled: config.auth?.methods?.passkeyAuthEnabled ?? proxyAuthConfig?.enabledProviders.includes("passkey"),
366
- walletAuthEnabled: config.auth?.methods?.walletAuthEnabled ?? proxyAuthConfig?.enabledProviders.includes("wallet"),
367
- googleOauthEnabled: config.auth?.methods?.googleOauthEnabled ?? proxyAuthConfig?.enabledProviders.includes("google"),
368
- xOauthEnabled: config.auth?.methods?.xOauthEnabled ?? proxyAuthConfig?.enabledProviders.includes("x"),
369
- discordOauthEnabled: config.auth?.methods?.discordOauthEnabled ?? proxyAuthConfig?.enabledProviders.includes("discord"),
370
- appleOauthEnabled: config.auth?.methods?.appleOauthEnabled ?? proxyAuthConfig?.enabledProviders.includes("apple"),
371
- facebookOauthEnabled: config.auth?.methods?.facebookOauthEnabled ?? proxyAuthConfig?.enabledProviders.includes("facebook")
400
+ emailOtpAuthEnabled: config.ui?.authModal?.methods?.emailOtpAuthEnabled ?? proxyAuthConfig?.enabledProviders.includes("email"),
401
+ smsOtpAuthEnabled: config.ui?.authModal?.methods?.smsOtpAuthEnabled ?? proxyAuthConfig?.enabledProviders.includes("sms"),
402
+ passkeyAuthEnabled: config.ui?.authModal?.methods?.passkeyAuthEnabled ?? proxyAuthConfig?.enabledProviders.includes("passkey"),
403
+ walletAuthEnabled: config.ui?.authModal?.methods?.walletAuthEnabled ?? proxyAuthConfig?.enabledProviders.includes("wallet"),
404
+ googleOauthEnabled: config.ui?.authModal?.methods?.googleOauthEnabled ?? proxyAuthConfig?.enabledProviders.includes("google"),
405
+ xOauthEnabled: config.ui?.authModal?.methods?.xOauthEnabled ?? proxyAuthConfig?.enabledProviders.includes("x"),
406
+ discordOauthEnabled: config.ui?.authModal?.methods?.discordOauthEnabled ?? proxyAuthConfig?.enabledProviders.includes("discord"),
407
+ appleOauthEnabled: config.ui?.authModal?.methods?.appleOauthEnabled ?? proxyAuthConfig?.enabledProviders.includes("apple"),
408
+ facebookOauthEnabled: config.ui?.authModal?.methods?.facebookOauthEnabled ?? proxyAuthConfig?.enabledProviders.includes("facebook")
372
409
  };
373
- const resolvedClientIds = {
374
- googleClientId: config.auth?.oauthConfig?.googleClientId ?? proxyAuthConfig?.oauthClientIds?.google,
375
- appleClientId: config.auth?.oauthConfig?.appleClientId ?? proxyAuthConfig?.oauthClientIds?.apple,
376
- facebookClientId: config.auth?.oauthConfig?.facebookClientId ?? proxyAuthConfig?.oauthClientIds?.facebook,
377
- xClientId: config.auth?.oauthConfig?.xClientId ?? proxyAuthConfig?.oauthClientIds?.x,
378
- discordClientId: config.auth?.oauthConfig?.discordClientId ?? proxyAuthConfig?.oauthClientIds?.discord
410
+ const resolvedOauthProviders = {
411
+ google: {
412
+ primaryClientId: config.auth?.oauthConfig?.google?.primaryClientId ?? proxyAuthConfig?.oauthClientIds?.google,
413
+ secondaryClientIds: config.auth?.oauthConfig?.google?.secondaryClientIds ?? []
414
+ },
415
+ apple: {
416
+ primaryClientId: config.auth?.oauthConfig?.apple?.primaryClientId ?? proxyAuthConfig?.oauthClientIds?.apple,
417
+ secondaryClientIds: config.auth?.oauthConfig?.apple?.secondaryClientIds ?? []
418
+ },
419
+ facebook: {
420
+ primaryClientId: config.auth?.oauthConfig?.facebook?.primaryClientId ?? proxyAuthConfig?.oauthClientIds?.facebook,
421
+ secondaryClientIds: config.auth?.oauthConfig?.facebook?.secondaryClientIds ?? []
422
+ },
423
+ x: {
424
+ primaryClientId: config.auth?.oauthConfig?.x?.primaryClientId ?? proxyAuthConfig?.oauthClientIds?.x,
425
+ secondaryClientIds: config.auth?.oauthConfig?.x?.secondaryClientIds ?? []
426
+ },
427
+ discord: {
428
+ primaryClientId: config.auth?.oauthConfig?.discord?.primaryClientId ?? proxyAuthConfig?.oauthClientIds?.discord,
429
+ secondaryClientIds: config.auth?.oauthConfig?.discord?.secondaryClientIds ?? []
430
+ }
379
431
  };
380
432
  const redirectUrl = config.auth?.oauthConfig?.oauthRedirectUri ?? proxyAuthConfig?.oauthRedirectUrl;
381
433
  // Set a default ordering for the oAuth methods
382
- const oauthOrder = config.auth?.oauthOrder ?? ["google", "apple", "x", "discord", "facebook"].filter(provider => resolvedMethods[`${provider}OauthEnabled`]);
434
+ const oauthOrder = config.ui?.authModal?.oauthOrder ?? ["google", "apple", "x", "discord", "facebook"].filter(provider => resolvedMethods[`${provider}OauthEnabled`]);
383
435
  // Set a default ordering for the overall auth methods
384
- const methodOrder = config.auth?.methodOrder ?? [oauthOrder.length > 0 ? "socials" : null, resolvedMethods.emailOtpAuthEnabled ? "email" : null, resolvedMethods.smsOtpAuthEnabled ? "sms" : null, resolvedMethods.passkeyAuthEnabled ? "passkey" : null, resolvedMethods.walletAuthEnabled ? "wallet" : null].filter(Boolean);
436
+ 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);
385
437
  // Warn if they are trying to set auth proxy only settings directly
386
438
  if (proxyAuthConfig) {
387
439
  if (config.auth?.sessionExpirationSeconds) {
@@ -400,24 +452,33 @@ const ClientProvider = ({
400
452
  otpAlphanumeric: proxyAuthConfig?.otpAlphanumeric ?? config.auth?.otpAlphanumeric ?? true,
401
453
  otpLength: proxyAuthConfig?.otpLength ?? config.auth?.otpLength ?? "6"
402
454
  };
455
+ const scopePasskeyToUser = config.auth?.scopePasskeyToUser ?? true;
403
456
  return {
404
457
  ...config,
458
+ scopePasskeyToUser,
405
459
  // Overrides:
406
460
  auth: {
407
461
  ...config.auth,
408
462
  ...authProxyPrioSettings,
409
- methods: resolvedMethods,
410
463
  oauthConfig: {
411
464
  ...config.auth?.oauthConfig,
412
- ...resolvedClientIds,
465
+ ...resolvedOauthProviders,
413
466
  oauthRedirectUri: redirectUrl,
414
467
  // on mobile we default to true since many mobile browsers
415
468
  // (e.g. Safari) block popups
416
469
  openOauthInPage: isMobile ? true : config.auth?.oauthConfig?.openOauthInPage
417
470
  },
418
- methodOrder,
419
- oauthOrder,
420
- autoRefreshSession: config.auth?.autoRefreshSession ?? true
471
+ autoRefreshSession: config.auth?.autoRefreshSession ?? true,
472
+ scopePasskeyToUser
473
+ },
474
+ ui: {
475
+ ...config.ui,
476
+ authModal: {
477
+ ...config.ui?.authModal,
478
+ methods: resolvedMethods,
479
+ methodOrder,
480
+ oauthOrder
481
+ }
421
482
  },
422
483
  autoRefreshManagedState: config.autoRefreshManagedState ?? true,
423
484
  walletConfig: {
@@ -482,7 +543,8 @@ const ClientProvider = ({
482
543
  walletConnect: masterConfig.walletConfig.walletConnect
483
544
  })
484
545
  },
485
- defaultStamperType: masterConfig.defaultStamperType
546
+ defaultStamperType: masterConfig.defaultStamperType,
547
+ scopePasskeyToUser: masterConfig.scopePasskeyToUser ?? true
486
548
  });
487
549
  await turnkeyClient.init();
488
550
  setClient(turnkeyClient);
@@ -535,7 +597,7 @@ const ClientProvider = ({
535
597
  // specifically, if WalletConnect finishes initializing before this promise resolves,
536
598
  // `maybeRefreshWallets()` could overwrite the WalletConnect wallet state with an outdated
537
599
  // list of wallets that doesn’t yet include the WalletConnect wallets
538
- const [, wallets] = await Promise.all([maybeRefreshUser(), (() => {
600
+ const [user, wallets] = await Promise.all([maybeRefreshUser(), (() => {
539
601
  if (!masterConfig?.autoRefreshManagedState) return [];
540
602
  return fetchWallets();
541
603
  })()]);
@@ -543,6 +605,7 @@ const ClientProvider = ({
543
605
  if (wallets) {
544
606
  setWallets(prev => utils.mergeWalletsWithoutDuplicates(prev, wallets));
545
607
  }
608
+ if (client) await core.applyPasskeyScope(client, client.config.passkeyConfig, user, masterConfig?.auth?.scopePasskeyToUser);
546
609
  return;
547
610
  }
548
611
  } catch (error) {
@@ -730,7 +793,8 @@ const ClientProvider = ({
730
793
  const allSessions = await client.getAllSessions();
731
794
  setSession(session);
732
795
  setAllSessions(allSessions);
733
- await Promise.all([maybeRefreshWallets(), maybeRefreshUser()]);
796
+ const [, user] = await Promise.all([maybeRefreshWallets(), maybeRefreshUser()]);
797
+ if (client) await core.applyPasskeyScope(client, client.config.passkeyConfig, user, masterConfig?.auth?.scopePasskeyToUser);
734
798
  if (masterConfig?.auth?.verifyWalletOnSignup === true && appProofs && appProofs.length > 0 && action === sdkTypes.AuthAction.SIGNUP) {
735
799
  // On signup, if we have appProofs, verify them
736
800
  await handleVerifyAppProofs({
@@ -764,9 +828,10 @@ const ClientProvider = ({
764
828
  * @returns void
765
829
  * @throws {TurnkeyError} If there is an error during the post-logout process.
766
830
  */
767
- const handlePostLogout = sessionKey => {
831
+ const handlePostLogout = react.useCallback(async sessionKey => {
768
832
  try {
769
- clearSessionTimeouts(sessionKey ? [sessionKey, `${sessionKey}-warning`] : undefined);
833
+ const timeoutKeys = sessionKey ? [sessionKey, `${sessionKey}-warning`] : undefined;
834
+ clearSessionTimeouts(timeoutKeys);
770
835
  setAllSessions(prev => {
771
836
  if (!prev) return prev;
772
837
  if (sessionKey) {
@@ -781,16 +846,29 @@ const ClientProvider = ({
781
846
  setSession(undefined);
782
847
  setUser(undefined);
783
848
  setWallets([]);
849
+ if (client) await core.resetPasskeyScope(client, client.config.passkeyConfig);
784
850
  } catch (error) {
785
- callbacks?.onError?.(new sdkTypes.TurnkeyError(`Failed to initialize sessions`, sdkTypes.TurnkeyErrorCodes.HANDLE_POST_LOGOUT_ERROR, error));
851
+ callbacks?.onError?.(new sdkTypes.TurnkeyError(`Failed to handle post logout`, sdkTypes.TurnkeyErrorCodes.HANDLE_POST_LOGOUT_ERROR, error));
786
852
  }
787
- };
853
+ }, [callbacks, clearSessionTimeouts, client, masterConfig?.passkeyConfig]);
788
854
  const createHttpClient = react.useCallback(params => {
789
855
  if (!client) {
790
856
  throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
791
857
  }
792
858
  return client.createHttpClient(params);
793
859
  }, [client]);
860
+ const overrideApiKeyStamper = react.useCallback(params => {
861
+ if (!client) {
862
+ throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
863
+ }
864
+ return client.overrideApiKeyStamper(params);
865
+ }, [client]);
866
+ const overridePasskeyStamper = react.useCallback(params => {
867
+ if (!client) {
868
+ throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
869
+ }
870
+ return client.overridePasskeyStamper(params);
871
+ }, [client]);
794
872
  const getActiveSessionKey = react.useCallback(async () => {
795
873
  if (!client) throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
796
874
  return utils.withTurnkeyErrorHandling(() => client.getActiveSessionKey(), undefined, callbacks, "Failed to get active session key");
@@ -805,10 +883,10 @@ const ClientProvider = ({
805
883
  if (!sessionKey) sessionKey = await getActiveSessionKey();
806
884
  await client.logout(params);
807
885
  // We only handle post logout if the sessionKey is defined since that means we actually logged out of a session.
808
- if (sessionKey) handlePostLogout(sessionKey);
886
+ if (sessionKey) await handlePostLogout(sessionKey);
809
887
  }, undefined, callbacks, "Failed to logout");
810
888
  return;
811
- }, [client, callbacks, getActiveSessionKey]);
889
+ }, [client, callbacks, getActiveSessionKey, handlePostLogout]);
812
890
  const getSession = react.useCallback(async params => {
813
891
  if (!client) throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
814
892
  return utils.withTurnkeyErrorHandling(() => client.getSession(params), undefined, callbacks, "Failed to get session");
@@ -868,6 +946,7 @@ const ClientProvider = ({
868
946
  if (user) {
869
947
  setUser(user);
870
948
  }
949
+ return user;
871
950
  }, [client, callbacks, fetchUser, logout]);
872
951
  /**
873
952
  * @internal
@@ -879,7 +958,7 @@ const ClientProvider = ({
879
958
  * @returns A promise that resolves when the user is refreshed, or does nothing if auto-refresh is disabled
880
959
  */
881
960
  const maybeRefreshUser = react.useCallback(async params => {
882
- if (!masterConfig?.autoRefreshManagedState) return;
961
+ if (!masterConfig?.autoRefreshManagedState) return undefined;
883
962
  return refreshUser(params);
884
963
  }, [masterConfig, refreshUser]);
885
964
  const refreshWallets = react.useCallback(async params => {
@@ -920,11 +999,15 @@ const ClientProvider = ({
920
999
  }, [masterConfig, refreshWallets]);
921
1000
  const clearSession = react.useCallback(async params => {
922
1001
  if (!client) throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
1002
+ const activeSessionKey = await getActiveSessionKey();
923
1003
  await utils.withTurnkeyErrorHandling(async () => client.clearSession(params), undefined, callbacks, "Failed to clear session");
924
- const sessionKey = params?.sessionKey ?? (await getActiveSessionKey());
1004
+ const sessionKey = params?.sessionKey ?? activeSessionKey;
925
1005
  if (!sessionKey) return;
926
- if (!params?.sessionKey) {
1006
+ if (!params?.sessionKey || params.sessionKey === activeSessionKey) {
927
1007
  setSession(undefined);
1008
+ setUser(undefined);
1009
+ setWallets([]);
1010
+ if (client) await core.resetPasskeyScope(client, client.config.passkeyConfig);
928
1011
  }
929
1012
  clearSessionTimeouts([sessionKey]);
930
1013
  // clear only the cleared session from allSessions
@@ -936,7 +1019,7 @@ const ClientProvider = ({
936
1019
  }
937
1020
  setAllSessions(newAllSessions);
938
1021
  return;
939
- }, [client, callbacks, getActiveSessionKey, allSessions]);
1022
+ }, [client, callbacks, getActiveSessionKey, allSessions, masterConfig?.passkeyConfig]);
940
1023
  /**
941
1024
  * @internal
942
1025
  * Schedules a session expiration and warning timer for the given session key.
@@ -1606,17 +1689,20 @@ const ClientProvider = ({
1606
1689
  const addPasskey = react.useCallback(async params => {
1607
1690
  if (!client) throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
1608
1691
  const res = await utils.withTurnkeyErrorHandling(() => client.addPasskey(params), () => logout(), callbacks, "Failed to add passkey");
1609
- if (res) await maybeRefreshUser({
1610
- stampWith: params?.stampWith,
1611
- ...(params?.organizationId && {
1612
- organizationId: params.organizationId
1613
- }),
1614
- ...(params?.userId && {
1615
- userId: params.userId
1616
- })
1617
- });
1692
+ if (res) {
1693
+ const updatedUser = await maybeRefreshUser({
1694
+ stampWith: params?.stampWith,
1695
+ ...(params?.organizationId && {
1696
+ organizationId: params.organizationId
1697
+ }),
1698
+ ...(params?.userId && {
1699
+ userId: params.userId
1700
+ })
1701
+ });
1702
+ await core.applyPasskeyScope(client, client.config.passkeyConfig, updatedUser, masterConfig?.auth?.scopePasskeyToUser);
1703
+ }
1618
1704
  return res;
1619
- }, [client, callbacks, logout, maybeRefreshUser]);
1705
+ }, [client, callbacks, logout, maybeRefreshUser, masterConfig?.passkeyConfig, masterConfig?.auth?.scopePasskeyToUser]);
1620
1706
  const removePasskeys = react.useCallback(async params => {
1621
1707
  if (!client) throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
1622
1708
  const res = await utils.withTurnkeyErrorHandling(() => client.removePasskeys(params), () => logout(), callbacks, "Failed to remove passkeys");
@@ -1724,15 +1810,20 @@ const ClientProvider = ({
1724
1810
  const allSessions = await getAllSessions();
1725
1811
  setSession(session);
1726
1812
  setAllSessions(allSessions);
1727
- await Promise.all([maybeRefreshWallets(), maybeRefreshUser()]);
1728
- }, [client, callbacks, logout, getActiveSessionKey, getSession, scheduleSessionExpiration, getAllSessions, maybeRefreshWallets, maybeRefreshUser]);
1813
+ const nextUser = await maybeRefreshUser();
1814
+ await maybeRefreshWallets();
1815
+ if (client) await core.applyPasskeyScope(client, client.config.passkeyConfig, nextUser, masterConfig?.auth?.scopePasskeyToUser);
1816
+ }, [client, callbacks, logout, getActiveSessionKey, getSession, scheduleSessionExpiration, getAllSessions, masterConfig?.passkeyConfig, masterConfig?.auth?.scopePasskeyToUser, maybeRefreshWallets, maybeRefreshUser]);
1729
1817
  const clearAllSessions = react.useCallback(async () => {
1730
1818
  if (!client) throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
1731
1819
  setSession(undefined);
1732
1820
  setAllSessions(undefined);
1821
+ setUser(undefined);
1822
+ setWallets([]);
1733
1823
  clearSessionTimeouts();
1734
- return await utils.withTurnkeyErrorHandling(() => client.clearAllSessions(), () => logout(), callbacks, "Failed to clear all sessions");
1735
- }, [client, callbacks, logout, clearSessionTimeouts]);
1824
+ await utils.withTurnkeyErrorHandling(() => client.clearAllSessions(), () => logout(), callbacks, "Failed to clear all sessions");
1825
+ await core.resetPasskeyScope(client, client.config.passkeyConfig);
1826
+ }, [client, callbacks, logout, clearSessionTimeouts, masterConfig?.passkeyConfig]);
1736
1827
  const setActiveSession = react.useCallback(async params => {
1737
1828
  if (!client) throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
1738
1829
  const session = await utils.withTurnkeyErrorHandling(() => client.getSession({
@@ -1745,10 +1836,12 @@ const ClientProvider = ({
1745
1836
  await utils.withTurnkeyErrorHandling(() => client.setActiveSession(params), () => logout(), callbacks, "Failed to set active session");
1746
1837
  setSession(session);
1747
1838
  await utils.withTurnkeyErrorHandling(async () => {
1748
- await Promise.all([maybeRefreshWallets(), maybeRefreshUser()]);
1839
+ const nextUser = await maybeRefreshUser();
1840
+ await maybeRefreshWallets();
1841
+ if (client) await core.applyPasskeyScope(client, client.config.passkeyConfig, nextUser, masterConfig?.auth?.scopePasskeyToUser);
1749
1842
  }, () => logout(), callbacks, "Failed to refresh data after setting active session");
1750
1843
  return;
1751
- }, [client, callbacks, logout, getSession, maybeRefreshWallets, maybeRefreshUser]);
1844
+ }, [client, callbacks, logout, getSession, masterConfig?.passkeyConfig, masterConfig?.auth?.scopePasskeyToUser, maybeRefreshWallets, maybeRefreshUser]);
1752
1845
  const clearUnusedKeyPairs = react.useCallback(async () => {
1753
1846
  if (!client) throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
1754
1847
  return utils.withTurnkeyErrorHandling(() => client.clearUnusedKeyPairs(), undefined, callbacks, "Failed to clear unused key pairs");
@@ -1757,6 +1850,14 @@ const ClientProvider = ({
1757
1850
  if (!client) throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
1758
1851
  return utils.withTurnkeyErrorHandling(() => client.createApiKeyPair(params), undefined, callbacks, "Failed to create API key pair");
1759
1852
  }, [client, callbacks]);
1853
+ const deleteApiKeyPair = react.useCallback(async params => {
1854
+ if (!client) throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
1855
+ return utils.withTurnkeyErrorHandling(() => client.deleteApiKeyPair(params), undefined, callbacks, "Failed to delete API key pair");
1856
+ }, [client, callbacks]);
1857
+ const signWithApiKey = react.useCallback(async params => {
1858
+ if (!client) throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
1859
+ return utils.withTurnkeyErrorHandling(() => client.signWithApiKey(params), undefined, callbacks, "Failed to sign with API key");
1860
+ }, [client, callbacks]);
1760
1861
  const getProxyAuthConfig = react.useCallback(async () => {
1761
1862
  if (!client) throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
1762
1863
  return utils.withTurnkeyErrorHandling(() => client.getProxyAuthConfig(), undefined, callbacks, "Failed to get proxy auth config");
@@ -1771,10 +1872,12 @@ const ClientProvider = ({
1771
1872
  }, [client, callbacks, logout]);
1772
1873
  const handleDiscordOauth = react.useCallback(async params => {
1773
1874
  const {
1774
- clientId = masterConfig?.auth?.oauthConfig?.discordClientId,
1875
+ primaryClientId = masterConfig?.auth?.oauthConfig?.discord?.primaryClientId,
1876
+ secondaryClientIds = masterConfig?.auth?.oauthConfig?.discord?.secondaryClientIds ?? [],
1775
1877
  openInPage = masterConfig?.auth?.oauthConfig?.openOauthInPage ?? false,
1776
1878
  additionalState: additionalParameters
1777
1879
  } = params || {};
1880
+ const clientId = primaryClientId;
1778
1881
  const provider = sdkTypes.OAuthProviders.DISCORD;
1779
1882
  if (!masterConfig) {
1780
1883
  throw new sdkTypes.TurnkeyError("Config is not ready yet!", sdkTypes.TurnkeyErrorCodes.INVALID_CONFIGURATION);
@@ -1839,7 +1942,19 @@ const ClientProvider = ({
1839
1942
  publicKey,
1840
1943
  result,
1841
1944
  callbacks,
1842
- completeOauth,
1945
+ completeOauth: completionParams => {
1946
+ const existingCreateSubOrgParams = masterConfig?.auth?.createSuborgParams?.oauth;
1947
+ const secondaryProviders = core.buildSecondaryOauthProviders(completionParams.oidcToken, completionParams.providerName ?? provider, secondaryClientIds);
1948
+ return completeOauth({
1949
+ ...completionParams,
1950
+ ...(secondaryProviders.length > 0 && {
1951
+ createSubOrgParams: {
1952
+ ...existingCreateSubOrgParams,
1953
+ oauthProviders: [...(existingCreateSubOrgParams?.oauthProviders ?? []), ...secondaryProviders]
1954
+ }
1955
+ })
1956
+ });
1957
+ },
1843
1958
  onOauthSuccess: params?.onOauthSuccess,
1844
1959
  exchangeCodeForToken: async codeVerifier => {
1845
1960
  const resp = await client?.httpClient.proxyOAuth2Authenticate({
@@ -1866,10 +1981,12 @@ const ClientProvider = ({
1866
1981
  }, [client, callbacks, completeOauth, createApiKeyPair, masterConfig]);
1867
1982
  const handleXOauth = react.useCallback(async params => {
1868
1983
  const {
1869
- clientId = masterConfig?.auth?.oauthConfig?.xClientId,
1984
+ primaryClientId = masterConfig?.auth?.oauthConfig?.x?.primaryClientId,
1985
+ secondaryClientIds = masterConfig?.auth?.oauthConfig?.x?.secondaryClientIds ?? [],
1870
1986
  openInPage = masterConfig?.auth?.oauthConfig?.openOauthInPage ?? false,
1871
1987
  additionalState: additionalParameters
1872
1988
  } = params || {};
1989
+ const clientId = primaryClientId;
1873
1990
  const provider = sdkTypes.OAuthProviders.X;
1874
1991
  if (!masterConfig) {
1875
1992
  throw new sdkTypes.TurnkeyError("Config is not ready yet!", sdkTypes.TurnkeyErrorCodes.INVALID_CONFIGURATION);
@@ -1934,7 +2051,19 @@ const ClientProvider = ({
1934
2051
  publicKey,
1935
2052
  result,
1936
2053
  callbacks,
1937
- completeOauth,
2054
+ completeOauth: completionParams => {
2055
+ const existingCreateSubOrgParams = masterConfig?.auth?.createSuborgParams?.oauth;
2056
+ const secondaryProviders = core.buildSecondaryOauthProviders(completionParams.oidcToken, completionParams.providerName ?? provider, secondaryClientIds);
2057
+ return completeOauth({
2058
+ ...completionParams,
2059
+ ...(secondaryProviders.length > 0 && {
2060
+ createSubOrgParams: {
2061
+ ...existingCreateSubOrgParams,
2062
+ oauthProviders: [...(existingCreateSubOrgParams?.oauthProviders ?? []), ...secondaryProviders]
2063
+ }
2064
+ })
2065
+ });
2066
+ },
1938
2067
  onOauthSuccess: params?.onOauthSuccess,
1939
2068
  exchangeCodeForToken: async codeVerifier => {
1940
2069
  const resp = await client?.httpClient.proxyOAuth2Authenticate({
@@ -1961,10 +2090,12 @@ const ClientProvider = ({
1961
2090
  }, [client, callbacks, completeOauth, createApiKeyPair, masterConfig]);
1962
2091
  const handleGoogleOauth = react.useCallback(async params => {
1963
2092
  const {
1964
- clientId = masterConfig?.auth?.oauthConfig?.googleClientId,
2093
+ primaryClientId = masterConfig?.auth?.oauthConfig?.google?.primaryClientId,
2094
+ secondaryClientIds = masterConfig?.auth?.oauthConfig?.google?.secondaryClientIds ?? [],
1965
2095
  openInPage = masterConfig?.auth?.oauthConfig?.openOauthInPage ?? false,
1966
2096
  additionalState: additionalParameters
1967
2097
  } = params || {};
2098
+ const clientId = primaryClientId;
1968
2099
  const provider = sdkTypes.OAuthProviders.GOOGLE;
1969
2100
  if (!masterConfig) {
1970
2101
  throw new sdkTypes.TurnkeyError("Config is not ready yet!", sdkTypes.TurnkeyErrorCodes.INVALID_CONFIGURATION);
@@ -2023,7 +2154,19 @@ const ClientProvider = ({
2023
2154
  publicKey,
2024
2155
  result,
2025
2156
  callbacks,
2026
- completeOauth,
2157
+ completeOauth: completionParams => {
2158
+ const existingCreateSubOrgParams = masterConfig?.auth?.createSuborgParams?.oauth;
2159
+ const secondaryProviders = core.buildSecondaryOauthProviders(completionParams.oidcToken, completionParams.providerName ?? provider, secondaryClientIds);
2160
+ return completeOauth({
2161
+ ...completionParams,
2162
+ ...(secondaryProviders.length > 0 && {
2163
+ createSubOrgParams: {
2164
+ ...existingCreateSubOrgParams,
2165
+ oauthProviders: [...(existingCreateSubOrgParams?.oauthProviders ?? []), ...secondaryProviders]
2166
+ }
2167
+ })
2168
+ });
2169
+ },
2027
2170
  onOauthSuccess: params?.onOauthSuccess
2028
2171
  }).then(() => resolve()).catch(reject);
2029
2172
  }
@@ -2039,10 +2182,12 @@ const ClientProvider = ({
2039
2182
  }, [callbacks, completeOauth, createApiKeyPair, masterConfig]);
2040
2183
  const handleAppleOauth = react.useCallback(async params => {
2041
2184
  const {
2042
- clientId = masterConfig?.auth?.oauthConfig?.appleClientId,
2185
+ primaryClientId = masterConfig?.auth?.oauthConfig?.apple?.primaryClientId,
2186
+ secondaryClientIds = masterConfig?.auth?.oauthConfig?.apple?.secondaryClientIds ?? [],
2043
2187
  openInPage = masterConfig?.auth?.oauthConfig?.openOauthInPage ?? false,
2044
2188
  additionalState: additionalParameters
2045
2189
  } = params || {};
2190
+ const clientId = primaryClientId;
2046
2191
  const provider = sdkTypes.OAuthProviders.APPLE;
2047
2192
  if (!masterConfig) {
2048
2193
  throw new sdkTypes.TurnkeyError("Config is not ready yet!", sdkTypes.TurnkeyErrorCodes.INVALID_CONFIGURATION);
@@ -2101,7 +2246,19 @@ const ClientProvider = ({
2101
2246
  publicKey,
2102
2247
  result,
2103
2248
  callbacks,
2104
- completeOauth,
2249
+ completeOauth: completionParams => {
2250
+ const existingCreateSubOrgParams = masterConfig?.auth?.createSuborgParams?.oauth;
2251
+ const secondaryProviders = core.buildSecondaryOauthProviders(completionParams.oidcToken, completionParams.providerName ?? provider, secondaryClientIds);
2252
+ return completeOauth({
2253
+ ...completionParams,
2254
+ ...(secondaryProviders.length > 0 && {
2255
+ createSubOrgParams: {
2256
+ ...existingCreateSubOrgParams,
2257
+ oauthProviders: [...(existingCreateSubOrgParams?.oauthProviders ?? []), ...secondaryProviders]
2258
+ }
2259
+ })
2260
+ });
2261
+ },
2105
2262
  onOauthSuccess: params?.onOauthSuccess
2106
2263
  }).then(() => resolve()).catch(reject);
2107
2264
  }
@@ -2117,10 +2274,12 @@ const ClientProvider = ({
2117
2274
  }, [callbacks, completeOauth, createApiKeyPair, masterConfig]);
2118
2275
  const handleFacebookOauth = react.useCallback(async params => {
2119
2276
  const {
2120
- clientId = masterConfig?.auth?.oauthConfig?.facebookClientId,
2277
+ primaryClientId = masterConfig?.auth?.oauthConfig?.facebook?.primaryClientId,
2278
+ secondaryClientIds = masterConfig?.auth?.oauthConfig?.facebook?.secondaryClientIds ?? [],
2121
2279
  openInPage = masterConfig?.auth?.oauthConfig?.openOauthInPage ?? false,
2122
2280
  additionalState: additionalParameters
2123
2281
  } = params || {};
2282
+ const clientId = primaryClientId;
2124
2283
  const provider = sdkTypes.OAuthProviders.FACEBOOK;
2125
2284
  if (!masterConfig) {
2126
2285
  throw new sdkTypes.TurnkeyError("Config is not ready yet!", sdkTypes.TurnkeyErrorCodes.INVALID_CONFIGURATION);
@@ -2185,7 +2344,19 @@ const ClientProvider = ({
2185
2344
  publicKey,
2186
2345
  result,
2187
2346
  callbacks,
2188
- completeOauth,
2347
+ completeOauth: completionParams => {
2348
+ const existingCreateSubOrgParams = masterConfig?.auth?.createSuborgParams?.oauth;
2349
+ const secondaryProviders = core.buildSecondaryOauthProviders(completionParams.oidcToken, completionParams.providerName ?? provider, secondaryClientIds);
2350
+ return completeOauth({
2351
+ ...completionParams,
2352
+ ...(secondaryProviders.length > 0 && {
2353
+ createSubOrgParams: {
2354
+ ...existingCreateSubOrgParams,
2355
+ oauthProviders: [...(existingCreateSubOrgParams?.oauthProviders ?? []), ...secondaryProviders]
2356
+ }
2357
+ })
2358
+ });
2359
+ },
2189
2360
  onOauthSuccess: params?.onOauthSuccess,
2190
2361
  exchangeCodeForToken: async codeVerifier => {
2191
2362
  const tokenData = await pkce.exchangeFacebookCodeForToken(clientId, redirectUri, result.authCode, codeVerifier);
@@ -2489,9 +2660,6 @@ const ClientProvider = ({
2489
2660
  if (!masterConfig) {
2490
2661
  throw new sdkTypes.TurnkeyError("Config is not ready yet!", sdkTypes.TurnkeyErrorCodes.CONFIG_NOT_INITIALIZED);
2491
2662
  }
2492
- if (!masterConfig.auth?.methods?.smsOtpAuthEnabled) {
2493
- throw new sdkTypes.TurnkeyError("SMS OTP authentication is not enabled in the configuration.", sdkTypes.TurnkeyErrorCodes.AUTH_METHOD_NOT_ENABLED);
2494
- }
2495
2663
  const s = await getSession();
2496
2664
  const organizationId = params?.organizationId || s?.organizationId;
2497
2665
  if (!organizationId) {
@@ -2541,7 +2709,10 @@ const ClientProvider = ({
2541
2709
  });
2542
2710
  }), () => logout());
2543
2711
  } else {
2544
- const otpId = await initOtp({
2712
+ const {
2713
+ otpId,
2714
+ otpEncryptionTargetBundle
2715
+ } = await initOtp({
2545
2716
  otpType: core.OtpType.Sms,
2546
2717
  contact: params.phoneNumber
2547
2718
  });
@@ -2552,6 +2723,7 @@ const ClientProvider = ({
2552
2723
  otpType: core.OtpType.Sms,
2553
2724
  contact: params.phoneNumber,
2554
2725
  otpId: otpId,
2726
+ otpEncryptionTargetBundle: otpEncryptionTargetBundle,
2555
2727
  otpLength: masterConfig.auth?.otpLength !== undefined ? Number(masterConfig.auth.otpLength) : undefined,
2556
2728
  alphanumeric: masterConfig.auth?.otpAlphanumeric,
2557
2729
  onContinue: async otpCode => {
@@ -2561,8 +2733,7 @@ const ClientProvider = ({
2561
2733
  } = await verifyOtp({
2562
2734
  otpId,
2563
2735
  otpCode,
2564
- contact: params.phoneNumber,
2565
- otpType: core.OtpType.Sms
2736
+ otpEncryptionTargetBundle
2566
2737
  });
2567
2738
  const res = await updateUserPhoneNumber({
2568
2739
  phoneNumber: params.phoneNumber,
@@ -2659,7 +2830,10 @@ const ClientProvider = ({
2659
2830
  });
2660
2831
  }), () => logout());
2661
2832
  } else {
2662
- const otpId = await initOtp({
2833
+ const {
2834
+ otpId,
2835
+ otpEncryptionTargetBundle
2836
+ } = await initOtp({
2663
2837
  otpType: core.OtpType.Email,
2664
2838
  contact: params.email
2665
2839
  });
@@ -2670,6 +2844,7 @@ const ClientProvider = ({
2670
2844
  otpType: core.OtpType.Email,
2671
2845
  contact: params.email,
2672
2846
  otpId: otpId,
2847
+ otpEncryptionTargetBundle: otpEncryptionTargetBundle,
2673
2848
  otpLength: masterConfig?.auth?.otpLength !== undefined ? Number(masterConfig.auth.otpLength) : undefined,
2674
2849
  alphanumeric: masterConfig?.auth?.otpAlphanumeric,
2675
2850
  onContinue: async otpCode => {
@@ -2679,8 +2854,7 @@ const ClientProvider = ({
2679
2854
  } = await verifyOtp({
2680
2855
  otpId,
2681
2856
  otpCode,
2682
- contact: params.email,
2683
- otpType: core.OtpType.Email
2857
+ otpEncryptionTargetBundle
2684
2858
  });
2685
2859
  const res = await updateUserEmail({
2686
2860
  email: params.email,
@@ -2774,7 +2948,10 @@ const ClientProvider = ({
2774
2948
  });
2775
2949
  }), () => logout());
2776
2950
  } else {
2777
- const otpId = await initOtp({
2951
+ const {
2952
+ otpId,
2953
+ otpEncryptionTargetBundle
2954
+ } = await initOtp({
2778
2955
  otpType: core.OtpType.Email,
2779
2956
  contact: params.email
2780
2957
  });
@@ -2785,6 +2962,7 @@ const ClientProvider = ({
2785
2962
  otpType: core.OtpType.Email,
2786
2963
  contact: params.email,
2787
2964
  otpId: otpId,
2965
+ otpEncryptionTargetBundle: otpEncryptionTargetBundle,
2788
2966
  otpLength: masterConfig?.auth?.otpLength !== undefined ? Number(masterConfig.auth.otpLength) : undefined,
2789
2967
  alphanumeric: masterConfig?.auth?.otpAlphanumeric,
2790
2968
  onContinue: async otpCode => {
@@ -2794,8 +2972,7 @@ const ClientProvider = ({
2794
2972
  } = await verifyOtp({
2795
2973
  otpId,
2796
2974
  otpCode,
2797
- contact: params.email,
2798
- otpType: core.OtpType.Email
2975
+ otpEncryptionTargetBundle
2799
2976
  });
2800
2977
  const res = await updateUserEmail({
2801
2978
  email: params.email,
@@ -2839,9 +3016,6 @@ const ClientProvider = ({
2839
3016
  if (!masterConfig) {
2840
3017
  throw new sdkTypes.TurnkeyError("Config is not ready yet!", sdkTypes.TurnkeyErrorCodes.CONFIG_NOT_INITIALIZED);
2841
3018
  }
2842
- if (!masterConfig.auth?.methods?.smsOtpAuthEnabled) {
2843
- throw new sdkTypes.TurnkeyError("SMS OTP authentication is not enabled in the configuration.", sdkTypes.TurnkeyErrorCodes.AUTH_METHOD_NOT_ENABLED);
2844
- }
2845
3019
  const s = await getSession();
2846
3020
  const organizationId = params?.organizationId || s?.organizationId;
2847
3021
  if (!organizationId) {
@@ -2893,7 +3067,10 @@ const ClientProvider = ({
2893
3067
  });
2894
3068
  }), () => logout(), callbacks, "Failed to add phone number");
2895
3069
  } else {
2896
- const otpId = await initOtp({
3070
+ const {
3071
+ otpId,
3072
+ otpEncryptionTargetBundle
3073
+ } = await initOtp({
2897
3074
  otpType: core.OtpType.Sms,
2898
3075
  contact: params.phoneNumber
2899
3076
  });
@@ -2904,6 +3081,7 @@ const ClientProvider = ({
2904
3081
  otpType: core.OtpType.Sms,
2905
3082
  contact: params.phoneNumber,
2906
3083
  otpId: otpId,
3084
+ otpEncryptionTargetBundle: otpEncryptionTargetBundle,
2907
3085
  otpLength: masterConfig.auth?.otpLength !== undefined ? Number(masterConfig.auth.otpLength) : undefined,
2908
3086
  alphanumeric: masterConfig?.auth?.otpAlphanumeric,
2909
3087
  onContinue: async otpCode => {
@@ -2913,8 +3091,7 @@ const ClientProvider = ({
2913
3091
  } = await verifyOtp({
2914
3092
  otpId,
2915
3093
  otpCode,
2916
- contact: params.phoneNumber,
2917
- otpType: core.OtpType.Sms
3094
+ otpEncryptionTargetBundle
2918
3095
  });
2919
3096
  const res = await updateUserPhoneNumber({
2920
3097
  phoneNumber: params.phoneNumber,
@@ -3107,6 +3284,29 @@ const ClientProvider = ({
3107
3284
  successPageDuration = 2000,
3108
3285
  openInPage = masterConfig?.auth?.oauthConfig?.openOauthInPage ?? false
3109
3286
  } = params;
3287
+ // Resolve the provider's per-provider config, then apply per-call overrides.
3288
+ let providerConfig;
3289
+ switch (providerName) {
3290
+ case sdkTypes.OAuthProviders.DISCORD:
3291
+ providerConfig = masterConfig?.auth?.oauthConfig?.discord;
3292
+ break;
3293
+ case sdkTypes.OAuthProviders.X:
3294
+ providerConfig = masterConfig?.auth?.oauthConfig?.x;
3295
+ break;
3296
+ case sdkTypes.OAuthProviders.GOOGLE:
3297
+ providerConfig = masterConfig?.auth?.oauthConfig?.google;
3298
+ break;
3299
+ case sdkTypes.OAuthProviders.APPLE:
3300
+ providerConfig = masterConfig?.auth?.oauthConfig?.apple;
3301
+ break;
3302
+ case sdkTypes.OAuthProviders.FACEBOOK:
3303
+ providerConfig = masterConfig?.auth?.oauthConfig?.facebook;
3304
+ break;
3305
+ default:
3306
+ providerConfig = undefined;
3307
+ }
3308
+ const primaryClientId = params.primaryClientId ?? providerConfig?.primaryClientId;
3309
+ const secondaryClientIds = params.secondaryClientIds ?? providerConfig?.secondaryClientIds ?? [];
3110
3310
  const s = await getSession();
3111
3311
  const organizationId = params?.organizationId || s?.organizationId;
3112
3312
  if (!organizationId) {
@@ -3119,9 +3319,13 @@ const ClientProvider = ({
3119
3319
  return new Promise(async (resolve, reject) => {
3120
3320
  try {
3121
3321
  const onOauthSuccess = async params => {
3322
+ const oidcClaims = core.buildSecondaryOidcClaims(params.oidcToken, secondaryClientIds);
3122
3323
  await addOauthProvider({
3123
3324
  providerName: params.providerName,
3124
3325
  oidcToken: params.oidcToken,
3326
+ ...(oidcClaims.length > 0 && {
3327
+ oidcClaims
3328
+ }),
3125
3329
  stampWith,
3126
3330
  organizationId,
3127
3331
  userId
@@ -3156,66 +3360,42 @@ const ClientProvider = ({
3156
3360
  openModal: "true"
3157
3361
  })
3158
3362
  } : undefined;
3363
+ // Forward overrides so the inner handler uses the same client IDs.
3364
+ const sharedOauthParams = {
3365
+ openInPage,
3366
+ ...(primaryClientId && {
3367
+ primaryClientId
3368
+ }),
3369
+ ...(secondaryClientIds.length > 0 && {
3370
+ secondaryClientIds
3371
+ }),
3372
+ ...(additionalState && {
3373
+ additionalState
3374
+ }),
3375
+ ...(!openInPage && {
3376
+ onOauthSuccess
3377
+ })
3378
+ };
3159
3379
  switch (providerName) {
3160
3380
  case sdkTypes.OAuthProviders.DISCORD:
3161
3381
  {
3162
- return await handleDiscordOauth({
3163
- openInPage,
3164
- ...(additionalState && {
3165
- additionalState
3166
- }),
3167
- ...(!openInPage && {
3168
- onOauthSuccess
3169
- })
3170
- });
3382
+ return await handleDiscordOauth(sharedOauthParams);
3171
3383
  }
3172
3384
  case sdkTypes.OAuthProviders.X:
3173
3385
  {
3174
- return await handleXOauth({
3175
- openInPage,
3176
- ...(additionalState && {
3177
- additionalState
3178
- }),
3179
- ...(!openInPage && {
3180
- onOauthSuccess
3181
- })
3182
- });
3386
+ return await handleXOauth(sharedOauthParams);
3183
3387
  }
3184
3388
  case sdkTypes.OAuthProviders.GOOGLE:
3185
3389
  {
3186
- return await handleGoogleOauth({
3187
- openInPage,
3188
- ...(additionalState && {
3189
- additionalState
3190
- }),
3191
- ...(!openInPage && {
3192
- onOauthSuccess
3193
- })
3194
- });
3390
+ return await handleGoogleOauth(sharedOauthParams);
3195
3391
  }
3196
3392
  case sdkTypes.OAuthProviders.APPLE:
3197
3393
  {
3198
- return await handleAppleOauth({
3199
- openInPage,
3200
- ...(additionalState && {
3201
- additionalState
3202
- }),
3203
- ...(!openInPage && {
3204
- onOauthSuccess
3205
- })
3206
- });
3394
+ return await handleAppleOauth(sharedOauthParams);
3207
3395
  }
3208
3396
  case sdkTypes.OAuthProviders.FACEBOOK:
3209
3397
  {
3210
- return await handleFacebookOauth({
3211
- openInPage,
3212
- ...(additionalState && {
3213
- additionalState
3214
- }),
3215
- ...(!openInPage && {
3216
- onOauthSuccess
3217
- })
3218
- });
3398
+ return await handleFacebookOauth(sharedOauthParams);
3219
3399
  }
3220
3400
  default:
3221
3401
  {
@@ -3379,7 +3559,7 @@ const ClientProvider = ({
3379
3559
  const tx = {
3380
3560
  from,
3381
3561
  to,
3382
- caip2,
3562
+ caip2: caip2,
3383
3563
  sponsor: sponsor ?? false,
3384
3564
  ...(value ? {
3385
3565
  value
@@ -3812,6 +3992,8 @@ const ClientProvider = ({
3812
3992
  config: masterConfig,
3813
3993
  httpClient: client?.httpClient,
3814
3994
  createHttpClient,
3995
+ overrideApiKeyStamper,
3996
+ overridePasskeyStamper,
3815
3997
  createPasskey,
3816
3998
  logout,
3817
3999
  loginWithPasskey,
@@ -3874,6 +4056,8 @@ const ClientProvider = ({
3874
4056
  clearUnusedKeyPairs,
3875
4057
  getActiveSessionKey,
3876
4058
  createApiKeyPair,
4059
+ deleteApiKeyPair,
4060
+ signWithApiKey,
3877
4061
  getProxyAuthConfig,
3878
4062
  fetchBootProofForAppProof,
3879
4063
  verifyAppProofs,