# Google (/docs/authentication/google)

Google 提供者的设置和使用。



<Steps>
  <Step>
    ### 获取 Google 凭据 [#获取-google-凭据]

    要将 Google 用作社交身份提供者，你需要获取 Google 凭据。你可以在 [Google Cloud Console](https://console.cloud.google.com/apis/dashboard) 中创建一个新项目来获取这些凭据。

    在 Google Cloud Console > 凭据 > 授权重定向 URI 中，请确保将重定向 URL 设置为 `http://localhost:3000/api/auth/callback/google` 用于本地开发。生产环境中，请将重定向 URL 设置为你的应用程序域名，例如 `https://example.com/api/auth/callback/google`。如果修改了认证路由的基本路径，请相应更新重定向 URL。

    <Callout type="info">
      **创建你的 Google OAuth 凭据**

      如果你尚未创建 OAuth 凭据，请按照以下逐步说明操作：

      1. 打开 **Google Cloud Console** → **API 与服务** → **凭据**
      2. 点击 **创建凭据** → **OAuth 客户端 ID**
      3. 选择 **Web 应用程序**
      4. 添加你的重定向 URI：
         * `http://localhost:3000/api/auth/callback/google`（用于本地开发）
         * `https://your-domain.com/api/auth/callback/google`（用于生产环境）
      5. 将 **客户端 ID** 和 **客户端密钥** 复制到你的环境变量中

      这些步骤可以避免 `redirect_uri_mismatch` 等常见问题。
    </Callout>
  </Step>

  <Step>
    ### 配置提供者 [#配置提供者]

    要配置该提供者，需要将 `clientId` 和 `clientSecret` 传递给 `socialProviders.google`。

    ```ts title="auth.ts"
    import { betterAuth } from "better-auth"

    export const auth = betterAuth({
        baseURL: process.env.BETTER_AUTH_URL, // [!code highlight]
        socialProviders: {
            google: { // [!code highlight]
                clientId: process.env.GOOGLE_CLIENT_ID as string, // [!code highlight]
                clientSecret: process.env.GOOGLE_CLIENT_SECRET as string, // [!code highlight]
            }, // [!code highlight]
        },
    })
    ```

    <Callout type="warn">
      **重要：设置你的基础 URL**

      你必须配置 `baseURL` 以避免 `redirect_uri_mismatch` 错误。Better Auth 使用它来构造发送给 Google 的 OAuth 回调 URL。

      **选项 1：使用环境变量（推荐）**

      在 `.env` 文件中添加：

      ```dotenv
      BETTER_AUTH_URL=https://your-domain.com
      ```

      **选项 2：显式配置**

      如上所示，直接将 `baseURL` 传递到认证配置中。
      如果不设置，回调 URL 可能会默认为 `localhost`，导致生产环境中的 Google OAuth 失败。
    </Callout>
  </Step>
</Steps>

## 使用方法 [#使用方法]

### 使用 Google 登录 [#使用-google-登录]

要使用 Google 登录，可以使用客户端提供的 `signIn.social` 函数。`signIn` 函数接收一个包含以下属性的对象：

* `provider`：要使用的提供者，应设置为 `google`。

```ts title="auth-client.ts"  /
import { createAuthClient } from "better-auth/client";
const authClient = createAuthClient();

const signIn = async () => {
  const data = await authClient.signIn.social({
    provider: "google",
  });
};
```

### 使用 ID Token 登录 Google [#使用-id-token-登录-google]

要使用 Google 的 ID Token 登录，可以通过 `signIn.social` 函数传递 ID Token。

当你已经在客户端拥有 Google 的 ID Token，并希望在服务器端使用它登录时，这非常有用。

<Callout>
  如果提供了 ID Token，则不会发生重定向，用户将直接登录。
</Callout>

```ts title="auth-client.ts"
const data = await authClient.signIn.social({
    provider: "google",
    idToken: {
        token: // Google ID Token,
        accessToken: // Google 访问令牌
    }
})
```

<Callout>
  如果你想使用 Google 的一键登录，可以参考 [一键登录插件](/docs/plugins/one-tap) 指南。
</Callout>

### 跨平台登录（Web、iOS、Android） [#跨平台登录webiosandroid]

Google 会在同一个 Google Cloud 项目中为每个平台分别发放一个 Client ID。将数组传递给 `clientId`，即可接受来自任一平台的 ID Token。有关共享提供者选项语义，请参阅 [clientId](/docs/concepts/oauth#clientid)。

```ts title="auth.ts"
socialProviders: {
    google: {
        clientId: [ // [!code highlight]
            process.env.GOOGLE_WEB_CLIENT_ID as string, // [!code highlight]
            process.env.GOOGLE_IOS_CLIENT_ID as string, // [!code highlight]
            process.env.GOOGLE_ANDROID_CLIENT_ID as string, // [!code highlight]
        ], // [!code highlight]
        clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
    },
}
```

你的移动应用使用原生 Google SDK 登录，并转发 ID Token：

```ts title="Mobile app"
const { idToken, accessToken } = await GoogleSignin.signIn();

await authClient.signIn.social({
    provider: "google",
    idToken: { token: idToken, accessToken },
});
```

<Callout type="info">
  数组仅会扩展 ID Token 的受众验证。授权码流程仍然使用第一个条目，并与单个 `clientSecret` 和 `redirectURI` 配对，因此在同一个提供者块内，这些值不能按平台分别变化。
</Callout>

### 将登录限制为 Google Workspace [#将登录限制为-google-workspace]

在 Google 提供者上设置 `hd`，以要求经过验证的 Google Workspace 主机域名声明。Google 也会将此值作为账户选择提示传递，但 Better Auth 会在 Google 签署响应后强制检查返回的 ID token/资料声明。

```ts title="auth.ts"
socialProviders: {
    google: {
        clientId: process.env.GOOGLE_CLIENT_ID as string,
        clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
        hd: "company.com", // [!code highlight]
    },
}
```

将 `hd: "*"` 设置为允许任意 Google Workspace 主机域名。只要配置了 `hd`，没有 `hd` 声明的令牌都会被拒绝。

<Callout type="warn">
  自定义的 `getUserInfo` 回调会替换 Google 内置的回调路径 `hd`
  检查。请从受信任的提供者响应中验证该声明，并在声明缺失或不匹配时返回 `null`。
  直接使用 ID token 登录会遵循提供者的 ID token 验证路径，而 Google One Tap
  会单独强制执行已配置的 `hd`。
</Callout>

### 始终要求选择账户 [#始终要求选择账户]

如果你希望始终要求用户选择账户，可以在提供者中传递 `prompt` 参数，并将其设置为 `select_account`。

```ts
socialProviders: {
    google: {
        prompt: "select_account", // [!code highlight]
        clientId: process.env.GOOGLE_CLIENT_ID as string,
        clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
    },
}
```

### 请求额外的 Google 权限 [#请求额外的-google-权限]

如果你的应用需要在用户注册后访问额外的 Google 权限（例如 Google Drive、Gmail 或其他 Google 服务），你可以使用相同的 Google 提供者，通过 `linkSocial` 方法请求这些权限。

```tsx title="auth-client.ts"
const requestGoogleDriveAccess = async () => {
  await authClient.linkSocial({
    provider: "google",
    scopes: ["https://www.googleapis.com/auth/drive.file"],
  });
};

// React 组件中的示例用法
return (
  <button onClick={requestGoogleDriveAccess}>
    添加 Google Drive 权限
  </button>
);
```

这将触发新的 OAuth 流程，请求额外权限。完成后，你的账户将在数据库中获得新的权限，访问令牌将允许你访问请求的 Google API。

<Callout>
  确保你使用的是 Better Auth 版本 1.2.7 或更高版本，以避免在请求同一提供者额外权限时出现“社交账户已绑定”错误。
</Callout>

### 禁用增量授权 [#禁用增量授权]

默认情况下，Better Auth 会向 Google 的授权端点发送 `include_granted_scopes=true`，因此新签发的访问令牌除了涵盖当前流程请求的作用域外，还会涵盖之前授权中的作用域。如果每个 OAuth 流程都应该只请求其自身的作用域，请设置 `includeGrantedScopes: false`。

```ts
socialProviders: {
    google: {
        clientId: process.env.GOOGLE_CLIENT_ID as string,
        clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
        includeGrantedScopes: false, // [!code highlight]
    },
}
```

调用时的 `additionalParams.include_granted_scopes` 仍然遵循通用的 OAuth 参数优先级规则，并且可以针对单个流程覆盖此提供者默认值。

有关底层参数行为，请参阅 Google 的[增量授权](https://developers.google.com/identity/protocols/oauth2/web-server#incrementalAuth)文档。

### 始终获取刷新令牌 [#始终获取刷新令牌]

Google 仅在用户首次同意授权你的应用时发放刷新令牌。
如果用户已经授权过，后续 OAuth 流程只会返回访问令牌，不会返回刷新令牌。

要始终获取刷新令牌，你可以在提供者选项中设置 `accessType` 为 `offline`，并将 `prompt` 设置为 `select_account consent`。

```ts
socialProviders: {
    google: {
        clientId: process.env.GOOGLE_CLIENT_ID as string,
        clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
        accessType: "offline", // [!code highlight]
        prompt: "select_account consent", // [!code highlight]
    },
}
```

<Callout>
  **撤销访问权限：** 如果你想为已经授权你的应用的用户获取新的刷新令牌，用户必须先在其 Google 账户设置中撤销你的应用访问权限，然后重新授权。
</Callout>

### 限制为 Google Workspace 域名 [#限制为-google-workspace-域名]

要将登录限制为特定 Google Workspace 域名中的账户，请在调用时传递
`hd` 参数。这与 Google 的 `hd` 授权 URL 参数相对应，并且会针对每个请求解析：

```ts
await authClient.signIn.social({
  provider: "google",
  additionalParams: { hd: "example.com" },
});
```

如果该限制对你的应用是静态的，也可以在提供者配置级别设置 `hd`。

