Better Auth 1.7 版本全解析:从账户身份模型重构到 OAuth 2.1 安全加固的升级实战指南
【免费下载链接】better-authThe most comprehensive authentication framework项目地址: https://gitcode.com/GitHub_Trending/be/better-auth
Better Auth 1.7 是该框架近年来最大的一次 Minor 版本升级,围绕"身份可信性"这一核心主题,重构了账户(Account)身份模型、重写了 Generic OAuth 与 OAuth Provider 生态、引入了数据库 Schema 运行时校验,并对 TOTP/2FA、设备授权、MCP 集成等数十个模块做了安全与稳定性加固。本文基于仓库 packages/better-auth/CHANGELOG.md(覆盖 1.6.0 至 1.7.3 全部条目),结合 packages/better-auth 源码与 docs/content/docs/guides/1-7-upgrade-guide.mdx 升级指南,系统梳理 1.7 的破坏性变更、新 API、配置项迁移路径与升级注意事项,帮助你在升级前评估影响面、升级后快速排查问题。
升级前必读:1.7 的三大破坏性变更
1.7.0 的破坏性变更集中在三点:账户身份键从(providerId, accountId)变为(issuer, accountId)、Generic OAuth 插件重写为一等公民社交提供商、MCP 插件独立成包并迁移端点。1.7.3 又针对 1.7.0~1.7.2 的账户 Schema 做了兼容性修复,因此升级路径需要分阶段理解。
账户身份模型:按可信 Issuer 界定身份
1.7.0(PR #10403)将账户的唯一键从"提供商配置"改为"可信 Issuer":账户现在使用唯一的(issuer, accountId)键,同一 OIDC Issuer 的别名会去重为同一个外部身份,而不同 Issuer 下的相同 subject 保持独立。这一改动要求Account.issuer字段必填,同时保留accountId作为提供商分配的账户标识符。
升级到 1.7 后:
- 账户相关 API 通过请求属性
accountId选择本地Account.id;token 与 provider-profile 类 API 可通过useAccountCookie: true改用签名账户 Cookie 选择。 - 凭据账户使用
local:credential作为 provider 身份,并以关联用户的稳定id作为账户标识。 - OAuth provider 身份来自原始已验证的 profile:OIDC discovery 使用
sub,纯 OAuth 使用id,提供商可通过accountSubject声明其他不可变字段;不再在运行时切换sub/id。 getUserInfo().user不再携带 provider 身份,mapProfileToUser也不能返回id,需从accountInfo.account.accountId读取所选身份。- SSO 账户 subject 由协议定义:OIDC 使用已验证的
subclaim,SAML 使用签名的NameID,两者配置中的mapping.id均被移除。手动配置的 SAML(无 metadata XML)必须设置idpMetadata.entityID,因为samlConfig.issuer现在仅标识服务提供商。
1.7.3 的兼容性修复(PR #11153):恢复与 1.6 数据库的登录兼容——通过(providerId, accountId)识别账户并移除 1.7.0 引入的issuer必填要求,从 1.6 升级不再需要账户 Schema 迁移;歧义账户键会被拒绝而非随意选择。若你已应用 1.7.0~1.7.2 的账户 Schema,升级 1.7.3 前需删除其 issuer 唯一索引;SQL 数据库还需将issuer设为可空或删除该列,否则注册与账户关联会失败。auth migrate不会执行此清理,请按 1-7 升级指南 中对应数据库的步骤操作。
Generic OAuth:一等公民社交提供商 + OAuth 2.1 安全默认值
1.7.0(PR #9069)将 Generic OAuth 插件重写为首选社交提供商实现,采用 OAuth 2.1 安全默认值。破坏性变更清单如下:
| 旧 API | 新 API |
|---|---|
signIn.oauth2({ providerId }) | signIn.social({ provider }) |
oauth2.link() | linkSocial() |
回调/api/auth/oauth2/callback/:id | /api/auth/callback/:id |
genericOAuthClient() | 标准社交客户端 API |
pkce默认false | pkce默认true(不支持 PKCE 的提供商需显式pkce: false) |
authorizationUrlParams/tokenUrlParams任意类型 | 仅接受Record<string, string> |
issuer/requireIssuerValidation配置 | 移除,issuer 校验通过 OIDC discovery 自动完成 |
mapProfileToUser的 profile 类型 | OAuth2UserInfo & Record<string, unknown> |
安全默认值包括:PKCE 必选、RFC 9207 issuer 校验、带openidscope 注入的 OIDC 自动发现、类型化 provider ID。配套变更(PR #9966)要求使用discoveryUrl的 provider 通过其发布的 JWKS 验证id_token(签名、issuer、audience、算法),并用服务器生成的 OIDCnonce绑定授权请求;不返回nonceclaim 的提供商需设置disableIdTokenNonceBinding: true。这些 provider 还接受signIn.social({ idToken })客户端提交的 id_token 登录。
MCP 插件独立成包
1.7.0(PR #9992)将 MCP 插件从better-auth内核迁出为独立包@better-auth/mcp(基于@better-auth/oauth-provider构建):
- 授权插件与受保护请求助手从包根导入;内核中的 MCP 客户端(
createMcpAuthClient及其适配器)已移除,改用官方 v2@modelcontextprotocol/client、@modelcontextprotocol/server包。 - OAuth 端点从
/mcp/*迁移到/oauth2/*,发现端点位于/.well-known/oauth-authorization-server,受保护资源元数据位于/.well-known/oauth-protected-resource。 - 路由助手
withMcpAuth更名为requireMcpAuth;独立受保护资源工厂mcpHandler更名为createMcpProtectedRequestHandler(扁平化McpProtectedRequestHandlerOptions对象,含issuer、单一audience、可选jwtVerifyOptions等)。 - 迁移步骤:安装
@better-auth/mcp、@better-auth/cimd及所需官方 MCP v2 包;新增jwt()插件(token 签名必需);将oidcConfig下嵌套选项改为mcp({ ... })平铺选项;数据库模型oauthApplication变为oauthClient,新增oauthRefreshToken、oauthClientAssertion表,用npx auth migrate或npx auth generate重新生成 Schema。
数据库与迁移:Schema 运行时校验与安全迁移策略
1.7 在数据库层引入了两项重要机制:初始化期 Schema 校验与迁移安全防护。
初始化期 Schema 校验(默认开启)
1.7.3(PR #11178)新增数据库 Schema 校验:报告 Better Auth 从未写入的缺失表、缺失列、必需列,并给出修复指引;Kysely 会检查实时数据库 Schema,认证请求等待同一校验,Schema 不匹配则被拒绝。校验默认开启(含生产环境),设置advanced.database.validateSchema: false可关闭运行时校验。对应实现位于 packages/better-auth/src/auth/base.ts:validateSchema !== false时执行检查,validateSchema === true时以"warn"级别输出,否则"debug"。
auth migrate在需要人工修复的必需未写列存在时拒绝应用变更。相关测试见 packages/better-auth/src/auth/schema-check.test.ts。
UnsafeMigrationError:必需列迁移不再静默失败
1.7.1(PR #10863)修复了auth migrate向已有数据行添加"无默认值的必需列"时的行为:此前 SQLite/Postgres/SQL Server 生成失败语句、MySQL 则用空字符串填充每一行并报告成功。现在它停止并报错,指明列名与需先执行的 backfill:
getMigrations抛出新的UnsafeMigrationError(从better-auth/db/migration导出),调用方可区分索引冲突等其他迁移错误。实现见 packages/better-auth/src/db/get-migration.ts。auth generate仍为外部迁移工具输出语句,并附加注释横幅提示需手动 backfill 的列。- 必需字段对应的数据库列若仍可空,仅记录警告而不阻断迁移。
- CLI 命令失败时打印错误并以非零码退出,不再产生未处理的 promise rejection。
1.7.2(PR #10875)进一步修复 Cloudflare D1 上的程序化迁移失败,同时保留各受支持数据库上的既有索引校验;PR #10877 防止被禁用的 MyISAM 索引满足迁移索引检查。
数据库连接(joins)从实验性转正
1.7.0(PR #10359)将数据库 joins 移出experimental,成为稳定选项advanced.database.joins(默认false):
advanced: { database: { joins: true, }, }支持原生 join 的适配器会在启用时使用 join;适配器无法返回 join 数据时,Better Auth 回退为附加查询并合并结果。Drizzle 与 Prisma 用户需确保 Schema 包含所需关系(npx auth@latest generate)。
OAuth 与 OAuth Provider:安全加固全景
1.7 在 OAuth 客户端与 OAuth Provider(授权服务器)两侧都做了大量加固,按主题整理如下。
per-request 附加参数与登录提示(PR #9305)
signIn.social、linkSocial、signIn.sso现在接受additionalParams: Record<string, string>追加到授权 URL 查询参数;linkSocial还获得与另外两者一致的loginHint。典型场景:Google 的access_type=offline/prompt=consent、Cognito 的identity_provider=Google、Microsoft 的domain_hint。
安全约束:
- 共享
createAuthorizationURL助手静默丢弃保留参数(state、client_id、redirect_uri、response_type、code_challenge、code_challenge_method、nonce、scope);请求体 Zod Schema 对同键返回 400。 - 非标准客户端标识(
wechat→appid、tiktok→client_key)额外过滤,防止切换已配置 OAuth 应用。 - 协议必需常量(
atlassian→audience、notion→owner)最后合并,调用方无法覆盖;操作员意图型默认值(Googleinclude_granted_scopes等)仍可覆盖。 signIn.sso对 SAML provider 的additionalParams直接拒绝 400(SAML AuthnRequest 已签名,不能携带调用方查询参数)。- Cognito 新增类型化
identityProvider?: string配置项,映射到identity_provider查询参数,避免魔法字符串。 - OpenAPI 生成器新增
ZodRecord处理,z.record()字段现在输出带类型化additionalProperties的type: object,顺带修复additionalData被渲染为type: string的长期 bug。
多客户端 ID 与 audience 校验(PR #9292)
按 audience 校验 ID token 的提供商(Google、Apple、Microsoft Entra、Facebook、Cognito)可接受客户端 ID 数组:第一个用于授权码流程,校验audclaim 时接受全部条目,一个后端可服务 Web/iOS/Android 多个平台客户端:
socialProviders: { google: { clientId: [ process.env.GOOGLE_WEB_CLIENT_ID!, process.env.GOOGLE_IOS_CLIENT_ID!, process.env.GOOGLE_ANDROID_CLIENT_ID!, ], clientSecret: process.env.GOOGLE_CLIENT_SECRET!, }, }@better-auth/core/oauth2导出getPrimaryClientId供 provider 作者使用。Google、Apple、Facebook 必须同时提供clientId与clientSecret(服务端 code exchange 强制);Microsoft Entra 与 Cognito 仅需clientId(支持纯 PKCE 的 public-client 流程)。空数组、空字符串、缺失配置会在登录时报错而非静默生成畸形授权 URL。
id_token 统一验证器(PR #9828)
客户端提交的 id_token 登录/关联由单一函数验证,不再使用每 provider 一个的verifyIdToken。每个 provider 声明带 JWKS 来源、issuer、audience 的idToken配置,核心验证器执行签名、issuer、audience、nonce 检查;未声明配置的 provider 拒绝客户端 id_token 路径(PayPal 因身份来自 access token,返回ID_TOKEN_NOT_SUPPORTED)。自定义 provider 示例:
idToken: { jwks: createRemoteJWKSet(new URL("https://issuer.example/.well-known/jwks.json")), issuer: "https://issuer.example", audience: clientId, },无法使用本地 JWKS 时传idToken: { verify: async (token, nonce) => boolean }。
邮件验证门槛:requireEmailVerification(PR #9929)
内置社交提供商与 Generic OAuth 新增requireEmailVerification选项:provider 报告未验证邮箱时,用户/账户仍会创建或关联,但不签发会话——OAuth 回调重定向到?error=email_not_verified,ID token 与 One Tap 登录返回403 EMAIL_NOT_VERIFIED。该选项按 provider 启用,不继承emailAndPassword.requireEmailVerification;校验的是本地用户验证状态,仅建议对email_verified信号可信的 provider 启用。
提供商标识:Microsoft oid claim(PR #10204)
内置microsoftprovider 与 Generic OAuthmicrosoftEntraId助手现在用稳定的oidclaim 标识 Entra 账户;无有效oid的 token 被拒绝,Generic OAuth 助手在 Microsoft discovery 不提供 ID-token 验证元数据时拒绝初始化。基于sub创建的既有 Microsoft 账户行需在升级前迁移。
动态 baseURL 与代理头信任(PR #9134)
动态baseURL配置默认忽略x-forwarded-host与x-forwarded-proto,除非设置advanced.trustedProxyHeaders: true。使用baseURL: { allowedHosts }时从Host解析 auth 来源,防止转发头选择其他允许主机。破坏性变更:若你的代理仅通过x-forwarded-host暴露公网主机名,需启用该选项;nginx 默认、Vercel、Cloudflare、Netlify(代理重写Host)不受影响:
betterAuth({ baseURL: { allowedHosts: [...] }, advanced: { trustedProxyHeaders: true, }, });配套变更(PR #10127):配置baseURL.allowedHosts后,OAuth 登录/关联/回调/代理流程从当前请求 base URL 构建redirect_uri,多主机部署下内置社交与 Generic OAuth provider 使用解析后的请求主机;自定义OAuthProvider使用共享/callback/<provider-id>路由时可省略callbackPath。
OAuth Provider:DPoP、受保护资源、Back-Channel Logout 与设备授权
- DPoP(RFC 9449,PR #10039):OAuth Provider 可签发与验证 DPoP sender-constrained token。客户端通过注册时的
dpop_bound_access_tokens、授权请求的dpop_jkt或针对配置了dpopBoundAccessTokensRequired的资源请求。签发 token 携带cnf.jkt、返回token_type: "DPoP",并在 refresh-token 轮换、introspection、userinfo 全程保持绑定。资源服务器用verifyAccessTokenRequest验证(检查Authorization: DPoP方案、proof、请求目标、token 哈希、proof 重放);重放通过数据库支撑的验证存储拒绝,跨实例有效。破坏性变更:原始 token 验证器verifyAccessToken更名为verifyBearerToken(better-auth/oauth2与oauthProviderResourceClientaction 两处),并拒绝 DPoP-bound token;AccessTokenRequestInput更名为ResourceRequestInput。需迁移 Schema:access-token/refresh-token 表的confirmation列、客户端的dpopBoundAccessTokens、资源的dpopBoundAccessTokensRequired。 - 受保护资源建模(PR #9648):用
resources或oauthResource管理 API 显式建模受保护资源,可定义 token TTL、允许 scope、自定义 JWT claim 与 JWT 签名 pin。validAudiences移除,改为resources+oauthClientResource或 DCRresources关联。签发时按资源策略收窄 scope、采用最短 TTL、剥离保留 claim、输出jti。signJWT()接受signingKeyId/signingAlgorithm;jwks表新增可空alg、crv列。@better-auth/mcp现在要求显式resource选项,例如resource: "https://api.example.com/mcp"。 - Back-Channel Logout 1.0(PR #9304):会话在 OP 结束时(登出、
/oauth2/end-session、admin 撤销、封禁),通知持有该会话 token 的每个 Relying Party,API 访问立即切断(而非等 token TTL)。客户端通过 DCR 或 admin 注册backchannel_logout_uri(可选backchannel_logout_session_required)加入;provider 按客户端签名logout+jwtLogout Token 并行 POST。破坏性变更:绑定会话已结束的 opaque/JWT access token,introspection 返回{ active: false },/oauth2/userinfo返回invalid_token。无offline_access的 refresh token 在会话结束时被撤销。无后台任务处理器时内联完成投递,serverless 运行时建议配置advanced.backgroundTasks.handler。Schema 变更:oauthClient.backchannelLogoutUri、oauthClient.backchannelLogoutSessionRequired、oauthAccessToken.revoked。 - 设备授权(PR #10135、#10746):注册的 OAuth 客户端可用 RFC 8628 设备流获取 token:
oauthDeviceAuthorization()搭配oauthProvider()或mcp(),/device/code请求码、用户批准后在/oauth2/token兑换。支持绑定 RFC 8707 资源指示符;GET /device返回请求的客户端、scope、资源给持有该请求的已认证用户;token 请求可复用或收窄已批准资源但不能新增。启用后deviceCode表新增可空oauthClientId与resources字段,需重新生成并应用 Schema。此集成取代独立deviceCodeGrant()插件与共享授权配置。 - 其他 OAuth 加固:携带凭据的响应统一发送
Cache-Control: no-store与Pragma: no-cache(PR #10065,NO_STORE_HEADERS从@better-auth/core导出);client_secret_basic/client_secret_post/private_key_jwt(RFC 7523)token 端点客户端认证(PR #8836、#9657),含encodeBasicCredentials/decodeBasicCredentials与createPrivateKeyJwtClientAssertionGetter;ID token 增加at_hashclaim(OIDC Core §3.1.3.6,PR #9079);OAuth 账户在用户创建事务内创建(PR #10125);已授予 scope 单调累积不再被窄化(PR #10128);allowIdpInitiated支持无state参数发起 OAuth 的 IdP(PR #9301)。
会话、Cookie 与客户端体验
1.7 在会话层的关键改进如下:
hydrateSession(PR #8733):用服务器获取的会话预填充客户端,使useSession在首次渲染即可返回数据。- Auth 实例可 fetch(PR #9431):
Auth实例本身可被直接 fetch 调用。 useSession请求去重与 Nuxt 集成(PR #10769、#11084、#11120):React 重试挂起组件时去重在途会话请求;Vue 客户端配合 NuxtuseFetch时防止重复会话请求与 hydration 不匹配;cookie 缓存关闭但客户端仍有缓存会话 cookie 时getSession不再失败;类型安全的 NuxtuseFetch集成(PR #11085)。- 会话 Cookie 缓存 JWT 非对称签名(PR #8931):
jwt({ sessionCookieCache: true })配合session.cookieCache.strategy = "jwt",服务可用公钥而非共享密钥验证 cookie 缓存 JWT。 - Cookie 分块(PR #10019):接近浏览器单 Cookie 大小上限(长
cookiePrefix或大量缓存字段)时按块拆分;即使分块也放不下时跳过并告警,读操作回退数据库。 - 新鲜会话年龄对齐创建时间(1.6.0):会话新鲜年龄计算以创建时间而非更新时间为准。
- admin 权限与封禁即时生效(PR #10187):即使启用会话 cookie 缓存,admin 权限变更与封禁对 admin API 即时生效。
- 登出时的 Back-Channel Logout 联动(PR #9969):
secondaryStorage+session.preserveSessionInDatabase下登出会执行session.deletehooks、标记保留会话行已结束、撤销绑定 token 并派发 back-channel logout。
2FA/TOTP 与账号锁定
1.7 对双因素认证做了多项功能与安全改进:
- OTP-only 启用与可判别响应(PR #9057):
enableTwoFactor接受method参数("otp" | "totp",默认"totp"),返回带method字段的可判别响应。method: "otp"立即置twoFactorEnabled: true,要求服务端配置otpOptions.sendOTP,否则返回OTP_NOT_CONFIGURED;method: "totp"返回{ method, totpURI, backupCodes },totpOptions.disable时返回TOTP_NOT_CONFIGURED。响应形状破坏性变更:enableTwoFactor响应新增method字段。 - TOTP 验证状态列(PR #8711):
twoFactor表新增verified布尔列。首次启用创建verified: false行,verifyTOTP成功后才置真;重新启用保留verified: true,轮换 TOTP 密钥不会锁死登录;verifyTOTP拒绝verified === false的行。新列默认true,存量行无需数据迁移。 - 账户级锁定(PR #10240):2FA 验证失败次数按账户跨挑战与跨因子(TOTP、email-OTP、备用码共享一个计数器)统计,成功验证重置。默认:连续 10 次失败锁定 15 分钟,锁定期间返回
429 ACCOUNT_TEMPORARILY_LOCKED。配置项twoFactor({ accountLockout: { enabled, maxFailedAttempts, durationSeconds } })。升级后需迁移:twoFactor表新增failedVerificationCount、lockedUntil列。 - 备用码存储格式保持(PR #7231):使用备用码后,剩余码按用户配置的
storeBackupCodes策略(plain/encrypted/custom)重新保存,不再强制重新加密。 - 2FA 挑战范围回退(PR #9205):恢复 1.6.2 前的范围——2FA 仅在
/sign-in/email、/sign-in/username、/sign-in/phone-number挑战;magic link、email OTP、OAuth、SSO、passkey、SIWE、one-tap、phone-number OTP、设备授权、邮箱验证自动登录默认不再被 2FA 挑战拦截(1.7.0-beta.1 曾一度全路径强制,随后回退)。 - 2FA 方法列表返回(PR #8772):2FA 登录重定向返回
twoFactorMethods(如["totp", "otp"]),前端无需猜测渲染哪种验证 UI;onTwoFactorRedirect客户端回调收到twoFactorMethods上下文参数。
一次性 Token 与并发安全加固
1.6.17(PR #9993)针对一次性令牌与并发竞态做了系统性加固,这一主题贯穿 1.7:密码重置 token 不能并发重复改密、one-time token 不能并发重复兑换会话、同一 email/phone OTP 并发提交不能多次登录或超出尝试上限、过期的 2FA 挑战不能凭有效 TOTP/OTP/备用码完成登录、同一 2FA 挑战并发验证不能创建多个会话、设备授权轮询不能重复兑换同一已批准码、SIWE nonce 不能并发重复登录。支撑机制是新增的internalAdapter.reserveVerificationValue——原子记录单次使用标记(重放墓碑),多个并发调用恰好一个成功;数据库支撑的验证存储是原子的,仅 secondary-storage 时为 best-effort。
同期加固还包括:SIWE 消息绑定服务端状态(PR #9974,解析 ERC-4361 消息并要求 nonce/domain/address/chain ID 与服务器签发一致、校验过期/未生效时间窗)、SSO provider id 与社交提供商命名空间隔离(信任仅来自domainVerified)、组织邀请 teamId 限定到邀请所属组织、magic-link/email-OTP 发送端点强制校验 Origin(PR #10368)、OAuth state 参数对 cookie 存储 nonce 校验防 CSRF(1.6.2 PR #8949)。
其他值得关注的变更
- Cloudflare 新社交提供商(PR #9908):内置 Cloudflare 社交提供商,支持 client-secret 认证与无 secret 的 PKCE 客户端。
isPasswordCompromised(PR #11147):在自定义服务端流程中对照 Have I Been Pwned 检查密码,并忽略零出现次数的填充条目;HIBP 插件默认路径扩展覆盖更多密码设置端点(PR #9993)。- 电子邮箱枚举防护(PR #8839):
emailAndPassword.autoSignIn: false时重复注册返回合成用户(token: null)并触发onExistingUserSignUp。 - 用户名插件
displayUsername: false(PR #10330):服务端与客户端插件均可省略独立displayUsername字段;新增不可变用户名选项(PR #9240);更新资料时强制用户名唯一(1.6.0)。 - 非阻塞 scrypt(1.6.0):密码哈希改用非阻塞 scrypt,避免阻塞事件循环。
user.validateUserInfo供给门禁(PR #9864):在创建用户或关联账户前拒绝身份,覆盖所有供给用户的方法(OAuth、SSO/SAML、邮箱密码、magic link、email OTP、匿名、SIWE、手机号、admin 创建、SCIM),无持久数据库的 stateless 部署同样适用。organization.getOrganization()(PR #10397):无成员与邀请元数据地获取组织信息;listUserTeams支持userId/organizationId(PR #8977);团队满员限制在所有路径生效(PR #10002)。- 测试设施
getHttpTestInstance(PR #9657):better-auth/test新增与getTestInstance对应的 HTTP 测试实例,在 OS 分配端口绑定真实 HTTP 监听器并按发现 URL 构造 auth 实例,消除各测试文件自行拷贝的临时服务器竞态;getTestInstance默认避免生产密码哈希成本以加速测试(PR #10879)。实现见 packages/better-auth/src/test-utils/http-test-instance.ts。 - 依赖与兼容性:打包的 Zod 升级到 4.5(PR #11066,OpenAPI 必填字段与运行时校验对齐);drizzle-orm peer 收窄至
^0.45.2、kysely peer 收窄至^0.28.14(PR #9165);捆绑依赖刷新(jose、nanostores、noble crypto、SimpleWebAuthn,PR #10170);experimental: { joins: true }配置需迁移为advanced.database.joins。
升级路线图与检查清单
按仓库 1.7 升级指南与变更记录,推荐以下升级路径:
- 读升级指南:先通读 docs/content/docs/guides/1-7-upgrade-guide.mdx,按数据库(SQLite/Postgres/MySQL/SQL Server/MongoDB)执行对应 Schema 步骤,尤其是账户身份 backfill——生成式 Schema 迁移无法自动分配可信 issuer 或解决既有身份冲突。
- 版本跳跃注意:若已应用 1.7.0~1.7.2 账户 Schema,升级 1.7.3 前删除 issuer 唯一索引并将
issuer置空/删列;从 1.6 直接升级则无需账户迁移(1.7.3 兼容(providerId, accountId)识别)。 - OAuth 变更:Generic OAuth 用户迁移到
signIn.social;新增/恢复jwt()插件(MCP 场景强制);OAuth Provider 用户按 DPoP/受保护资源/back-channel logout 的 Schema 变更逐项迁移;若依赖 access token 存活超过会话结束时间,注意 Back-Channel Logout 的破坏性变更。 - 配置迁移:
experimental.joins→advanced.database.joins;oidcConfig嵌套选项 →mcp({ ... })平铺;代理仅暴露x-forwarded-host时设置advanced.trustedProxyHeaders: true。 - Schema 校验:确认生产环境
advanced.database.validateSchema的取舍(默认开启,任何表/列不匹配都会拒绝认证请求);2FA 账户锁定与 TOTPverified列需要迁移。 - 验证测试:用
getHttpTestInstance或既有getTestInstance覆盖 OAuth 回调、账户关联、2FA、一次性令牌并发等回归场景,然后执行npx auth migrate或npx auth generate并应用迁移。
Better Auth 1.7 的核心价值在于把"身份信任"从配置约定推进到协议与数据库约束层面:(issuer, accountId)身份键、OAuth 2.1 默认安全、DPoP/Back-Channel Logout、Schema 运行时校验与并发安全的单次令牌,共同构成了一套更适合生产环境与多租户场景的身份基础设施。升级时以本文梳理的破坏性变更清单逐项核对,可显著降低回归风险。
【免费下载链接】better-authThe most comprehensive authentication framework项目地址: https://gitcode.com/GitHub_Trending/be/better-auth
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考