fix(deps): update dependency better-auth to v1.6.11#284
Open
renovate[bot] wants to merge 1 commit into
Open
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #284 +/- ##
=======================================
Coverage 54.06% 54.06%
=======================================
Files 128 128
Lines 4056 4056
Branches 828 828
=======================================
Hits 2193 2193
Misses 1860 1860
Partials 3 3 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
domus-cron | 65fd0cc | Commit Preview URL Branch Preview URL |
May 12 2026, 06:03 PM |
959e4a4 to
7b221bc
Compare
7b221bc to
b1b93e2
Compare
b1b93e2 to
67742f9
Compare
67742f9 to
65fd0cc
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR contains the following updates:
1.6.5→1.6.11Release Notes
better-auth/better-auth (better-auth)
v1.6.11Compare Source
Patch Changes
#9568
0cbddb8Thanks @gustavovalverde! - AddinternalAdapter.consumeVerificationValue(identifier): atomically consume a verification row keyed by identifier. The first concurrent caller receives the row; later racers receivenull. Backed by a newDBAdapter.consumeOneprimitive implemented natively per adapter (memory, mongo, drizzle, kysely, prisma), with atransaction(findMany + delete)factory fallback.SecondaryStorage.getAndDeleteis added as an optional companion; Redis ships it via an atomic Lua get-and-delete operation for compatibility with Redis versions before 6.2.#9162
a26333bThanks @ping-maxwell! - fix: cleanup sessions when admin, anonymous, or SCIM deletes a user#9573
99a254aThanks @gustavovalverde! - fix(device-authorization): require verify-time ownership claim for approve/denyPending device codes were not bound to the user who entered the code on the verification page until approval, leaving a window where any authenticated user could approve or deny another user's pending code by knowing the
user_code.GET /devicenow claims the pending row for the calling session, andPOST /device/approveandPOST /device/denyrequire the calling session to match the claimed owner. Custom verification pages must be served to an authenticated session for the flow to succeed.#8948
ee93485Thanks @ping-maxwell! - fix: add error code to change-email-disabled#9572
5f09d56Thanks @gustavovalverde! - Fix race condition in themagic-linkplugin's verify handler that allowed two concurrent requests to mint two sessions from the same single-use token. The handler now consumes the verification row atomically viainternalAdapter.consumeVerificationValue, so a given magic link mints at most one session regardless of concurrency. TheallowedAttemptsoption is retained for backward compatibility but no longer multiplies successful redemptions; tokens are single-use. The second-redeem error code changes fromATTEMPTS_EXCEEDEDtoINVALID_TOKEN(the token no longer exists after consumption).b4bc65aThanks @gustavovalverde! - Fix race condition in the OAuth authorization-code grant: two concurrent token-exchange requests sharing the samecodecould both pass the find step before either delete completed and each mint an independent access/refresh/id token set. Theauthorization_codehandler in@better-auth/oauth-provider, plus the legacyoidc-providerandmcpplugins inbetter-auth, now consume the verification row atomically viainternalAdapter.consumeVerificationValue. The first caller mints tokens; concurrent racers receiveinvalid_grant(RFC 6749 §5.2). Malformed-verification-value branches in@better-auth/oauth-providerpreviously returned a project-specificinvalid_verificationcode; those are nowinvalid_grantso spec-compliant clients can branch on the standard code.#9578
da7e50bThanks @gustavovalverde! -handleOAuthUserInfo(used by every social provider, generic-oauth, oauth-proxy, SSO OIDC and SAML, and idToken sign-in) implicitly linked a returning OAuth identity into a local user row whenever the IdP'semail_verifiedclaim was true or the provider was trusted. The local row's ownemailVerifiedflag was read only to flip it after linking, never as a precondition.POST /sign-up/emailcreates rows withemailVerified: falsefor any caller, so an attacker who pre-registered a victim's email at the application could wait for the legitimate user's first OAuth sign-in: the IdP's verified claim was treated as ownership proof, and the victim's IdP identity was linked into the attacker-owned row.The implicit-link gate now requires
dbUser.user.emailVerified === truein addition to the provider trust check by default. A newaccount.accountLinking.requireLocalEmailVerifiedoption (defaulttrue) is the public surface for this gate. Apps whose users sign up via OAuth without verifying their email locally can opt back into the legacy behavior withaccount: { accountLinking: { requireLocalEmailVerified: false } }; understand the takeover risk before doing so. The option is@deprecated; a FIXME at each gate site points at the next-minor follow-up onnextthat drops the option and makes the gate unconditional.The
one-tapplugin honored its own copy of the gate and was updated identically:requireLocalEmailVerifiedandaccountLinking.disableImplicitLinkingboth apply on/one-tap/callback. Theemail_verifiedclaim from the Google ID token is now normalized viatoBooleanso a string"false"is treated as falsy.Test fixtures across
admin,oidc-provider,mcp,generic-oauth,last-login-method, andoauth-providersuites now mark usersemailVerified: truevia adatabaseHooks.user.create.beforehook (or thedisableTestUseropt-in on the oauth-provider RP) so the suites continue to exercise their role/flow logic rather than the new gate.#9507
a1c9f3cThanks @GautamBytes! - Preserve exact access-control role statement types so predefined organization roles expose only their configured permissions in TypeScript.#9577
23094a6Thanks @gustavovalverde! - The organization plugin's invitation recipient endpoints (acceptInvitation,rejectInvitation,getInvitation,listUserInvitations) treatedinvitation.email.toLowerCase() === session.user.email.toLowerCase()as proof that the calling user owned the invited address. A session-authenticated user whose email matched but was never verified passed the gate, so anyone who could pre-register an unverified account at a victim's email could accept invitations addressed to that email. TherequireEmailVerificationOnInvitationopt-in option closed the gap only when explicitly enabled and did not protectgetInvitationorlistUserInvitationsat all.The gate is now applied on all four recipient endpoints and the
requireEmailVerificationOnInvitationoption default flips fromfalsetotrueso existing apps are secure by default. Apps that intentionally accept invitations from unverified accounts can keep the legacy permissive behavior withorganization({ requireEmailVerificationOnInvitation: false }), but they should understand the takeover risk before doing so. Server-side calls tolistUserInvitationswithctx.query.emailand no session continue to bypass the gate (the caller is trusted).The option is
@deprecated. The next-minor release onnextremoves it entirely and makes the gate unconditional.#9548
142b86cThanks @dipan-ck! - anonymous plugin now correctly calls onLinkAccount when email verification triggers auto sign-in#9576
1f2ff42Thanks @gustavovalverde! - fix(oidc-provider, mcp): authenticate confidential clients on refresh_token grant and harden secret comparisonRefresh-token grants on the legacy
oidc-providerandmcpplugins now require the registeredclient_secretfrom confidential clients, matching theauthorization_codepath. Public clients (wherecode_verifiersubstitutes for the secret on the auth-code grant) continue to skip secret validation. Secret comparisons across both plugins now use constant-time equality. The/mcp/tokenendpoint no longer emits a wildcard CORSAccess-Control-Allow-Origin: *header.These plugins are deprecated in favor of
@better-auth/oauth-provider, which is unaffected. New deployments should adopt the replacement; this patch keeps existing deployments protected while migrating.#9575
699b09aThanks @gustavovalverde! - fix(oidc-provider, mcp): drop"none"from advertised signing algorithms, defaultallowPlainCodeChallengeMethodtofalse, and reject missing PKCE methodThe legacy
oidc-providerandmcpplugins now follow OAuth 2.1 (RFC 9700) on three protocol gates:id_token_signing_alg_values_supported(oidc-provider, mcp) andresource_signing_alg_values_supported(mcp) no longer include"none". Relying parties that negotiate from this list will no longer be steered toward unsigned tokens.allowPlainCodeChallengeMethoddefaults tofalse. Callers who needplainPKCE must opt in explicitly.code_challenge_methodto"plain"before the allowlist check. A request that providescode_challengewithoutcode_challenge_methodis now rejected withinvalid_request; the inverse case (code_challenge_methodwithoutcode_challenge) is also rejected so no inconsistent PKCE state is persisted on the authorization code record.Non-breaking for callers who never relied on
"none"advertisement or the plain default. Callers who explicitly setallowPlainCodeChallengeMethod: truekeepplainon the allowlist and retain the legacy "missing method defaults to plain" behavior for backward compatibility, so existing integrations that opted into plain PKCE continue to work. The next-minor onnextwill drop both theplainallowlist entry and this fallback; until then, the option is the single explicit knob for legacy behavior. Migrate to@better-auth/oauth-providerfor the canonical, spec-aligned implementation.Updated dependencies [
0cbddb8,c6918ec,da7e50b,b0ef96f,e21d744]:v1.6.10Compare Source
Patch Changes
#8339
1e0f26dThanks @ping-maxwell! - fix(captcha): breaks email-otp flow#9484
8c1e917Thanks @ping-maxwell! - fix: warn for cookie-plugin being last in array#9437
b2d655cThanks @cyphercodes! - Allow organization invitation role input types to accept dynamic access control roles.#9497
09f1327Thanks @bytaesu! - Endpoints that set cookies before redirecting (such as social sign-incallbacks and magic-link verification) no longer emit each
Set-Cookieentry twice on the response.
#9387
906b7b3Thanks @bytaesu! - The bearer plugin now produces a single entry per cookie name when mergingits session token into the request
Cookieheader. Previously the mergedheader could carry two entries for the same name if the request already
had a stale session cookie, which would surface to downstream code that
picks the first occurrence.
#9475
e9c978eThanks @jaydeep-pipaliya! - fix(username): respect callbackURL on/sign-in/usernameThe endpoint accepted a
callbackURLbody field but ignored it, soauthClient.signIn.username({ ..., callbackURL })silently did nothingwhile
authClient.signIn.emailredirected as expected. The handler nowsets a
Locationheader whencallbackURLis provided and returns{ redirect, url }alongsidetoken/user, matching the email flow.#9440
e71aad3Thanks @cyphercodes! - Clear organization active hook state after sign-out souseActiveMemberRoledoes not retain a previous user's role in SPA sign-out/sign-in flows.#9402
80a655dThanks @onmax! - Revalidate the client session after admin impersonation starts or stops.#9503
15ff28aThanks @bytaesu! -internalAdapter.deleteAccountparameter renamed fromaccountIdtoidto reflect that it queries by primary key, not theaccountIdcolumn. No runtime behavior change.#9268
88a7c67Thanks @ping-maxwell! - fix: openAPI schema for POST /sign-in/social mis-declares required fields#8839
9a7b51dThanks @dipan-ck! - Apply email enumeration protection whenemailAndPassword.autoSignInis false. Duplicate sign-ups now return a synthetic user (token: null) and triggeronExistingUserSignUp, and new sign-ups skip auto sign-in (token: null)—even withoutrequireEmailVerification, aligning with the docs.#9065
1b25902Thanks @ping-maxwell! - non-ASCII error_description in generic-oauth callback routes causes TypeError on redirect#9349
cf59136Thanks @ping-maxwell! - fix(organization): re-export field types to prevent TS2742 with additionalFields#9453
a597ee0Thanks @mausic! - The organization plugin'scancelPendingInvitationsOnReInviteoption now actually cancels the prior pending invitation when re-inviting the same email. Previously the option had no effect — re-inviting always failed withUSER_IS_ALREADY_INVITED_TO_THIS_ORGANIZATION#9456
fc02cedThanks @cyphercodes! - Reject OAuth callbacks when provider user info omits the account id to avoid linking accounts under the literalundefinedid.#9461
9f1ef1fThanks @cyphercodes! - ExposeauthClient.siwe.getNonce()as a compatibility alias for the SIWE nonce endpoint.#9369
36ef808Thanks @ping-maxwell! - fix: incorrect email casing across one-tap, email-otp & email-verification#9239
c1336c5Thanks @GautamBytes! - Fixorganization.setActiveTeamso it only accepts teams from the current active organization.#7764
3a9a2c3Thanks @programming-with-ia! - chore: expose refreshUserSessions on internal adapter#9521
fde0432Thanks @ping-maxwell! - fix: improve link accessibility issuesUpdated dependencies [
2220a6d]:v1.6.9Compare Source
Patch Changes
815ecf6]:v1.6.8Compare Source
Patch Changes
#9253
856ab24Thanks @baptisteArno! - fix(organization): allow passing id throughbeforeCreateTeamandbeforeCreateInvitationMirrors #4765 for teams and invitations:
adapter.createTeamandadapter.createInvitationnow passforceAllowId: true, so ids returned from the respective hooks survive the DB insert.#9331
9aa8e63Thanks @gustavovalverde! - fix(oauth): supportmapProfileToUserfallback for providers that may omit emailSocial sign-in with OAuth providers that may return no email address (Discord phone-only accounts, Apple subsequent sign-ins, GitHub private emails, Facebook, LinkedIn, and Microsoft Entra ID managed users) can now be unblocked by synthesizing an email inside
mapProfileToUser. Rejection logger messages now point at this workaround and at the new "Handling Providers Without Email" docs section.Provider profile types now reflect where
emailcan benullor absent:DiscordProfile.emailisstring | nulland optional (absent when theemailscope is not granted)AppleProfile.emailis optionalGithubProfile.emailisstring | nullFacebookProfile.emailis optionalFacebookProfile.email_verifiedis optional (Meta's Graph API does not include this field)LinkedInProfile.emailis optionalLinkedInProfile.email_verifiedis optionalMicrosoftEntraIDProfile.emailis optionalTypeScript consumers who previously dereferenced
profile.emaildirectly insidemapProfileToUserwill see a compile error that matches the runtime reality; use a nullish-coalescing fallback (profile.email ?? ...) or null-check the field.Sign-in still rejects with
error=email_not_found(social callback) orerror=email_is_missing(Generic OAuth plugin) when neither the provider normapProfileToUserproduces an email. First-class support for users without an email, keyed on(providerId, accountId)per OpenID Connect Core §5.7, is tracked in #9124.Updated dependencies [
9aa8e63]:v1.6.7Compare Source
Patch Changes
#9211
307196aThanks @stewartjarod! - PreserveSet-Cookieheaders accumulated onctx.responseHeaderswhen an endpoint throwsAPIError. Cookie side-effects fromdeleteSessionCookie(and anyctx.setCookie/ctx.setHeadercalls before the throw) are no longer silently discarded on the error path.#9292
4f373eeThanks @gustavovalverde! - Accept an array of Client IDs on providers that verify ID tokens by audience (Google, Apple, Microsoft Entra, Facebook, Cognito). The first entry is used for the authorization code flow; all entries are accepted when verifying an ID token'saudclaim, so a single backend can serve Web, iOS, and Android clients with their platform-specific Client IDs.Passing a single string keeps working; no migration needed.
Also exports
getPrimaryClientIdfrom@better-auth/core/oauth2for provider authors: it returns the primary Client ID (the raw string, or the entry at array index 0), paired withclientSecretfor the authorization code flow. Providers now reject empty arrays, empty strings, and missing config at sign-in time instead of silently producing a malformed authorization URL. Google, Apple, and Facebook require bothclientIdandclientSecretbecause each of those providers mandates a client secret for their server-side code exchange. Microsoft Entra and Cognito only requireclientId, since both support public-client flows with PKCE alone (no secret).#9293
e1b1cfcThanks @gustavovalverde! - Guard againstc.bodybeing undefined inparseState. Callback requests that arrive as GET leavec.bodyunset in some runtimes, which causedc.body.stateto throw aTypeErrorbefore the existing error redirect could run. The state lookup now short-circuits on the query parameter and falls back toc.body?.statesafely, so a callback without a state parameter redirects to the error page instead of crashing.#4894
d053a45Thanks @Kinfe123! - FirecallbackOnVerificationwhen a phone number is verified withupdatePhoneNumber: true. The callback previously only ran on initial verification, so consumers relying on it (e.g. to sync verified numbers to an external system) would miss the event when an authenticated user changed their number.Updated dependencies [
307196a,4a180f0,4f373ee]:v1.6.6Compare Source
Patch Changes
#9214
4debfb6Thanks @ping-maxwell! - fix(custom-session): use coerced boolean for disableRefresh query param validation#9235
9ea7eb1Thanks @bytaesu! - Preserve thePartitionedattribute when thecustomSessionplugin and framework integrations forwardSet-Cookieheaders.#9266
ab4c10fThanks @ping-maxwell! - fix(organization): infer team additional fields correctly#9219
a61083eThanks @bytaesu! - Allow removing a phone number withupdateUser({ phoneNumber: null }). The verified flag is reset atomically. Changing to a different number still requires OTP verification throughverify({ updatePhoneNumber: true }).#9226
e64ff72Thanks @gustavovalverde! - Consolidate host/IP classification behind@better-auth/core/utils/hostand close several loopback/SSRF bypasses that the previous per-package regex checks missed.Electron user-image proxy: SSRF bypasses closed (
@better-auth/electron).fetchUserImagepreviously gated outbound requests with a bespoke IPv4/IPv6 regex that missed multiple vectors. All of the following were reachable in production and are now blocked:http://tenant.localhost/and other*.localhostnames (RFC 6761 reserves the entire TLD for loopback).http://[::ffff:169.254.169.254]/(IPv4-mapped IPv6 to AWS IMDS, the classic SSRF bypass).http://metadata.google.internal/,http://metadata.goog/(GCP instance metadata).http://instance-data/,http://instance-data.ec2.internal/(AWS IMDS alternate FQDNs).http://100.100.100.200/(Alibaba Cloud IMDS; lives in RFC 6598 shared address space100.64/10, which the old regex did not cover).http://0.0.0.0:PORT/(the Linux/macOS kernel routes the unspecified address to loopback: Oligo's "0.0.0.0 Day").http://[fc00::...]/,http://[fd00::...]/(IPv6 ULA per RFC 4193) and IPv6 link-localfe80::/10, neither of which the regex recognized.Documentation ranges (RFC 5737 / RFC 3849), benchmarking (
198.18/15), multicast, and broadcast are also now rejected.better-auth:0.0.0.0is no longer treated as loopback. The previousisLoopbackHostimplementation inpackages/better-auth/src/utils/url.tsclassified0.0.0.0alongside127.0.0.1/::1/localhost.0.0.0.0is the unspecified address, not loopback; treating it as such lets browser-origin requests reach localhost-bound dev services (Oligo's "0.0.0.0 Day"). The helper now accepts the full127.0.0.0/8range and any*.localhostname, and rejects0.0.0.0.better-auth: trusted-origin substring hardening.getTrustedOriginspreviously usedhost.includes("localhost") || host.includes("127.0.0.1")when deciding whether to add anhttp://variant for a dynamicbaseURL.allowedHostsentry. Misconfigurations likeevil-localhost.comor127.0.0.1.nip.iowould incorrectly gain an HTTP origin in the trust list. The check now uses the shared classifier, so only real loopback hosts get the HTTP variant.@better-auth/oauth-provider: RFC 8252 compliance.127.0.0.0/8range (not just127.0.0.1) plus[::1], with port-flexible comparison. Port-flexible matching is limited to IP literals; DNS names such aslocalhostcontinue to use exact-string matching per §8.3 ("NOT RECOMMENDED" for loopback).validateIssuerUrluses the shared loopback check rather than a two-hostname literal comparison.New module:
@better-auth/core/utils/host. ExposesclassifyHost,isLoopbackIP,isLoopbackHost, andisPublicRoutableHost. One RFC 6890 / RFC 6761 / RFC 8252 implementation that handles IPv4, IPv6 (including bracketed literals, zone IDs, IPv4-mapped addresses, and 6to4 / NAT64 / Teredo tunnel forms with embedded-IPv4 recursion), and FQDNs, with a curated cloud-metadata FQDN set. All bespoke loopback/private/link-local checks across the monorepo now route through it.Updated dependencies [
b5742f9,a844c7d,e64ff72]:Configuration
📅 Schedule: (in timezone Asia/Makassar)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about these updates again.
This PR was generated by Mend Renovate. View the repository job log.