in packages/better-auth/src/plugins/one-tap/client.ts [87:187]
oneTap: async (
opts?: GoogleOneTapActionOptions,
fetchOptions?: BetterFetchOption,
) => {
if (isRequestInProgress) {
console.warn(
"A Google One Tap request is already in progress. Please wait.",
);
return;
}
isRequestInProgress = true;
try {
if (typeof window === "undefined" || !window.document) {
console.warn(
"Google One Tap is only available in browser environments",
);
return;
}
const { autoSelect, cancelOnTapOutside, context } = opts ?? {};
const contextValue = context ?? options.context ?? "signin";
await loadGoogleScript();
await new Promise<void>((resolve, reject) => {
let isResolved = false;
const baseDelay = options.promptOptions?.baseDelay ?? 1000;
const maxAttempts = options.promptOptions?.maxAttempts ?? 5;
window.google?.accounts.id.initialize({
client_id: options.clientId,
callback: async (response: { credential: string }) => {
isResolved = true;
try {
await $fetch("/one-tap/callback", {
method: "POST",
body: { idToken: response.credential },
...opts?.fetchOptions,
...fetchOptions,
});
if (
(!opts?.fetchOptions && !fetchOptions) ||
opts?.callbackURL
) {
window.location.href = opts?.callbackURL ?? "/";
}
resolve();
} catch (error) {
console.error("Error during One Tap callback:", error);
reject(error);
}
},
auto_select: autoSelect,
cancel_on_tap_outside: cancelOnTapOutside,
context: contextValue,
...options.additionalOptions,
});
const handlePrompt = (attempt: number) => {
if (isResolved) return;
window.google?.accounts.id.prompt((notification: any) => {
if (isResolved) return;
if (
notification.isDismissedMoment &&
notification.isDismissedMoment()
) {
if (attempt < maxAttempts) {
const delay = Math.pow(2, attempt) * baseDelay;
setTimeout(() => handlePrompt(attempt + 1), delay);
} else {
opts?.onPromptNotification?.(notification);
}
} else if (
notification.isSkippedMoment &&
notification.isSkippedMoment()
) {
if (attempt < maxAttempts) {
const delay = Math.pow(2, attempt) * baseDelay;
setTimeout(() => handlePrompt(attempt + 1), delay);
} else {
opts?.onPromptNotification?.(notification);
}
}
});
};
handlePrompt(0);
});
} catch (error) {
console.error("Error during Google One Tap flow:", error);
throw error;
} finally {
isRequestInProgress = false;
}
},