diff --git a/.changeset/witty-carpets-wait.md b/.changeset/witty-carpets-wait.md new file mode 100644 index 00000000000..31de091758d --- /dev/null +++ b/.changeset/witty-carpets-wait.md @@ -0,0 +1,5 @@ +--- +"@clerk/clerk-js": patch +"@clerk/shared": patch +--- +WIP ignore diff --git a/packages/clerk-js/src/ui/components/GoogleOneTap/one-tap-start.tsx b/packages/clerk-js/src/ui/components/GoogleOneTap/one-tap-start.tsx index ce4f5a97c2b..418bfbd1a88 100644 --- a/packages/clerk-js/src/ui/components/GoogleOneTap/one-tap-start.tsx +++ b/packages/clerk-js/src/ui/components/GoogleOneTap/one-tap-start.tsx @@ -66,9 +66,10 @@ function OneTapStartInternal(): JSX.Element | null { useEffect(() => { if (initializedGoogle && !user?.id && !isPromptedRef.current) { initializedGoogle.accounts.id.prompt(notification => { - // Close the modal, when the user clicks outside the prompt or cancels - if (notification.getMomentType() === 'skipped') { - // Unmounts the component will cause the useEffect cleanup function from below to be called + // Close Google One Tap when user dismisses or skips the prompt + // Using methods compatible with both FedCM and legacy modes + // https://developers.google.com/identity/gsi/web/guides/fedcm-migration + if (notification.isSkippedMoment?.() || notification.isDismissedMoment?.()) { clerk.closeGoogleOneTap(); } }); diff --git a/packages/clerk-js/src/utils/one-tap.ts b/packages/clerk-js/src/utils/one-tap.ts index 4b56a2b083a..5acedaaaa7b 100644 --- a/packages/clerk-js/src/utils/one-tap.ts +++ b/packages/clerk-js/src/utils/one-tap.ts @@ -15,13 +15,38 @@ interface InitializeProps { use_fedcm_for_prompt?: boolean; } +// PromptMomentNotification methods +// See: https://developers.google.com/identity/gsi/web/reference/js-reference#PromptMomentNotification interface PromptMomentNotification { - getMomentType: () => 'display' | 'skipped' | 'dismissed'; + // Moment type detection + getMomentType?: () => 'display' | 'skipped' | 'dismissed'; + + // Display moment methods - NOT supported when FedCM is enabled + isDisplayMoment?: () => boolean; + isDisplayed?: () => boolean; + isNotDisplayed?: () => boolean; + getNotDisplayedReason?: () => + | 'browser_not_supported' + | 'invalid_client' + | 'missing_client_id' + | 'opt_out_or_no_session' + | 'secure_http_required' + | 'suppressed_by_user' + | 'unregistered_origin' + | 'unknown_reason'; + + // Skipped moment methods - partially supported in FedCM (no user_cancel reason) + isSkippedMoment?: () => boolean; + getSkippedReason?: () => 'auto_cancel' | 'user_cancel' | 'tap_outside' | 'issuing_failed'; + + // Dismissed moment methods - fully supported in FedCM + isDismissedMoment?: () => boolean; + getDismissedReason?: () => 'credential_returned' | 'cancel_called' | 'flow_restarted'; } interface OneTapMethods { initialize: (params: InitializeProps) => void; - prompt: (promptListener: (promptMomentNotification: PromptMomentNotification) => void) => void; + prompt: (promptListener?: (notification: PromptMomentNotification) => void) => void; cancel: () => void; } diff --git a/packages/shared/src/types/clerk.ts b/packages/shared/src/types/clerk.ts index e18204bed10..7bdb9e55a3e 100644 --- a/packages/shared/src/types/clerk.ts +++ b/packages/shared/src/types/clerk.ts @@ -1518,10 +1518,21 @@ export type GoogleOneTapProps = GoogleOneTapRedirectUrlProps & { */ itpSupport?: boolean; /** - * FedCM enables more private sign-in flows without requiring the use of third-party cookies. - * The browser controls user settings, displays user prompts, and only contacts an Identity Provider such as Google after explicit user consent is given. - * Backwards compatible with browsers that still support third-party cookies. + * FedCM enables more private sign-in flows without requiring third-party cookies. + * The browser controls user settings, displays user prompts, and only contacts + * an Identity Provider such as Google after explicit user consent. * + * Requirements: + * - Chrome 117+ or Edge 117+ (falls back to legacy mode in older browsers) + * - HTTPS in production + * - Proper Content Security Policy (CSP) configuration + * + * Troubleshooting: + * - If you see "NetworkError: Failed to execute 'get'" or CORS errors, check your CSP headers + * - Add `connect-src https://accounts.google.com` to your CSP policy + * - Set to `false` to temporarily use legacy mode while debugging + * + * @see https://developers.google.com/identity/gsi/web/guides/fedcm-migration * @default true */ fedCmSupport?: boolean;