@authowl/react 0.22.0 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { AuthConfig, Locale, AuthOwlClient, PublicConfig, ConsentStatus, OrganizationInvitationDetails, OrganizationDetails, OrganizationMembership, HasParams, AuthUser, AuthClientError, InvitationRecipientHint, SessionState, Organization, AuthOwlErrorCode } from '@authowl/core';
2
+ import { AuthConfig, Locale, AuthOwlClient, PublicConfig, ConsentStatus, OrganizationInvitationDetails, OrganizationDetails, OrganizationMembership, HasParams, AuthUser, AuthClientError, InvitationRecipientHint, SessionState, Organization, AuthOwlErrorCode, LastUsedSignInMethod } from '@authowl/core';
3
3
  export { AuthOwlError, AuthPasskey, ConsentStatus, HasParams, InvalidKeyError, Organization, OrganizationDetails, OrganizationInvitation, OrganizationMember, OrganizationMemberWithUser, OrganizationMembership, OrganizationRoleSummary, OrganizationTeam, OrganizationTeamMember, OrganizationUserInvitation, PublicConfig, RateLimitedError, createMembershipHas, membershipHas, membershipHasPermission, membershipHasTeam } from '@authowl/core';
4
4
 
5
5
  type Appearance = {
@@ -901,7 +901,7 @@ type GoogleOneTapError = {
901
901
  type GoogleOneTapProps = {
902
902
  /** Disable prompting without unmounting the component. */
903
903
  disabled?: boolean;
904
- /** Bind Google's ID token to this browser attempt. Generate a fresh random value server-side. */
904
+ /** Ask Google to include this nonce and verify the returned token carries the same value. */
905
905
  nonce?: string;
906
906
  /** Let eligible returning Google users sign in automatically. Defaults to false. */
907
907
  autoSelect?: boolean;
@@ -924,4 +924,24 @@ type GoogleOneTapProps = {
924
924
  /** Invisible, server-configured Google One Tap conversion helper. */
925
925
  declare function GoogleOneTap({ disabled, nonce, autoSelect, cancelOnTapOutside, context, itpSupport, loginHint, hostedDomain, stateCookieDomain, scriptNonce, onSignedIn, onSkipped, onDismissed, onError, }: GoogleOneTapProps): null;
926
926
 
927
- export { type Appearance, AuthLoaded, type AuthLoadedProps, AuthLoading, type AuthLoadingProps, AuthOwlBadge, type AuthOwlBadgeProps, AuthOwlBranding, type AuthOwlBrandingProps, AuthOwlProvider, type AuthOwlProviderProps, type AutofillHost, BackupCodesManager, type BackupCodesManagerProps, Bidi, type ConfigState, ConsentDocLinks, type ConsentDocLinksProps, ConsentGate, type ConsentGateProps, CreateOrganization, type CreateOrganizationProps, DEFAULT_BRAND_COLOR, EmailOtpForm, type EmailOtpFormProps, ForgotPassword, type ForgotPasswordProps, GoogleOneTap, type GoogleOneTapDismissReason, type GoogleOneTapError, type GoogleOneTapErrorCode, type GoogleOneTapProps, type GoogleOneTapSkipReason, InvitationPrompt, type InvitationPromptStatus, KNOWN_METHODS, type KnownMethod, MFAChallenge, type MFAChallengeProps, MFAEnrollment, type MFAEnrollmentProps, MFARequiredGate, type MFARequiredGateProps, MagicLinkForm, type MagicLinkFormProps, OrganizationList, type OrganizationListProps, OrganizationProfile, type OrganizationProfileProps, type OrganizationProfileSection, OrganizationSwitcher, type OrganizationSwitcherProps, PasskeyButton, type PasskeyButtonProps, PasskeyManager, type PasskeyManagerProps, PhoneOTP, type PhoneOTPProps, Protect, type ProtectProps, ResetPassword, type ResetPasswordProps, SignIn, type SignInPlan, type SignInProps, SignOutButton, type SignOutButtonProps, SignUp, type SignUpProps, SignedIn, type SignedInProps, SignedOut, type SignedOutProps, SocialButtons, type SocialButtonsProps, Spinner, type UseAccountResult, type UseAuthResult, type UseConsentResult, type UseEmailVerificationResult, type UseMFAResult, type UseOrganizationInvitationResult, type UseOrganizationResult, type UsePasskeysResult, type UsePasswordResetResult, type UsePublicConfigResult, type UseSignInResult, type UseSignOutResult, type UseSignUpResult, type UseUserResult, type UseWaitlistResult, UserButton, UserProfile, type UserProfileProps, type UserProfileSection, VerificationPending, type VerificationPendingProps, VerifyEmail, type VerifyEmailProps, Waitlist, type WaitlistProps, emailAutocomplete, resolveSignInMethods, useAccount, useAuth, useAuthClient, useAuthOwlContext, useConsent, useEmailVerification, useInvitationRecipientHint, useLocale, useMFA, useOrganization, useOrganizationInvitation, usePasskeys, usePasswordReset, usePublicConfig, useSession, useSignIn, useSignOut, useSignUp, useUser, useWaitlist };
927
+ /**
928
+ * Which sign-in method last worked in this browser, for this project.
929
+ *
930
+ * Two kinds of method need different treatment, and conflating them is the bug
931
+ * this shape exists to avoid:
932
+ *
933
+ * completes in page password, email-OTP verification, passkey - observable
934
+ * success, so it is recorded when it happens.
935
+ *
936
+ * leaves the page social, SSO, magic link - the page that would observe
937
+ * success is one the browser navigates away from. The
938
+ * attempt is PARKED and promoted only when a session
939
+ * actually appears, so bouncing off a consent screen does
940
+ * not teach the form that the provider worked.
941
+ *
942
+ * Everything is per project and per browser, and never keyed by an identifier -
943
+ * see the core module for why that line matters.
944
+ */
945
+ declare function useLastUsedSignInMethod(): LastUsedSignInMethod | null;
946
+
947
+ export { type Appearance, AuthLoaded, type AuthLoadedProps, AuthLoading, type AuthLoadingProps, AuthOwlBadge, type AuthOwlBadgeProps, AuthOwlBranding, type AuthOwlBrandingProps, AuthOwlProvider, type AuthOwlProviderProps, type AutofillHost, BackupCodesManager, type BackupCodesManagerProps, Bidi, type ConfigState, ConsentDocLinks, type ConsentDocLinksProps, ConsentGate, type ConsentGateProps, CreateOrganization, type CreateOrganizationProps, DEFAULT_BRAND_COLOR, EmailOtpForm, type EmailOtpFormProps, ForgotPassword, type ForgotPasswordProps, GoogleOneTap, type GoogleOneTapDismissReason, type GoogleOneTapError, type GoogleOneTapErrorCode, type GoogleOneTapProps, type GoogleOneTapSkipReason, InvitationPrompt, type InvitationPromptStatus, KNOWN_METHODS, type KnownMethod, MFAChallenge, type MFAChallengeProps, MFAEnrollment, type MFAEnrollmentProps, MFARequiredGate, type MFARequiredGateProps, MagicLinkForm, type MagicLinkFormProps, OrganizationList, type OrganizationListProps, OrganizationProfile, type OrganizationProfileProps, type OrganizationProfileSection, OrganizationSwitcher, type OrganizationSwitcherProps, PasskeyButton, type PasskeyButtonProps, PasskeyManager, type PasskeyManagerProps, PhoneOTP, type PhoneOTPProps, Protect, type ProtectProps, ResetPassword, type ResetPasswordProps, SignIn, type SignInPlan, type SignInProps, SignOutButton, type SignOutButtonProps, SignUp, type SignUpProps, SignedIn, type SignedInProps, SignedOut, type SignedOutProps, SocialButtons, type SocialButtonsProps, Spinner, type UseAccountResult, type UseAuthResult, type UseConsentResult, type UseEmailVerificationResult, type UseMFAResult, type UseOrganizationInvitationResult, type UseOrganizationResult, type UsePasskeysResult, type UsePasswordResetResult, type UsePublicConfigResult, type UseSignInResult, type UseSignOutResult, type UseSignUpResult, type UseUserResult, type UseWaitlistResult, UserButton, UserProfile, type UserProfileProps, type UserProfileSection, VerificationPending, type VerificationPendingProps, VerifyEmail, type VerifyEmailProps, Waitlist, type WaitlistProps, emailAutocomplete, resolveSignInMethods, useAccount, useAuth, useAuthClient, useAuthOwlContext, useConsent, useEmailVerification, useInvitationRecipientHint, useLastUsedSignInMethod, useLocale, useMFA, useOrganization, useOrganizationInvitation, usePasskeys, usePasswordReset, usePublicConfig, useSession, useSignIn, useSignOut, useSignUp, useUser, useWaitlist };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { AuthConfig, Locale, AuthOwlClient, PublicConfig, ConsentStatus, OrganizationInvitationDetails, OrganizationDetails, OrganizationMembership, HasParams, AuthUser, AuthClientError, InvitationRecipientHint, SessionState, Organization, AuthOwlErrorCode } from '@authowl/core';
2
+ import { AuthConfig, Locale, AuthOwlClient, PublicConfig, ConsentStatus, OrganizationInvitationDetails, OrganizationDetails, OrganizationMembership, HasParams, AuthUser, AuthClientError, InvitationRecipientHint, SessionState, Organization, AuthOwlErrorCode, LastUsedSignInMethod } from '@authowl/core';
3
3
  export { AuthOwlError, AuthPasskey, ConsentStatus, HasParams, InvalidKeyError, Organization, OrganizationDetails, OrganizationInvitation, OrganizationMember, OrganizationMemberWithUser, OrganizationMembership, OrganizationRoleSummary, OrganizationTeam, OrganizationTeamMember, OrganizationUserInvitation, PublicConfig, RateLimitedError, createMembershipHas, membershipHas, membershipHasPermission, membershipHasTeam } from '@authowl/core';
4
4
 
5
5
  type Appearance = {
@@ -901,7 +901,7 @@ type GoogleOneTapError = {
901
901
  type GoogleOneTapProps = {
902
902
  /** Disable prompting without unmounting the component. */
903
903
  disabled?: boolean;
904
- /** Bind Google's ID token to this browser attempt. Generate a fresh random value server-side. */
904
+ /** Ask Google to include this nonce and verify the returned token carries the same value. */
905
905
  nonce?: string;
906
906
  /** Let eligible returning Google users sign in automatically. Defaults to false. */
907
907
  autoSelect?: boolean;
@@ -924,4 +924,24 @@ type GoogleOneTapProps = {
924
924
  /** Invisible, server-configured Google One Tap conversion helper. */
925
925
  declare function GoogleOneTap({ disabled, nonce, autoSelect, cancelOnTapOutside, context, itpSupport, loginHint, hostedDomain, stateCookieDomain, scriptNonce, onSignedIn, onSkipped, onDismissed, onError, }: GoogleOneTapProps): null;
926
926
 
927
- export { type Appearance, AuthLoaded, type AuthLoadedProps, AuthLoading, type AuthLoadingProps, AuthOwlBadge, type AuthOwlBadgeProps, AuthOwlBranding, type AuthOwlBrandingProps, AuthOwlProvider, type AuthOwlProviderProps, type AutofillHost, BackupCodesManager, type BackupCodesManagerProps, Bidi, type ConfigState, ConsentDocLinks, type ConsentDocLinksProps, ConsentGate, type ConsentGateProps, CreateOrganization, type CreateOrganizationProps, DEFAULT_BRAND_COLOR, EmailOtpForm, type EmailOtpFormProps, ForgotPassword, type ForgotPasswordProps, GoogleOneTap, type GoogleOneTapDismissReason, type GoogleOneTapError, type GoogleOneTapErrorCode, type GoogleOneTapProps, type GoogleOneTapSkipReason, InvitationPrompt, type InvitationPromptStatus, KNOWN_METHODS, type KnownMethod, MFAChallenge, type MFAChallengeProps, MFAEnrollment, type MFAEnrollmentProps, MFARequiredGate, type MFARequiredGateProps, MagicLinkForm, type MagicLinkFormProps, OrganizationList, type OrganizationListProps, OrganizationProfile, type OrganizationProfileProps, type OrganizationProfileSection, OrganizationSwitcher, type OrganizationSwitcherProps, PasskeyButton, type PasskeyButtonProps, PasskeyManager, type PasskeyManagerProps, PhoneOTP, type PhoneOTPProps, Protect, type ProtectProps, ResetPassword, type ResetPasswordProps, SignIn, type SignInPlan, type SignInProps, SignOutButton, type SignOutButtonProps, SignUp, type SignUpProps, SignedIn, type SignedInProps, SignedOut, type SignedOutProps, SocialButtons, type SocialButtonsProps, Spinner, type UseAccountResult, type UseAuthResult, type UseConsentResult, type UseEmailVerificationResult, type UseMFAResult, type UseOrganizationInvitationResult, type UseOrganizationResult, type UsePasskeysResult, type UsePasswordResetResult, type UsePublicConfigResult, type UseSignInResult, type UseSignOutResult, type UseSignUpResult, type UseUserResult, type UseWaitlistResult, UserButton, UserProfile, type UserProfileProps, type UserProfileSection, VerificationPending, type VerificationPendingProps, VerifyEmail, type VerifyEmailProps, Waitlist, type WaitlistProps, emailAutocomplete, resolveSignInMethods, useAccount, useAuth, useAuthClient, useAuthOwlContext, useConsent, useEmailVerification, useInvitationRecipientHint, useLocale, useMFA, useOrganization, useOrganizationInvitation, usePasskeys, usePasswordReset, usePublicConfig, useSession, useSignIn, useSignOut, useSignUp, useUser, useWaitlist };
927
+ /**
928
+ * Which sign-in method last worked in this browser, for this project.
929
+ *
930
+ * Two kinds of method need different treatment, and conflating them is the bug
931
+ * this shape exists to avoid:
932
+ *
933
+ * completes in page password, email-OTP verification, passkey - observable
934
+ * success, so it is recorded when it happens.
935
+ *
936
+ * leaves the page social, SSO, magic link - the page that would observe
937
+ * success is one the browser navigates away from. The
938
+ * attempt is PARKED and promoted only when a session
939
+ * actually appears, so bouncing off a consent screen does
940
+ * not teach the form that the provider worked.
941
+ *
942
+ * Everything is per project and per browser, and never keyed by an identifier -
943
+ * see the core module for why that line matters.
944
+ */
945
+ declare function useLastUsedSignInMethod(): LastUsedSignInMethod | null;
946
+
947
+ export { type Appearance, AuthLoaded, type AuthLoadedProps, AuthLoading, type AuthLoadingProps, AuthOwlBadge, type AuthOwlBadgeProps, AuthOwlBranding, type AuthOwlBrandingProps, AuthOwlProvider, type AuthOwlProviderProps, type AutofillHost, BackupCodesManager, type BackupCodesManagerProps, Bidi, type ConfigState, ConsentDocLinks, type ConsentDocLinksProps, ConsentGate, type ConsentGateProps, CreateOrganization, type CreateOrganizationProps, DEFAULT_BRAND_COLOR, EmailOtpForm, type EmailOtpFormProps, ForgotPassword, type ForgotPasswordProps, GoogleOneTap, type GoogleOneTapDismissReason, type GoogleOneTapError, type GoogleOneTapErrorCode, type GoogleOneTapProps, type GoogleOneTapSkipReason, InvitationPrompt, type InvitationPromptStatus, KNOWN_METHODS, type KnownMethod, MFAChallenge, type MFAChallengeProps, MFAEnrollment, type MFAEnrollmentProps, MFARequiredGate, type MFARequiredGateProps, MagicLinkForm, type MagicLinkFormProps, OrganizationList, type OrganizationListProps, OrganizationProfile, type OrganizationProfileProps, type OrganizationProfileSection, OrganizationSwitcher, type OrganizationSwitcherProps, PasskeyButton, type PasskeyButtonProps, PasskeyManager, type PasskeyManagerProps, PhoneOTP, type PhoneOTPProps, Protect, type ProtectProps, ResetPassword, type ResetPasswordProps, SignIn, type SignInPlan, type SignInProps, SignOutButton, type SignOutButtonProps, SignUp, type SignUpProps, SignedIn, type SignedInProps, SignedOut, type SignedOutProps, SocialButtons, type SocialButtonsProps, Spinner, type UseAccountResult, type UseAuthResult, type UseConsentResult, type UseEmailVerificationResult, type UseMFAResult, type UseOrganizationInvitationResult, type UseOrganizationResult, type UsePasskeysResult, type UsePasswordResetResult, type UsePublicConfigResult, type UseSignInResult, type UseSignOutResult, type UseSignUpResult, type UseUserResult, type UseWaitlistResult, UserButton, UserProfile, type UserProfileProps, type UserProfileSection, VerificationPending, type VerificationPendingProps, VerifyEmail, type VerifyEmailProps, Waitlist, type WaitlistProps, emailAutocomplete, resolveSignInMethods, useAccount, useAuth, useAuthClient, useAuthOwlContext, useConsent, useEmailVerification, useInvitationRecipientHint, useLastUsedSignInMethod, useLocale, useMFA, useOrganization, useOrganizationInvitation, usePasskeys, usePasswordReset, usePublicConfig, useSession, useSignIn, useSignOut, useSignUp, useUser, useWaitlist };
package/dist/index.js CHANGED
@@ -20,6 +20,7 @@ import {
20
20
  useConsent,
21
21
  useEmailVerification,
22
22
  useInvitationRecipientHint,
23
+ useLastUsedSignInMethod,
23
24
  useLocale,
24
25
  useMFA,
25
26
  useOrganization,
@@ -31,13 +32,14 @@ import {
31
32
  useServerError,
32
33
  useSession,
33
34
  useSignIn,
35
+ useSignInMethodRecorder,
34
36
  useSignOut,
35
37
  useSignUp,
36
38
  useSubmitAction,
37
39
  useT,
38
40
  useUser,
39
41
  useWaitlist
40
- } from "./chunk-PUJV7S6G.js";
42
+ } from "./chunk-E5ZOQHXY.js";
41
43
 
42
44
  // src/project-capabilities.ts
43
45
  import {
@@ -276,6 +278,7 @@ function SocialButtons({ providers, callbackURL }) {
276
278
  const t = useT();
277
279
  const toServerError = useServerError();
278
280
  const { signInSocial } = useSignIn();
281
+ const recordSignInMethod = useSignInMethodRecorder();
279
282
  const [pending, setPending] = React2.useState(null);
280
283
  const [error, setError] = React2.useState(null);
281
284
  React2.useEffect(() => {
@@ -308,6 +311,8 @@ function SocialButtons({ providers, callbackURL }) {
308
311
  if (res?.error) {
309
312
  setError(toServerError(res.error, t("social.error.startFailed")));
310
313
  setPending(null);
314
+ } else {
315
+ recordSignInMethod(`social:${provider}`, true);
311
316
  }
312
317
  } catch {
313
318
  setError(t("social.error.startFailed"));
@@ -1415,6 +1420,15 @@ function SignIn({
1415
1420
  const [challenge, setChallenge] = React13.useState(false);
1416
1421
  const mfaEnrolment = useConfirmedMfaPending("clear");
1417
1422
  const emailRef = React13.useRef(null);
1423
+ const recordSignInMethod = useSignInMethodRecorder();
1424
+ const onPasskeySignedIn = React13.useCallback(() => {
1425
+ recordSignInMethod("passkey");
1426
+ onSignedIn?.();
1427
+ }, [onSignedIn, recordSignInMethod]);
1428
+ const onPhoneOtpSignedIn = React13.useCallback(() => {
1429
+ recordSignInMethod("phone-otp");
1430
+ onSignedIn?.();
1431
+ }, [onSignedIn, recordSignInMethod]);
1418
1432
  const plan = resolveSignInMethods(
1419
1433
  config,
1420
1434
  typeof window === "undefined" ? void 0 : window.location.hostname
@@ -1422,7 +1436,7 @@ function SignIn({
1422
1436
  usePasskeyAutofill({
1423
1437
  enabled: credentialMode === "email" && plan.autofillHost !== null,
1424
1438
  redirectTo,
1425
- onSignedIn
1439
+ onSignedIn: onPasskeySignedIn
1426
1440
  });
1427
1441
  const badge = /* @__PURE__ */ jsx19(AuthOwlBadge, { force: showBadge });
1428
1442
  const branding = showBranding ? /* @__PURE__ */ jsx19(AuthOwlBranding, {}) : null;
@@ -1474,7 +1488,10 @@ function SignIn({
1474
1488
  error,
1475
1489
  onSubmit: () => void run(() => signInEmailOtp({ email, otp }), {
1476
1490
  failure: t("emailOtp.error.invalidCode"),
1477
- onSuccess: () => finishSignIn({ sessionStore, redirectTo, onSignedIn })
1491
+ onSuccess: () => {
1492
+ recordSignInMethod("email-otp");
1493
+ finishSignIn({ sessionStore, redirectTo, onSignedIn });
1494
+ }
1478
1495
  }),
1479
1496
  onChangeEmail: () => {
1480
1497
  setOtp("");
@@ -1502,7 +1519,7 @@ function SignIn({
1502
1519
  PhoneOTP,
1503
1520
  {
1504
1521
  redirectTo,
1505
- onSignedIn,
1522
+ onSignedIn: onPhoneOtpSignedIn,
1506
1523
  onBack: () => setView("sign-in"),
1507
1524
  onMfaPasswordRequired: () => {
1508
1525
  setView("sign-in");
@@ -1530,6 +1547,7 @@ function SignIn({
1530
1547
  failure: t("signIn.error.failed"),
1531
1548
  onSuccess: (res) => {
1532
1549
  const data = res.data;
1550
+ recordSignInMethod(credentialMode === "username" ? "username" : "password");
1533
1551
  if (data && "twoFactorRedirect" in data && data.twoFactorRedirect) {
1534
1552
  setChallenge(true);
1535
1553
  } else {
@@ -1542,7 +1560,10 @@ function SignIn({
1542
1560
  "magic",
1543
1561
  () => void run(() => authChallenge.run(AUTH_CHALLENGE_ACTIONS.passwordless, (options) => signInMagicLink({ email, callbackURL: redirectTo }, options)), {
1544
1562
  failure: t("magicLink.error.sendFailed"),
1545
- onSuccess: () => setView("magic-sent")
1563
+ onSuccess: () => {
1564
+ recordSignInMethod("magic-link", true);
1565
+ setView("magic-sent");
1566
+ }
1546
1567
  })
1547
1568
  );
1548
1569
  const doRequestOtp = () => start(
@@ -1559,6 +1580,7 @@ function SignIn({
1559
1580
  {
1560
1581
  failure: t("sso.error.startFailed"),
1561
1582
  mapError: (error2) => error2.status === 404 ? t("sso.error.notFound") : null,
1583
+ onSuccess: () => recordSignInMethod("sso", true),
1562
1584
  // SSO always redirects the browser to the IdP; keep the spinner up
1563
1585
  // through that navigation instead of flashing back to idle.
1564
1586
  keepPendingOnSuccess: true
@@ -1697,7 +1719,7 @@ function SignIn({
1697
1719
  ]
1698
1720
  }
1699
1721
  ),
1700
- plan.passkey && /* @__PURE__ */ jsx19(PasskeyButton, { redirectTo, onSignedIn }),
1722
+ plan.passkey && /* @__PURE__ */ jsx19(PasskeyButton, { redirectTo, onSignedIn: onPasskeySignedIn }),
1701
1723
  plan.phoneOtp && /* @__PURE__ */ jsx19(
1702
1724
  "button",
1703
1725
  {
@@ -4433,7 +4455,7 @@ var SECTION_KEYS2 = {
4433
4455
  invitations: "organization.profile.nav.invitations",
4434
4456
  danger: "organization.profile.nav.danger"
4435
4457
  };
4436
- var TeamsSection = React44.lazy(() => import("./TeamsSection-ZQDNMWV3.js"));
4458
+ var TeamsSection = React44.lazy(() => import("./TeamsSection-NV64O5I4.js"));
4437
4459
  function OrganizationProfile({ organizationId, defaultSection = "general", onDeleted, onLeft } = {}) {
4438
4460
  const t = useT();
4439
4461
  const toServerError = useServerError();
@@ -5000,6 +5022,14 @@ function normalizeDismissReason(reason) {
5000
5022
  }
5001
5023
  return "unknown";
5002
5024
  }
5025
+ var warnedMissingNonce = /* @__PURE__ */ new Set();
5026
+ function warnOneTapWithoutNonce(clientId) {
5027
+ if (warnedMissingNonce.has(clientId)) return;
5028
+ warnedMissingNonce.add(clientId);
5029
+ console.warn(
5030
+ "[AuthOwl] <GoogleOneTap/> is running without a `nonce`. Google\u2019s ID token is then not bound to a value chosen for this prompt. Generate a fresh random value per prompt and pass it as `nonce`; AuthOwl forwards it to Google and verifies the match. The direct browser exchange does not keep separate one-time server state, so do not treat this prop by itself as replay protection. (This warning is dev-only.)"
5031
+ );
5032
+ }
5003
5033
  function GoogleOneTap({
5004
5034
  disabled = false,
5005
5035
  nonce,
@@ -5023,6 +5053,11 @@ function GoogleOneTap({
5023
5053
  callbacks.current = { onSignedIn, onSkipped, onDismissed, onError };
5024
5054
  const googleEnabled = config?.socialProviders.includes("google") === true;
5025
5055
  const clientId = config?.socialProviderClientIds?.google;
5056
+ React47.useEffect(() => {
5057
+ if (process.env.NODE_ENV === "production") return;
5058
+ if (disabled || !googleEnabled || !clientId || nonce) return;
5059
+ warnOneTapWithoutNonce(clientId);
5060
+ }, [clientId, disabled, googleEnabled, nonce]);
5026
5061
  React47.useEffect(() => {
5027
5062
  if (configLoading || !sessionLoaded) return;
5028
5063
  if (disabled) {
@@ -5198,6 +5233,7 @@ export {
5198
5233
  useConsent,
5199
5234
  useEmailVerification,
5200
5235
  useInvitationRecipientHint,
5236
+ useLastUsedSignInMethod,
5201
5237
  useLocale,
5202
5238
  useMFA,
5203
5239
  useOrganization,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@authowl/react",
3
- "version": "0.22.0",
3
+ "version": "0.23.0",
4
4
  "description": "React provider, hooks, and drop-in components for AuthOwl, the multi-tenant auth SaaS.",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
@@ -47,7 +47,7 @@
47
47
  "LICENSE"
48
48
  ],
49
49
  "dependencies": {
50
- "@authowl/core": "0.19.0"
50
+ "@authowl/core": "0.20.0"
51
51
  },
52
52
  "peerDependencies": {
53
53
  "react": ">=18",