One Tap
Open Google's One Tap prompt from copied shadcn authentication views.
The One Tap UI plugin opens Better Auth's native One Tap flow when an authentication view mounts. It refreshes the session after success, follows the configured redirectTo, and continues into the two-factor view when the server requests a second factor.
Keep Google in socialProviders as a visible fallback. One Tap is a passive prompt and browsers may decide not to show it.
Setup
Configure the Better Auth server plugin
Add Better Auth's One Tap plugin with the OAuth client ID from your Google Cloud project:
import { betterAuth } from "better-auth"
import { oneTap } from "better-auth/plugins"
export const auth = betterAuth({
// ...
plugins: [
oneTap({
clientId: process.env.GOOGLE_CLIENT_ID as string
})
]
})Configure the Better Auth client plugin
Use the same client ID in the browser client:
import { createAuthClient } from "better-auth/react"
import { oneTapClient } from "better-auth/client/plugins"
export const authClient = createAuthClient({
plugins: [
oneTapClient({
clientId: import.meta.env.VITE_GOOGLE_CLIENT_ID,
promptOptions: {
baseDelay: 1_000,
maxAttempts: 3
}
})
]
})Update the copied authentication views
Install the registry item so the sign-in and sign-up surfaces include the headless prompt slot:
bun x shadcn@latest registry add @better-auth-ui=https://better-auth-ui.com/r/{style}/{name}.jsonbunx --bun shadcn@latest add @better-auth-ui/one-tapRegister the Better Auth UI plugin
Pass oneTapPlugin() to your copied <AuthProvider>. The prompt opens on sign-in by default.
import { oneTapPlugin } from "@better-auth-ui/react/plugins"
<AuthProvider
authClient={authClient}
navigate={navigate}
plugins={[
oneTapPlugin()
]}
socialProviders={["google"]}
>
{children}
</AuthProvider>Add your authorized origins
Add every application origin that can render the prompt to the OAuth client's Authorized JavaScript origins in Google Cloud. Include the exact protocol, host, and development port, such as http://localhost:3000.
Show One Tap on sign-up
Pass both auth views when you also want the prompt on sign-up:
oneTapPlugin({
views: ["signIn", "signUp"]
})The plugin sends the matching signin or signup context to Better Auth. This preserves server-side sign-up controls and redirects.
Prompt options
Better Auth's prompt settings can be passed directly to the UI plugin:
oneTapPlugin({
autoSelect: true,
cancelOnTapOutside: false,
onPromptNotification: (notification) => {
// Track when Google skips or dismisses the prompt.
}
})Prop
Type
Better Auth 1.7
The integration supports the stricter One Tap responses in Better Auth 1.7. Errors such as EMAIL_NOT_VERIFIED are sent through the normal authentication error handler instead of being hidden.
Last login method
Better Auth's last-login-method plugin does not classify the One Tap callback as Google by default. If you use its badge, resolve the callback explicitly:
lastLoginMethod({
customResolveMethod: (context) =>
context.path === "/one-tap/callback" ? "google" : null
})Last updated on