# Cognito (/docs/authentication/cognito)

Amazon Cognito 提供者的设置与使用。



<Steps>
  <Step>
    ### 获取 Cognito 凭证 [#获取-cognito-凭证]

    要与 Cognito 集成，需要在 [Amazon Cognito 控制台](https://console.aws.amazon.com/cognito/) 中设置 **用户池** 和 **应用客户端**。

    按照以下步骤操作：

    1. 进入 **Cognito 控制台**，创建一个 **用户池**。
    2. 在 **应用客户端** 中，创建一个新的 **应用客户端**（如果启用，则记录客户端 ID 和客户端密钥）。
    3. 进入 **域** 并设置一个 Cognito 托管 UI 域（例如：`your-app.auth.us-east-1.amazoncognito.com`）。
    4. 在 **应用客户端设置** 中启用：
       * 允许的 OAuth 流程：`授权码授予`
       * 允许的 OAuth 范围：`openid`、`profile`、`email`
    5. 添加回调 URL（例如：`http://localhost:3000/api/auth/callback/cognito`）。

    <Callout type="info">
      * **用户池是使用 Cognito 身份验证所必需的**。
      * 确保回调 URL 与在 Cognito 中配置的完全一致。
    </Callout>
  </Step>

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

    在 `auth` 实例的 `socialProviders` 键中配置 `cognito` 键。

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

    export const auth = betterAuth({
      socialProviders: {
        cognito: {
          clientId: process.env.COGNITO_CLIENT_ID as string, // [!code highlight]
          clientSecret: process.env.COGNITO_CLIENT_SECRET as string, // [!code highlight]
          domain: process.env.COGNITO_DOMAIN as string, // 例如 "your-app.auth.us-east-1.amazoncognito.com" [!code highlight]
          region: process.env.COGNITO_REGION as string, // 例如 "us-east-1" [!code highlight]
          userPoolId: process.env.COGNITO_USERPOOL_ID as string, // [!code highlight]
          identityProvider: "Google", // 可选：跳过托管 UI 选择器 [!code highlight]
        },
      },
    })
    ```
  </Step>

  <Step>
    ### 使用 Cognito 登录 [#使用-cognito-登录]

    要使用 Cognito 登录，请从客户端使用 `signIn.social` 函数。

    ```ts title="auth-client.ts"
    import { createAuthClient } from "better-auth/client"

    const authClient = createAuthClient()

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

    要针对每次调用覆盖预选的身份提供者（例如，渲染一个绕过 Cognito 选择器的“使用 Okta 登录”按钮），请通过 `additionalParams` 传递 `identity_provider` 键：

    ```ts
    await authClient.signIn.social({
      provider: "cognito",
      additionalParams: { identity_provider: "Okta" },
    })
    ```

    ### 其他选项： [#其他选项]

    * `scope`：要请求的其他 OAuth2 范围（与默认权限合并）。
      * 默认值：`"openid" "profile" "email"`
      * 常见的 Cognito 范围：
        * `openid`：OpenID Connect 身份验证所必需
        * `profile`：访问基本个人资料信息
        * `email`：访问用户的电子邮件
        * `phone`：访问用户的电话号码
        * `aws.cognito.signin.user.admin`：授予访问 Cognito 特定 API 的权限

    * 注意：你必须在 Cognito 应用客户端设置中配置这些范围。[可用范围](https://docs.aws.amazon.com/cognito/latest/developerguide/token-endpoint.html#token-endpoint-userinfo)

    * `getUserInfo`：用于从 Cognito UserInfo 端点获取用户信息的自定义函数。

    * `identityProvider`：预选一个 Cognito 配置的身份提供者，以跳过托管 UI 选择器。有效值包括 `"COGNITO"`、用户池中的 SAML/OIDC 提供者名称，或 `"Google"`、`"Facebook"`、`"LoginWithAmazon"`、`"SignInWithApple"` 之一。通过 `additionalParams.identity_provider` 进行的每次调用覆盖具有更高优先级。

    * `refreshAccessToken`：用于刷新令牌的自定义函数。它接收存储的刷新令牌。

    ### 刷新令牌 [#刷新令牌]

    Cognito 会在成功的授权码授予后返回刷新令牌。之后的刷新令牌授予会返回新的访问令牌和 ID 令牌。只有在应用客户端启用了刷新令牌轮换时，Cognito 才会返回新的刷新令牌；否则，原始刷新令牌仍然有效，Better Auth 会继续使用它。

    当提供者账户具有刷新令牌且 `accessTokenExpiresAt` 已知时，`auth.api.getAccessToken` 会自动刷新过期的访问令牌。它会返回有效的访问令牌和 ID 令牌。如果你需要在响应中包含刷新令牌，请改用 `/refresh-token` 端点。

    在无数据库的设置中，如果启用了 `storeAccountCookie`，Better Auth 会将提供者账户数据（包括 OAuth 令牌材料）存储在加密的 `account_data` cookie 中。令牌刷新响应会设置更新后的 cookie，因此服务端调用方必须将返回的 `Set-Cookie` 标头转发给浏览器。Cognito JWT 可能很大；Better Auth 会对超大的账户 cookie 进行分块，但浏览器和代理仍可能强制执行总标头大小限制。对于较大的令牌载荷或需要持久令牌存储的生产流程，请使用基于数据库的账户存储。

    <Callout type="info">
      有关 Amazon Cognito 的范围和 API 功能的更多信息，请参考[官方文档](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-define-resource-servers.html?utm_source)。
    </Callout>
  </Step>
</Steps>

