跳转到主要内容
Google One-Tap 就是那个登出状态访问首页时,右上角弹出来的小卡片——当前浏览器 有 Google session,一点就登。没有跳转,不用填表。vibestrap 用 Better Auth 的 One-Tap 插件加一个 30 行的客户端组件(src/components/auth/one-tap.tsx)就接好了。 它用的是 FedCM, Google 的新浏览器 API,不依赖第三方 cookie——所以 Chrome 砍掉三方 cookie 之后 它依然能用。

前置条件

  • Google OAuth 已经配好。One-Tap 复用同一个 OAuth client,所以 GOOGLE_CLIENT_ID 必须已存在。
  • 一个 NEXT_PUBLIC_GOOGLE_CLIENT_ID 环境变量——公开版的同一个 ID。
  • 生产环境必须 HTTPS。(本地 localhost 走 HTTP 是允许的。)

一步步配置

  1. 把 client ID 镜像到 public env。Better Auth One-Tap 插件在客户端也要这个 ID, 写进 .env.local
    NEXT_PUBLIC_GOOGLE_CLIENT_ID=1234567890-abc...apps.googleusercontent.com
    
    GOOGLE_CLIENT_ID 是同一个值。暴露是安全的,本来就是公开标识符。
  2. 打开功能开关src/config/site.ts
    features: { enableOneTap: true, /* ... */ }
    
  3. 确认组件已挂载。它已经在 src/app/layout.tsx(或 locale layout)的 NextIntlClientProvider 里挂着,全站都能跑。组件本身不渲染任何东西——只是 找个空闲时机调 authClient.oneTap()
  4. 重启 pnpm dev。public 环境变量是 build 或 dev 启动时打进去的。

它实际怎么跑的

src/components/auth/one-tap.tsx 是个 30 行的 'use client' 组件:
const { data: session, isPending } = useSession();
useEffect(() => {
  if (isPending || session) return;
  authClient.oneTap?.().catch(() => {});
}, [isPending, session]);
用户已经登录,啥也不干。没登录,就让 Better Auth 插件去喊 Google。错误一律 吞掉——One-Tap 失败的所有原因(浏览器不支持、用户关掉了、没 Google session) 都是用户层面没法操作的。 /login 上的”用 Google 登录”按钮和 One-Tap 弹窗互不冲突——两个可以同时激活。 One-Tap 只是让首页更轻便。 对应的客户端配置在 src/lib/auth-client.ts
oneTapClient({
  clientId: googleClientId,
  autoSelect: false,         // 必须用户点 —— 不自动选
  cancelOnTapOutside: true,  // 可关闭
  context: 'signin',
})
autoSelect: false 是有意为之——不点就直接给人登录是典型的 dark pattern, Google 在 accounts.google.com 那边也会扣你分。别开。

验证是否生效

  1. 确保另一个标签页里有 Google 账号已登录,且当前没登录 vibestrap 站点。
  2. 用无痕窗口(带着那个 Google session)打开首页。
  3. 一两秒内,One-Tap 卡片应该从右上角滑出。
  4. 点一下——已登录,没跳转。
如果什么都没出,打开 DevTools → Network → 过滤 accounts.google.com 看 FedCM 请求有没有发出去。

常见坑

  • 本地能用、生产没反应。八成是托管平台(Vercel、Netlify 之类)没配 NEXT_PUBLIC_GOOGLE_CLIENT_ID。public 环境变量是 build 时打进去的——配好 之后必须重新部署。
  • 必须 HTTPS。生产环境必须 HTTPS。localhost 是浏览器唯一的 HTTP 例外。
  • Brave 或 Safari 上没反应。FedCM 在 Brave 里被 Shields 拦着,Safari 也才 刚开始支持。别把 One-Tap 当成唯一入口——保留常规按钮。
  • 用户有多个 Google 账号。不会直接一键登录,会出账号选择器。同一个插件, Google 那边的 UI 不一样而已——你这边不用改。
  • 卡片出来但点了没反应。多半是 OAuth client 的 authorized JavaScript origins 没加当前 host。去 Google Cloud Console,OAuth 2.0 Client ID → Authorized JavaScript origins 把当前域名加上。

官方文档