OAuth
了解如何配置社交 OAuth 提供商、登录和关联账户、请求权限范围、传递额外数据、刷新访问令牌、映射用户资料以及自定义提供商选项。
Better Auth 内置支持 OAuth 2.0 和 OpenID Connect。这使得你可以通过流行的 OAuth 提供商(如 Google、Facebook、GitHub 等)进行用户身份验证。
如果你想使用的提供商没有直接支持,可以使用 Generic 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",
},
},
});用法
登录
要使用社交提供商登录,可以使用 signIn.social 函数(客户端)或 auth.api(服务器端)调用。
// 客户端用法
await authClient.signIn.social({
provider: "google", // 或其它提供商 id
})// 服务器端用法
await auth.api.signInSocial({
body: {
provider: "google", // 或其它提供商 id
},
});关联账户
要将账户关联到社交提供商,可以使用 linkAccount 函数(客户端)或 auth.api(服务器端)调用。
await authClient.linkSocial({
provider: "google", // 或其它提供商 id
})服务器端用法:
await auth.api.linkSocialAccount({
body: {
provider: "google", // 或其它提供商 id
},
headers: await headers() // 包含用户会话令牌的请求头
});验证 OAuth 用户信息
使用 user.validateUserInfo 在 Better Auth 创建用户、关联新账户或让现有用户重新登录之前拒绝 OAuth 身份。回调会接收映射后的 user,以及 source.oauth 中的提供商 id 和原始提供商资料。
当 OAuth 身份首次创建时(来自常规回调、ID token 登录、One Tap 或 OAuth Proxy 的 create-user),关联新账户时(link-account),以及现有 OAuth 用户每次登录时(sign-in),都会运行该回调。在 sign-in 操作中,user 携带的是提供商的最新邮箱,因此,如果用户的提供商邮箱后来变更为不允许的域名,域名检查会拒绝该用户。它适用于无状态配置,因为无论是否使用数据库,都会在相同的时间点运行。
import { betterAuth } from "better-auth";
export const auth = betterAuth({
user: {
validateUserInfo: ({ user, source }) => {
if (source.oauth?.providerId !== "google") return;
if (!user.email?.endsWith("@example.com")) {
return {
error: "email_not_allowed",
errorDescription: "Use your example.com email to sign in",
};
}
},
},
socialProviders: {
google: {
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
},
},
});获取访问令牌
使用 getAccessToken 获取已关联账户的访问令牌。每个令牌或提供商资料请求都必须明确选择账户:将 Better Auth 账户记录的 id 作为 accountId 传入,或传入 useAccountCookie: true,从其签名 Cookie 中选择账户。providerId 永远不能作为账户选择器,不包含任何一种受支持选择器的请求均无效。
账户记录 ID 可从 listAccounts 获取。如果其访问令牌已过期,Better Auth 会在返回前刷新该令牌。
const { data: accounts, error } = await authClient.listAccounts();
if (error) {
throw new Error(error.message);
}
const account = accounts?.find((account) => account.providerId === "google");
if (!account) {
throw new Error("Google account is not linked");
}
const { accessToken } = await authClient.getAccessToken({
accountId: account.id,
})启用 account.storeAccountCookie 后,显式从签名 Cookie 中选择账户:
const { accessToken } = await authClient.getAccessToken({
useAccountCookie: true,
});在服务器端使用时,传入相同的账户记录 ID。如果不包含会话请求头,受信任的服务器调用也可以提供 userId。
await auth.api.getAccessToken({
body: {
accountId: account.id,
},
headers: await headers(), // headers containing the user's session token
});刷新访问令牌
当你需要立即刷新所选账户的访问令牌时,使用 refreshToken。它使用与 getAccessToken 相同的显式选择器约定。
const tokens = await authClient.refreshToken({
accountId: account.id,
});要改用签名账户 Cookie:
await auth.api.refreshToken({
body: {
useAccountCookie: true,
},
headers: await headers(),
});获取提供商提供的账户信息
使用 accountInfo 获取已关联账户在提供商处的当前资料数据。传入 Better Auth 账户记录的 id,而不是提供商的 subject 标识符。
响应会将身份数据与资料数据分开。account 包含所选的 Better Auth 记录及其提供商密钥,user 包含可变的资料字段,data 包含原始提供商响应。
const info = await authClient.accountInfo({
query: { accountId: account.id },
});
console.log(info.data?.account.accountId);
console.log(info.data?.user.email);当应通过签名账户 Cookie 选择账户时:
const info = await authClient.accountInfo({
query: { useAccountCookie: true },
});服务器端用法:
await auth.api.accountInfo({
query: {
accountId: account.id,
},
headers: await headers(), // headers containing the user's session token
});请求额外权限范围
有时你的应用可能需要用户在已注册后再授予额外的 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” 错误。
自定义授权 URL
要向提供商的授权端点传递额外查询参数,请在调用 signIn.social 或 linkSocial 时传入 additionalParams。这些值会在框架写入 OAuth state、PKCE challenge 和 redirect_uri 后应用;保留键 state、client_id、redirect_uri、response_type、code_challenge、code_challenge_method 和 scope 会被拒绝并返回 400,因此调用方无法破坏回调关联。
await authClient.signIn.social({
provider: "cognito",
additionalParams: {
identity_provider: "Google", // skip the Cognito hosted-UI picker
},
});
await authClient.linkSocial({
provider: "google",
loginHint: "[email protected]",
additionalParams: {
access_type: "offline",
prompt: "consent",
},
});提供商自身内置的查询参数(例如 Google 的 include_granted_scopes=true、Facebook 的 config_id,以及通过 identityProvider 设置时 Cognito 的 identity_provider)会与调用时的 additionalParams 合并;发生键冲突时,以调用时的值为准。
通过 OAuth 流程传递额外数据
Better Auth 允许你在 OAuth 流程中传递额外数据,但不将其存储到数据库。这适用于跟踪推荐码、分析来源或其他应在认证时处理但无需持久保存的临时数据。
发起 OAuth 登录或关联账户时,传递额外数据:
// 客户端:带额外数据登录
await authClient.signIn.social({
provider: "google",
additionalData: {
referralCode: "ABC123",
source: "landing-page",
},
});
// 客户端:带额外数据关联账户
await authClient.linkSocial({
provider: "google",
additionalData: {
referralCode: "ABC123",
},
});
// 服务器端:带额外数据登录
await auth.api.signInSocial({
body: {
provider: "google",
additionalData: {
referralCode: "ABC123",
source: "admin-panel",
},
},
});在钩子中访问额外数据
额外数据可以通过 getOAuthState 在 OAuth 回调时钩子中访问。
这通常适用于 /callback/:id 等 OAuth 回调路径。
使用 after 钩子的示例:
import { betterAuth } from "better-auth";
import { createAuthMiddleware, getOAuthState } from "better-auth/api";
export const auth = betterAuth({
// 其他配置...
hooks: {
after: createAuthMiddleware(async (ctx) => {
// Additional data is only available during OAuth callback
if (ctx.path === "/callback/:id") {
const additionalData = await getOAuthState<{
referralCode?: string;
source?: string;
}>();
if (additionalData) {
// IMPORTANT: Validate and sanitize the data before using it
// This data comes from the client and should not be trusted
// Example: Validate and process referral code
if (additionalData.referralCode) {
const isValidFormat = /^[A-Z0-9]{6}$/.test(additionalData.referralCode);
if (isValidFormat) {
// Verify the referral code exists in your database
const referral = await db.referrals.findByCode(additionalData.referralCode);
if (referral) {
// Safe to use the verified referral
await db.referrals.incrementUsage(referral.id);
}
}
}
// Track analytics (low-risk usage)
if (additionalData.source) {
await analytics.track("oauth_signin", {
source: additionalData.source,
userId: ctx.context.session?.user.id,
});
}
}
}
}),
},
});使用数据库钩子的示例:
// 你也可以在数据库钩子中访问额外数据
databaseHooks: {
user: {
create: {
before: async (user, ctx) => {
if (ctx.path === "/callback/:id") {
const additionalData = await getOAuthState<{ referredFrom?: string }>();
if (additionalData?.referredFrom) {
return {
data: {
referredFrom: additionalData.referredFrom,
},
};
}
}
},
},
},
},默认情况下,OAuth state 包含以下数据:
callbackURL- OAuth 流程的回调 URLcodeVerifier- OAuth 流程的代码验证器errorURL- OAuth 流程的错误 URLnewUserURL- OAuth 流程的新用户 URLlink- OAuth 流程的关联信息(邮箱和用户 id)requestSignUp- 是否请求注册 OAuth 流程expiresAt- OAuth state 的过期时间serverContext- 在服务器端设置且在重定向后仍保留的值(参见传递服务器信任的数据)[key: string]- 你传入的additionalData。这些数据来源于客户端,因此应视为不受信任。
传递服务器信任的数据
additionalData 由客户端提供,因此必须在回调时验证后才能使用。当插件(或你自己的 before 钩子)需要在重定向过程中传递服务器派生的数据时,请使用 addOAuthServerContext。它会写入客户端无法填充的仅限服务器端的存储槽,这些值可在回调时通过 serverContext 读取。
import { betterAuth } from "better-auth";
import {
addOAuthServerContext,
createAuthMiddleware,
getOAuthState,
} from "better-auth/api";
export const auth = betterAuth({
hooks: {
before: createAuthMiddleware(async (ctx) => {
// Social and generic OAuth providers both sign in here.
if (ctx.path === "/sign-in/social") {
// Derived on the server, so it is safe to trust on the callback.
await addOAuthServerContext({ tenantId: ctx.context.tenantId });
}
}),
after: createAuthMiddleware(async (ctx) => {
if (ctx.path === "/callback/:id") {
const tenantId = (await getOAuthState())?.serverContext?.tenantId;
// Safe to use without re-validation: the client could not set this.
}
}),
},
});处理不提供邮箱的提供商
Better Auth 目前要求每条用户记录都必须有电子邮件地址。大多数提供商会在使用 email scope 时返回邮箱,但有些提供商在合法情况下可能不会返回。当这种情况发生时,OAuth 流程会失败并报 error=email_not_found(而对于 Generic OAuth 插件则是 error=email_is_missing)。
下表总结了每个受影响的提供商:何时可能缺少 email、在 mapProfileToUser 中可作为回退的稳定标识符,以及对提供商 email_verified 信号的可信度。
| 提供商 | email 可能缺失的情况 | 稳定的回退 ID | 对 email_verified 的信任程度 |
|---|---|---|---|
| Apple | 首次登录后的每次登录(Apple 仅在首次同意时发送 email) | profile.sub(每个 Apple Team 稳定) | 可靠;中继地址也会被标记为已验证 |
| Discord | 仅使用手机号的账户;未授予 email scope | profile.id(snowflake) | 可靠(专用的 verified 字段) |
没有有效的邮箱,即使已授予 email 权限 | profile.id(应用范围) | 未知:Graph API 不提供逐邮箱验证标志 | |
| GitHub | 用户已将邮箱设为私密;GitHub App 缺少“Email addresses”权限 | profile.id(数字) | 可靠 |
成员没有已确认的邮箱;未授予 email scope | profile.sub(每个应用成对) | 存在时可靠 | |
| Microsoft Entra ID | 托管用户没有 mail 属性,除非将 email 配置为可选声明 | profile.oid(在 profile.tid 内稳定) | 不可信:Microsoft 明确警告永远不要将其用于授权 |
| Roblox | 默认 Roblox 资料流程不会返回邮箱;Better Auth 当前回退到 preferred_username | profile.sub(Roblox 用户 ID) | 对默认资料流程而言未知 |
使用 mapProfileToUser 合成占位邮箱
当 email 字段为 null 或不存在时,回退到提供商的稳定 ID:
import { betterAuth } from "better-auth";
export const auth = betterAuth({
socialProviders: {
discord: {
clientId: process.env.DISCORD_CLIENT_ID!,
clientSecret: process.env.DISCORD_CLIENT_SECRET!,
mapProfileToUser: (profile) => ({
email: profile.email ?? `${profile.id}@discord.placeholder.local`,
}),
},
apple: {
clientId: process.env.APPLE_CLIENT_ID!,
clientSecret: process.env.APPLE_CLIENT_SECRET!,
mapProfileToUser: (profile) => ({
email: profile.email ?? `${profile.sub}@apple.placeholder.local`,
}),
},
microsoft: {
clientId: process.env.MICROSOFT_CLIENT_ID!,
clientSecret: process.env.MICROSOFT_CLIENT_SECRET!,
mapProfileToUser: (profile) => ({
email: profile.email ?? `${profile.oid}@entra.placeholder.local`,
}),
},
},
});合成邮箱只是占位符,不是真实联系地址。发送邮件的插件(密码重置、魔法链接、邮箱验证、组织邀请)无法投递到这些地址。请使用你控制的域名,或使用保留后缀如 .invalid 或 .local,以免误发到真实邮箱。
提供商特定说明
- Apple:第一次看到邮箱时请将其持久化保存。Apple 不提供用户信息端点,因此如果你在首次登录时不保存它,之后就无法再获取。
email_verified和is_private_email都会被序列化为 字符串("true"/"false"),而不是布尔值。 - GitHub:默认会请求
user:emailscope。私密邮箱在/user上仍会返回null;主要已验证地址可在/user/emails获取。 - Microsoft Entra ID:由于
email可随租户变化且从不验证,请使用profile.oid(不可变、在租户内稳定)作为身份锚点;仅将email视为资料属性。Microsoft 的声明验证指南明确警告,切勿将email、preferred_username或unique_name用于授权决策。 - Facebook:由于没有逐邮箱验证标志,除非你自行执行验证挑战,否则应将每个 Facebook 邮箱都视为未验证。
Better Auth 会通过稳定的 (issuer, accountId) 键识别现有 OAuth 账户,但关联的 Better Auth 用户仍然需要电子邮件地址。不支持无邮箱用户的功能正在 #9124 中跟踪。
提供商选项
clientId
提供商签发的 OAuth 2.0 Client ID。
对于通过受众(audience)验证 ID token 的提供商(Google、Apple、Microsoft Entra、Facebook、Cognito),你可以传入一个数组,以接受为任意已配置客户端签发的 token。Better Auth 驱动授权码流程时会使用数组中的第一个条目;验证 ID token 的 aud 声明时会接受所有条目。这使得你可以使用单一后端配置实现跨平台登录(Web、iOS、Android),其中每个平台的原生 SDK 都会使用各自的 Client ID 签发 token。
import { betterAuth } from "better-auth";
export const auth = betterAuth({
// 其他配置...
socialProviders: {
google: {
clientId: [
process.env.GOOGLE_WEB_CLIENT_ID as string,
process.env.GOOGLE_IOS_CLIENT_ID as string,
process.env.GOOGLE_ANDROID_CLIENT_ID as string,
],
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
},
},
});所有 Client ID 必须位于同一个提供商项目中,这样用户同意才能共享。对于不通过受众验证 ID token 的提供商,只接受单个字符串。
scope
访问请求的权限范围,例如 email 或 profile。
import { betterAuth } from "better-auth";
export const auth = betterAuth({
// 其他配置...
socialProviders: {
google: {
clientId: "YOUR_GOOGLE_CLIENT_ID",
clientSecret: "YOUR_GOOGLE_CLIENT_SECRET",
scope: ["email", "profile"],
},
},
});redirectURI
提供商的自定义重定向 URI。默认使用 /api/auth/callback/${providerName}。
import { betterAuth } from "better-auth";
export const auth = betterAuth({
// 其他配置...
socialProviders: {
google: {
clientId: "YOUR_GOOGLE_CLIENT_ID",
clientSecret: "YOUR_GOOGLE_CLIENT_SECRET",
redirectURI: "https://your-app.com/auth/callback",
},
},
});disableSignUp
禁用新用户注册。
disableIdTokenSignIn
禁用使用 ID token 登录。默认对某些提供商(如 Google 和 Apple)启用。
verifyIdToken
用于验证 ID token 的自定义函数。接收 token、可选的 nonce,以及请求端点上下文,因此你可以根据请求头或其他请求数据进行分支处理。
提供 verifyIdToken 会替换提供商内置的验证逻辑(签名、签发者、受众和过期时间)。你的回调必须自行执行这些检查。来自客户端的请求头(例如 x-platform)由攻击者控制——只能用它们来选择要验证的受众(或其他声明),不能把它们当作身份凭证本身。
import { betterAuth } from "better-auth";
import { createRemoteJWKSet, jwtVerify } from "jose";
const appleJwks = createRemoteJWKSet(
new URL("https://appleid.apple.com/auth/keys"),
);
export const auth = betterAuth({
socialProviders: {
apple: {
clientId: "YOUR_APPLE_CLIENT_ID",
clientSecret: "YOUR_APPLE_CLIENT_SECRET",
verifyIdToken: async (token, nonce, ctx) => {
// 从请求中选择受众,然后进行加密验证。
const audience =
ctx?.headers?.get("x-platform") === "ios"
? process.env.APPLE_APP_BUNDLE_IDENTIFIER!
: process.env.APPLE_CLIENT_ID!;
try {
const { payload } = await jwtVerify(token, appleJwks, {
issuer: "https://appleid.apple.com",
audience,
maxTokenAge: "1h",
});
if (nonce && payload.nonce !== nonce) {
return false;
}
return true;
} catch {
return false;
}
},
},
},
});overrideUserInfoOnSignIn
一个布尔值,决定登录时是否覆盖数据库中的用户信息。默认是 false,即登录时不覆盖用户信息。如果希望每次登录都更新用户信息,设置为 true。
requireEmailVerification
要求在创建会话前验证此提供商的邮箱。默认为 false。
当提供商报告邮箱未验证时,Better Auth 仍会创建或关联用户和账户,但不会签发会话。OAuth 回调会重定向并附带 ?error=email_not_verified,ID token 登录则返回带有 EMAIL_NOT_VERIFIED 错误代码的 403。系统会根据你的 emailVerification 设置发送(或重新发送)验证邮件:sendOnSignUp 负责新用户,sendOnSignIn 负责回访用户。配置 emailVerification.sendVerificationEmail 并保持启用 sendOnSignUp,以确保被阻止的用户始终能收到验证链接。
该限制会检查本地用户的验证状态,而不是每次请求中的提供商声明。已经通过其他方式(例如邮箱和密码)完成验证的用户,即使提供商之后报告邮箱未验证,也仍可继续访问。
import { betterAuth } from "better-auth";
export const auth = betterAuth({
socialProviders: {
google: {
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
requireEmailVerification: true,
},
},
});此选项需按提供商单独启用,并且独立于 emailAndPassword.requireEmailVerification:启用邮箱和密码验证不会限制社交登录。
仅为报告可信 email_verified 信号的提供商启用此选项。有些提供商始终将邮箱报告为未验证(或从不返回邮箱),在这些提供商上启用该选项会阻止所有登录。请参阅处理不提供邮箱的提供商。
mapProfileToUser
使用 mapProfileToUser 更改默认的用户映射,或根据提供商个人资料填充其他用户字段。
Better Auth 会将该函数的返回值视为提供商输入,尽管该函数是在你的服务器上运行的。它会在 OAuth 注册、登录时覆盖个人资料,以及账户关联时同步个人资料的过程中,应用 user.additionalFields 中的输入规则。允许输入的映射字段会被解析并存储,而对于标记为 input: false 的字段,其映射值会被忽略。
资料映射无法重新定义提供商账户身份。内置提供商会根据其文档说明的不可变资料字段派生身份。当默认的 sub 或 id 字段不是正确的标识符时,Generic OAuth 提供商会使用 accountSubject。
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,
};
},
},
},
});在 user.additionalFields
选项中声明映射字段,
并允许这些字段作为输入。无状态身份验证配置同样适用此规则。
服务器拥有的字段与授权声明
将角色、封禁状态、内部标记和组织成员身份等安全敏感字段设置为 input: false。不要仅为了让 mapProfileToUser 持久化提供商声明就启用输入,因为同一设置也会允许通用注册和用户更新请求提供该字段。
input 和 returned 控制不同的方向。例如,{ input: false, returned: true } 定义了一个可读取的服务器拥有字段。API 输入和 mapProfileToUser 无法提供该字段,但 Better Auth 会在响应中包含其存储的值。
如果提供商声明决定了谁可以登录,请在 Better Auth 完成 OAuth 登录之前执行该策略。不要等到登录完成后再检查,因为 Better Auth 可能已经签发了有效会话。提供商存在专用选项时,优先使用该选项,例如 Google 提供商用于限制 Google Workspace 域名的 hd 选项。对于调用 getUserInfo 的流程,可以通过自定义实现验证提供商响应,并在策略验证失败时返回 null。对于不调用 getUserInfo 的独立登录路径,也要配置等效的强制执行逻辑。
如果还需要存储经过验证的声明,请将字段保持为 input: false,并使用应用程序的数据库层写入该字段。仅当静态值适用于通过该身份验证配置创建的每个用户时,才使用 defaultValue;不要将其用于存储从提供商个人资料中派生的值。
refreshAccessToken
自定义刷新令牌的函数。此功能仅支持内置社交提供商(Google、Facebook、GitHub 等),暂不支持通过通用 OAuth 插件配置的自定义 OAuth 提供商。对于内置提供商,需按需提供刷新令牌的自定义函数。
import { betterAuth } from "better-auth";
export const auth = betterAuth({
// 其他配置...
socialProviders: {
google: {
clientId: "YOUR_GOOGLE_CLIENT_ID",
clientSecret: "YOUR_GOOGLE_CLIENT_SECRET",
refreshAccessToken: async (token) => {
return {
accessToken: "new-access-token",
refreshToken: "new-refresh-token",
};
},
},
},
});clientKey
你的应用客户端密钥。TikTok 社交提供商使用此项替代 clientId。
import { betterAuth } from "better-auth";
export const auth = betterAuth({
// 其他配置...
socialProviders: {
tiktok: {
clientKey: "YOUR_TIKTOK_CLIENT_KEY",
clientSecret: "YOUR_TIKTOK_CLIENT_SECRET",
},
},
});getUserInfo
自定义函数,用于从提供商获取用户信息,覆盖默认的用户信息获取流程。
import { betterAuth } from "better-auth";
export const auth = betterAuth({
// 其他配置...
socialProviders: {
google: {
clientId: "YOUR_GOOGLE_CLIENT_ID",
clientSecret: "YOUR_GOOGLE_CLIENT_SECRET",
getUserInfo: async (token) => {
// 自定义实现获取用户信息
const response = await fetch("https://www.googleapis.com/oauth2/v2/userinfo", {
headers: {
Authorization: `Bearer ${token.accessToken}`,
},
});
const profile = await response.json();
return {
user: {
name: profile.name,
email: profile.email,
image: profile.picture,
emailVerified: profile.verified_email,
},
data: profile,
};
},
},
},
});disableImplicitSignUp
禁用隐式注册新用户。启用后,登录时需要传入 requestSignUp 为 true 才能创建新用户。
import { betterAuth } from "better-auth";
export const auth = betterAuth({
// 其他配置...
socialProviders: {
google: {
clientId: "YOUR_GOOGLE_CLIENT_ID",
clientSecret: "YOUR_GOOGLE_CLIENT_SECRET",
disableImplicitSignUp: true,
},
},
});prompt
授权码请求中使用的提示参数,控制认证流程行为。
import { betterAuth } from "better-auth";
export const auth = betterAuth({
// 其他配置...
socialProviders: {
google: {
clientId: "YOUR_GOOGLE_CLIENT_ID",
clientSecret: "YOUR_GOOGLE_CLIENT_SECRET",
prompt: "select_account", // 或 "consent", "login", "none", "select_account+consent"
},
},
});responseMode
授权码请求的响应模式,决定授权响应的返回方式。
import { betterAuth } from "better-auth";
export const auth = betterAuth({
// 其他配置...
socialProviders: {
google: {
clientId: "YOUR_GOOGLE_CLIENT_ID",
clientSecret: "YOUR_GOOGLE_CLIENT_SECRET",
responseMode: "query", // 或 "form_post"
},
},
});disableDefaultScope
移除提供商的默认权限范围。默认情况下,提供商会包含诸如 email 和 profile 的权限。设置为 true 后,会移除默认权限,只使用你指定的权限。
import { betterAuth } from "better-auth";
export const auth = betterAuth({
// 其他配置...
socialProviders: {
google: {
clientId: "YOUR_GOOGLE_CLIENT_ID",
clientSecret: "YOUR_GOOGLE_CLIENT_SECRET",
disableDefaultScope: true,
scope: ["https://www.googleapis.com/auth/userinfo.email"], // 只使用此权限
},
},
});其他提供商配置
每个提供商可能还有额外选项,请查看具体提供商文档了解更多细节。