OAuth
Better Auth 内置支持 OAuth 2.0 和 OpenID Connect。这使您能够通过流行的 OAuth 提供商(如 Google、Facebook、GitHub 等)对用户进行身份验证。
如果您所需的提供商未直接受支持,可以使用 通用 OAuth 插件 进行自定义集成。
配置社交登录提供商
要启用社交登录提供商,您需要提供该提供商的 clientId
和 clientSecret
。
以下是如何配置 Google 作为提供商的示例:
import { betterAuth } from "better-auth";
export const auth = betterAuth({
// 其他配置...
socialProviders: {
google: {
clientId: "YOUR_GOOGLE_CLIENT_ID",
clientSecret: "YOUR_GOOGLE_CLIENT_SECRET",
},
},
});
使用方法
登录
要使用社交提供商登录,您可以使用 authClient
的 signIn.social
函数,或在服务器端使用 auth.api
。
// 客户端用法
await authClient.signIn.social({
provider: "google", // 或其他任何提供商 ID
})
// 服务器端用法
await auth.api.signInSocial({
body: {
provider: "google", // 或其他任何提供商 ID
},
});
关联账户
要将账户关联到社交提供商,您可以使用 authClient
的 linkAccount
函数,或在服务器端使用 auth.api
。
await authClient.linkSocial({
provider: "google", // 或其他任何提供商 ID
})
服务器端用法:
await auth.api.linkSocialAccount({
body: {
provider: "google", // 或其他任何提供商 ID
},
headers: // 传递包含认证令牌的请求头
});
获取访问令牌
要获取社交提供商的访问令牌,您可以使用 authClient
的 getAccessToken
函数,或在服务器端使用 auth.api
。当您使用此端点时,如果访问令牌已过期,它将被自动刷新。
const { accessToken } = await authClient.getAccessToken({
providerId: "google", // 或其他任意提供商 ID
accountId: "accountId", // 可选,用于获取特定账户的访问令牌
})
服务器端用法:
await auth.api.getAccessToken({
body: {
providerId: "google", // 或其他任意提供商 ID
accountId: "accountId", // 可选,用于获取特定账户的访问令牌
userId: "userId", // 可选,如果未在请求头中提供认证令牌
},
headers: // 传递包含认证令牌的请求头
});
获取提供商提供的账户信息
要获取提供商特定的账户信息,您可以使用 authClient
的 accountInfo
函数,或在服务器端使用 auth.api
。
const info = await authClient.accountInfo({
accountId: "accountId", // 此处传入提供商提供的账户 ID,系统会根据账户 ID 自动检测提供商
})
服务器端用法:
await auth.api.accountInfo({
body: { accountId: "accountId" },
headers: // 传递包含认证令牌的请求头
});
请求额外权限范围
有时您的应用可能在用户注册后需要额外的 OAuth 权限范围(例如,用于访问 GitHub 仓库或 Google Drive)。用户可能不希望一开始就授予过多权限,而是倾向于从最小权限开始,按需授予额外访问权限。
您可以通过使用同一提供商的 linkSocial
方法来请求额外权限范围。这将触发一个新的 OAuth 流程,在保持现有账户连接的同时请求额外权限。
const requestAdditionalScopes = async () => {
await authClient.linkSocial({
provider: "google",
scopes: ["https://www.googleapis.com/auth/drive.file"],
});
};
请确保您运行的是 Better Auth 1.2.7 或更高版本。早期版本(如 1.2.2)在尝试与现有提供商链接以获取额外权限时,可能会显示 "Social account already linked"(社交账户已链接)错误。
其他提供商配置
scope 访问请求的权限范围。例如,email
或 profile
。
redirectURI 提供商的自定义重定向 URI。默认使用 /api/auth/callback/${providerName}
。
disableImplicitSignUp: 禁用隐式注册。要注册用户,需要在登录时将 requestSignUp
设置为 true
。
disableSignUp: 禁用新用户注册。
disableIdTokenSignIn: 禁用使用 ID 令牌进行登录。默认情况下,某些提供商(如 Google 和 Apple)会启用此功能。
verifyIdToken 用于验证 ID 令牌的自定义函数。
getUserInfo 用于从提供商获取用户信息的自定义函数。给定提供商返回的令牌,此函数应返回用户信息。
overrideUserInfoOnSignIn:一个布尔值,用于决定在用户登录时是否覆盖数据库中的用户信息。默认值为 false
,表示在登录过程中不会覆盖用户信息。如果您希望在每次登录时更新用户信息,请将其设置为 true
。
refreshAccessToken:一个用于刷新令牌的自定义函数。此功能仅适用于内置的社交登录提供商(Google、Facebook、GitHub 等),目前不支持通过通用 OAuth 插件配置的自定义 OAuth 提供商。对于内置提供商,您可以根据需要提供一个自定义函数来刷新令牌。
mapProfileToUser:一个自定义函数,用于将提供商返回的用户信息映射到数据库中的用户对象。
如果您希望在用户对象中包含来自提供商配置文件的额外字段,或者想要更改默认的用户对象映射方式,此功能非常有用。
import { betterAuth } from "better-auth";
export const auth = betterAuth({
// 其他配置...
socialProviders: {
google: {
clientId: "YOUR_GOOGLE_CLIENT_ID",
clientSecret: "YOUR_GOOGLE_CLIENT_SECRET",
mapProfileToUser: (profile) => {
return {
firstName: profile.given_name,
lastName: profile.family_name,
};
},
},
},
});
Better Auth 中的 OAuth 工作原理
以下是用户选择身份验证提供商时的流程:
- 配置检查: 确保已配置必要的提供商详细信息(例如客户端 ID、密钥)。
- 状态生成: 生成状态令牌并保存到数据库中,用于 CSRF 保护。
- PKCE 支持: 如果适用,创建 PKCE 代码挑战和验证器以进行安全交换。
- 授权 URL 构建: 使用客户端 ID、重定向 URI、状态等参数构建提供商的授权 URL。回调 URL 通常遵循模式
/api/auth/callback/${providerName}
。 - 用户重定向:
- 如果启用了重定向,用户将被重定向到提供商的登录页面。
- 如果禁用了重定向,则返回授权 URL 供客户端处理重定向。
登录后流程
用户完成登录过程后,提供商会将其重定向回带有代码和状态的回调 URL。Better Auth 会处理后续步骤:
- 令牌交换: 将代码交换为访问令牌和用户信息。
- 用户处理:
- 如果用户不存在,则创建新账户。
- 如果用户已存在,则将其登录。
- 如果用户在多个提供商处拥有多个账户,Better Auth 会根据您的配置将它们关联起来。了解更多关于账户关联的信息。
- 会话创建: 为用户创建新会话。
- 重定向: 用户被重定向到初始请求中指定的 URL 或
/
。
如果在过程中发生任何错误,Better Auth 会处理错误并将用户重定向到错误 URL(如果提供)或 callbackURL。并在查询字符串 ?error=...
中包含错误消息。