> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vibestrap.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Google One-Tap

> 对当前有 Google session 的用户实现一键登录——已经通过 Better Auth 的 One-Tap 插件接好。

Google One-Tap 就是那个登出状态访问首页时，右上角弹出来的小卡片——当前浏览器
有 Google session，一点就登。没有跳转，不用填表。Vibestrap 用 Better Auth 的
One-Tap 插件加一个 30 行的客户端组件（`src/components/auth/one-tap.tsx`）就接好了。

它用的是 [FedCM](https://developers.google.com/privacy-sandbox/3pcd/fedcm)，
Google 的新浏览器 API，不依赖第三方 cookie——所以 Chrome 砍掉三方 cookie 之后
它依然能用。

## 前置条件

* [Google OAuth](/zh/auth/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`：

   ```bash theme={null}
   NEXT_PUBLIC_GOOGLE_CLIENT_ID=1234567890-abc...apps.googleusercontent.com
   ```

   和 `GOOGLE_CLIENT_ID` 是同一个值。暴露是安全的，本来就是公开标识符。

2. **打开功能开关**。`src/config/site.ts`：

   ```ts theme={null}
   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'` 组件：

```tsx theme={null}
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`：

```ts theme={null}
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 把当前域名加上。

## 官方文档

* One-Tap 功能总览 — [developers.google.com/identity/gsi/web/guides/features](https://developers.google.com/identity/gsi/web/guides/features)
* FedCM 迁移指南 — [developers.google.com/identity/gsi/web/guides/fedcm-migration](https://developers.google.com/identity/gsi/web/guides/fedcm-migration)
* 显示 One-Tap 提示 — [developers.google.com/identity/gsi/web/guides/display-one-tap](https://developers.google.com/identity/gsi/web/guides/display-one-tap)
* Better Auth One-Tap 插件 — [better-auth.com/docs/plugins/one-tap](https://www.better-auth.com/docs/plugins/one-tap)
