一键登录

用于 Better Auth 的一键登录插件

一键登录插件允许用户通过 Google 的 One Tap API 只需轻点一次即可登录。该插件为您提供一个简单的方式将 One Tap 集成到您的应用中,负责处理客户端和服务器端的逻辑。

安装

添加服务器插件

将一键登录插件添加到您的认证配置中:

auth.ts
import { betterAuth } from "better-auth";
import { oneTap } from "better-auth/plugins"; 

export const auth = betterAuth({
    plugins: [
        oneTap(), // 添加 One Tap 服务器插件
    ]
});

添加客户端插件

添加客户端插件并指定用户登录后或需要额外验证(如两步验证)时应重定向到的位置。

import { createAuthClient } from "better-auth/client";
import { oneTapClient } from "better-auth/client/plugins"; 

export const authClient = createAuthClient({
  plugins: [
    oneTapClient({
      clientId: "YOUR_CLIENT_ID",
      // 可选的客户端配置:
      autoSelect: false,
      cancelOnTapOutside: true,
      context: "signin",
      additionalOptions: {
        // 传递给 Google 初始化方法的额外选项
      },
      // 配置提示行为和指数退避策略:
      promptOptions: {
        baseDelay: 1000,   // 基础延迟(毫秒)(默认:1000)
        maxAttempts: 5     // 触发 onPromptNotification 之前的最大尝试次数(默认:5)
      }
    })
  ]
});

用法

提示模式(默认)

要显示 One Tap 弹窗,只需在您的认证客户端调用 oneTap 方法:

import { authClient } from "@/lib/auth-client";

await authClient.oneTap(); 

按钮模式

如果想展示“使用 Google 登录”按钮而不是自动弹出提示,可使用 button 选项:

// 在您的组件内
<div id="google-signin-button"></div>

// 使用按钮配置调用 oneTap
await authClient.oneTap({
  button: {
    container: "#google-signin-button", // CSS 选择器或 HTMLElement
    config: {
      theme: "outline",
      size: "large",
      type: "standard",
      text: "signin_with"
    }
  }
});
import { useEffect, useRef } from "react";

function SignInButton() {
  const buttonRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (buttonRef.current) {
      authClient.oneTap({
        button: {
          container: buttonRef.current,
          config: {
            theme: "filled_blue",
            size: "large"
          }
        }
      });
    }
  }, []);

  return <div ref={buttonRef}></div>;
}

自定义重定向行为

默认情况下,登录成功后插件会硬跳转到 /。您可以按以下方法自定义该行为:

避免硬跳转

传递带有 onSuccess 回调的 fetchOptions,用于在不重新加载页面的情况下处理登录响应:

import { authClient } from "@/lib/auth-client";

await authClient.oneTap({
  fetchOptions: {
    onSuccess: () => {
      // 例如,使用路由器导航而不完整重载页面:
      router.push("/dashboard");
    }
  }
});

指定自定义回调 URL

如果登录后想进行硬跳转至不同页面,使用 callbackURL 选项:

import { authClient } from "@/lib/auth-client";

await authClient.oneTap({
  callbackURL: "/dashboard"
});

使用指数退避处理提示被关闭

若用户关闭或跳过提示,插件将根据您配置的 promptOptions 使用指数退避重试显示 One Tap 提示。

如果达到最大尝试次数仍未成功登录,您可以使用 onPromptNotification 回调得到通知,允许您渲染替代的用户界面(例如传统的 Google 登录按钮),以便用户手动重新开始流程:

import { authClient } from "@/lib/auth-client";

await authClient.oneTap({
  onPromptNotification: (notification) => {
    console.warn("提示已被关闭或跳过。请考虑显示替代的登录选项。", notification);
    // 在这里渲染您的替代 UI
  }
});

客户端选项

  • clientId: 您的 Google One Tap API 客户端 ID。
  • autoSelect: 如果用户已登录,是否自动选择帐户。默认值为 false。
  • cancelOnTapOutside: 当用户点击弹窗外部时,是否取消 One Tap 弹窗。启用 FedCM 时此选项可能无效,因为浏览器会管理关闭行为。默认值为 true。
  • uxMode: Google One Tap 流程使用的模式,可选 "popup"(弹窗)或 "redirect"(重定向)。默认值为 "popup"
  • context: One Tap API 所使用的上下文,可选 "signin""signup""use"。默认值为 "signin"
  • additionalOptions: 传递给 Google 初始化方法的额外选项,详见 Google Identity Services 文档
  • promptOptions: 用于配置提示行为和指数退避策略:
    • baseDelay: 重试的基础延迟,单位毫秒。默认值为 1000。
    • maxAttempts: 触发 onPromptNotification 回调前的提示尝试最大次数。默认值为 5。
    • fedCM: 启用后在登出时调用 navigator.credentials.preventSilentAccess() 清除浏览器的 FedCM 凭据状态。FedCM 由 Google Identity Services 库管理,无法禁用。默认值为 true。

按钮模式选项

使用按钮模式时,向 oneTap 方法传递 button 对象,包含以下属性:

  • container: 必填,按钮要渲染到的 HTML 元素或 CSS 选择器。
  • config: 可选,按钮配置选项:
    • type: 按钮类型 — "standard"(默认)或 "icon"(仅图标)
    • theme: 按钮主题 — "outline"(默认)、"filled_blue"、或 "filled_black"
    • size: 按钮尺寸 — "large"(默认)、"medium""small"
    • text: 按钮文字 — "signin_with"(默认)、"signup_with""continue_with"、或 "signin"
    • shape: 按钮形状 — "rectangular"(默认)、"pill""circle"、或 "square"
    • logo_alignment: Google 标志对齐方式 — "left"(默认)或 "center"(仅限标准按钮)
    • width: 按钮最小宽度(像素),最大 400
    • locale: 以指定语言代码显示按钮(例如 "zh_CN"

服务器端选项

  • disableSignUp: 禁用注册选项,仅允许已有用户登录。默认值为 false。
  • clientId: 如果您的社交提供商配置中未提供客户端 ID,可以在这里传入。

授权的 JavaScript 来源

请确保您已在 Google Cloud 控制台中为您的客户端 ID 配置了授权的 JavaScript 来源(例如 http://localhost:3000,https://example.com)。这是 Google One Tap API 的必需步骤,如未正确设置来源,该功能将无法正常工作。