chore(deps): update dependency better-auth to v1.6.23#1847
Open
renovate[bot] wants to merge 1 commit into
Open
chore(deps): update dependency better-auth to v1.6.23#1847renovate[bot] wants to merge 1 commit into
renovate[bot] wants to merge 1 commit into
Conversation
3916d9e to
2c5d79c
Compare
2c5d79c to
6a67797
Compare
6a67797 to
621b8f1
Compare
621b8f1 to
778ef25
Compare
778ef25 to
fa0f05b
Compare
fa0f05b to
dc8f436
Compare
dc8f436 to
c5e8a38
Compare
c5e8a38 to
cbfea1f
Compare
cbfea1f to
f808a65
Compare
f808a65 to
20f6741
Compare
20f6741 to
34b37a5
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.11→1.6.23Release Notes
better-auth/better-auth (better-auth)
v1.6.23Compare Source
Patch Changes
#9138
8581f97Thanks @vladflotsky! - Add a pre-configured Yandex provider helper for the generic OAuth plugin.Updated dependencies [
930b260]:v1.6.22Compare Source
Patch Changes
#10239
c06a56dThanks @gustavovalverde! - Magic-link and email-OTP sign-in now reset the credentials on an account whose email had never been confirmed. When verification resolves to such an account, any existing password on it is removed and its sessions are revoked before the user is signed in, so proven control of the mailbox is the source of truth for the account.If you signed up with email and password but first signed in through a magic link or email OTP rather than confirming the verification email, your password is cleared and you will need to set a new one through password reset.
#10240
3a035e9Thanks @gustavovalverde! - Add account-level lockout for two-factor verification. The attempt limit applies per account across sign-in challenges and across factors: TOTP, email-OTP, and backup codes share one counter, and a successful verification resets it.Enabled by default: an account locks for 15 minutes after 10 consecutive failed verifications, and locked attempts return
429with theACCOUNT_TEMPORARILY_LOCKEDerror code. Configure it withtwoFactor({ accountLockout: { enabled, maxFailedAttempts, durationSeconds } }).Run a database migration after upgrading: this adds
failedVerificationCountandlockedUntilcolumns to thetwoFactortable.Updated dependencies [
8bd43d9]:v1.6.21Compare Source
Patch Changes
#10212
e0762a1Thanks @bytaesu! - In root-mounted deployments, requests whose path does not start with the configuredbasePathnow return 404 instead of resolving to an endpoint.#10187
882cf9eThanks @ping-maxwell! - Admin permission changes and bans now take effect immediately for admin APIs, even when session cookie cache is enabled. Sensitive session checks also continue to work in stateless apps where signed cookies are the session record.#9939
f52e1abThanks @benpsnyder! - fixes a bug causing deviceAuthorization() throwing a ZodError at construction when called without a schema option#10196
b5bec19Thanks @Paola3stefania! - OAuth sign-up and account-link profile sync now ignore provider profile values for user fields markedinput: false. Input-allowed additional fields still persist frommapProfileToUser, and schema defaults still apply when OAuth creates a user. Apps that usedmapProfileToUserto fillinput: falsefields should set those fields in server-side provisioning code instead.#10197
816d7f9Thanks @Paola3stefania! - Google sign-in now acceptshd: "*"to allow any Google Workspace hosted domain while still rejecting tokens with no hosted-domain claim.Google One Tap now applies the configured Google hosted-domain restriction before creating a session.
#10192
239bcc8Thanks @bytaesu! - Validate PayPal user info against the verified ID token subject during social sign-in.#10228
1bc370aThanks @gustavovalverde! - The SIWE plugin no longer binds a provided email that already belongs to another account. Withanonymousset tofalse,/siwe/verifypreviously created the new account using that email even when it was already in use; it now keeps the wallet-derived address in that case, so one email cannot be attached to two accounts.#10198
570267cThanks @rachit367! - HonordisableMigrationon plugin schema tables. Tables flagged withdisableMigration: trueare now skipped bybetter-auth generate(Drizzle and Prisma output) and by the runtime migrator, instead of being emitted and created anyway. The flag was previously dropped while assembling the table list, so it had no effect.#10182
461ca6fThanks @bytaesu! - Only store display username fallbacks as usernames when they pass username validation during email sign-up.#10183
88409b0Thanks @bytaesu! - Require OAuth proxy profile callbacks to match an issued OAuth state before creating sessions.#10203
5953157Thanks @bytaesu! - Rate limiting no longer trusts multi-hopX-Forwarded-Forchains, preventing a client behind an appending proxy from spoofing the leftmost hop to bypass the per-IP rate limit. Single-value IP headers continue to work. To key the real client behind a proxy chain, setadvanced.ipAddress.trustedProxiesto your reverse-proxy IPs or CIDR ranges (the chain is walked right to left, skipping trusted hops), or pointadvanced.ipAddress.ipAddressHeadersat a single trusted client-IP header.#10191
b046f9eThanks @bytaesu! - Rate limit client requests before plugin request handlers run.#10210
ae647b4Thanks @gustavovalverde! - Two-factor verification now locks out after five wrong codes per sign-in challenge for TOTP and backup codes. Once the limit is reached the challenge is rejected withTOO_MANY_ATTEMPTS_REQUEST_NEW_CODE, and a new sign-in is required to try again.During a rolling deploy, two-factor challenges issued by the previous version may prompt the user to sign in again; this clears once the deploy completes.
Updated dependencies [
90d509e,816d7f9,570267c,5953157]:v1.6.20Compare Source
Patch Changes
#10121
21448b1Thanks @adityachaudhary99! - OAuth account-linking and create-user error logs now respect a customloggerconfigured inbetterAuth(), instead of always being written to the default console logger.#9621
8ecf238Thanks @dipan-ck! - Session refresh no longer emits a cookie Max-Age above the browser's 400-day ceiling when using a database without fractional-second precision.#8734
930f534Thanks @sleepe229! - declare inherited APIError properties to fix TypeScript inference errorsUpdated dependencies []:
v1.6.19Compare Source
Patch Changes
#10088
de4aa52Thanks @bytaesu! - Session and account cache cookies near the browser's per-cookie size limit (for example with a longcookiePrefixor many cached fields) are now split into chunks instead of being silently dropped by the browser. A cache too large to fit even when chunked is skipped with a warning rather than failing the request, so reads fall back to the database.#9995
b4b0266Thanks @ElGauchooooo! - The device authorization plugin now accepts an optionaluser_idwhen issuing a device code via/device/code, pre-binding the code to that user. Only the bound user can approve or deny the code, so a publicly visible user code can no longer be claimed by someone else.#10086
5bd5e1cThanks @gustavovalverde! - Refresh-token rotation and token revocation, two-factor backup-code regeneration, device-code claiming, and organization invitation acceptance now work on Prisma. Concurrent or repeat requests in these flows could previously return an error on Prisma instead of the expected result.On MongoDB servers older than 5.0, these flows and other guarded value updates (rate-limit window resets, API-key refills) no longer fail with an empty-update error.
@better-auth/core:incrementOnenow reports a clear error when called with noincrementand noset.#9319
581f827Thanks @ping-maxwell! - fix(last-login-method): include domain when clearing cross-subdomain cookies#10067
8407885Thanks @bytaesu! - Theoauth-popupplugin now ignores internal OAuth state fields passed through itsadditionalDataparameter, soadditionalDataonly ever carries your own custom values.#9555
c1a8a64Thanks @ChrisMGeo! - Fix invalid OpenAPI output for Better Auth callback, session, and passkey routes so client generators can consume the schema.#10071
635f190Thanks @gustavovalverde! - Auth clients exported from wrapper packages can now be emitted in TypeScript declaration builds without extra type annotations.#10070
a787e0bThanks @gustavovalverde! - Single-use verification flows no longer hang on database adapters that use a one-connection pool. This fixes magic-link verification and similar token checks in connection-limited serverless database setups.#9348
c2f718fThanks @ping-maxwell! - fix: cookie cache fallback lookup#8863
7d18175Thanks @ping-maxwell! -sendVerificationEmailwas invoked viarunInBackgroundOrAwait, which could defer work whenadvanced.backgroundTasks.handleris configured (so the handler could return 200 before the email callback finished) and, in the default path, caught and logged errors without rethrowing. User callbacks that throwAPIError(e.g. 429 from a rate limiter) were therefore not reliably reflected in the HTTP response (better-auth/better-auth#8757).Now we await
sendVerificationEmailFnso failures surface to the client with the correct status. The unauthenticated/send-verification-emailpath enforces a constant-time floor (500 ms) so that the response duration does not reveal whether the email belongs to a real unverified user.Updated dependencies [
0895993,5bd5e1c,a787e0b]:v1.6.18Compare Source
Patch Changes
#9315
9ef7240Thanks @GautamBytes! - fix OpenAPI requestBody generation for intersected and default-wrapped body schemas#9583
b21a5f7Thanks @GautamBytes! - Fix plugin-provided client methods and additional session fields not being inferred in composite monorepos.Updated dependencies [
b21a5f7]:v1.6.17Compare Source
Patch Changes
#9993
baeaa00Thanks @gustavovalverde! - When a team had a single open slot, accepting an invitation into it was wrongly rejected as over the member limit and left a dangling membership record. Two invitations accepted into a nearly-full team at the same time could also push it past its limit. Both are fixed.#9482
3e99e6cThanks @bytaesu! -admin.setUserPasswordnow creates a credential account when the target user does not have one, matching the behavior ofresetPassword. Previously the call returnedstatus: truewithout doing anything for users without an existing credential account (e.g., social-only or magic-link signups), so admins migrating users from another auth system or assigning an initial password to a social-only user can now do so directly without poking theaccounttable.96c78c3Thanks @GautamBytes! - Downgrade expected auth validation failures from error logs to warnings.#9993
baeaa00Thanks @gustavovalverde! - Captcha provider verification requests now time out after 10 seconds and fail closed, so a slow or unreachable captcha provider can no longer tie up a request indefinitely.#9993
baeaa00Thanks @gustavovalverde! - A delete-account confirmation link can no longer delete the account more than once when its callback is opened concurrently.#9991
0c3856fThanks @gustavovalverde! - Completing account deletion through/delete-user/callbacknow fails when the session has been revoked server-side, instead of proceeding within the cookie-cache window. Deployments that keep sessions only in the cookie are unaffected.#9993
baeaa00Thanks @gustavovalverde! - Polling for a device-authorization token can no longer redeem the same approved device code more than once when several polls arrive together.#9993
baeaa00Thanks @gustavovalverde! - Submitting the same email OTP from several requests at once can no longer sign in more than once or gain extra tries beyond the attempt limit.#10002
ed7b6c9Thanks @gustavovalverde! - Adding a member to a team that is already at itsmaximumMembersPerTeamlimit is now rejected on every path.addMemberwith ateamIdandadd-team-memberpreviously skipped the limit that invitation acceptance enforced, so they could push a team over its cap. A rejectedaddMemberno longer creates the organization member.#9677
e0a768cThanks @GautamBytes! - Refactorrole.authorizecontrol flow while preserving existing authorization behavior.#9987
7343284Thanks @bytaesu! - Generic OAuth sign-in works again for providers whose userinfo response has nosuboridfield whenmapProfileToUserderives the account id. An emptyidfield now falls back tosub.#9991
0c3856fThanks @gustavovalverde! -getCookieCachenow returnsnullfor an expired session instead of the stale session data. Middleware that calls it to gate access no longer treats an expired signed cookie as a live session.#9993
baeaa00Thanks @gustavovalverde! - The Have I Been Pwned plugin now checks submitted passwords against the breach database on more password-setting endpoints by default, including the email-OTP and phone-number reset-password routes and the admin create-user and set-user-password routes. A breached password can no longer be set through those routes when the plugin is enabled with its default paths.#9987
7343284Thanks @bytaesu! - Preserve the fresh account cookie issued while switching users in the same browser instead of expiring it from stale request cookie state.#9991
0c3856fThanks @gustavovalverde! - Expired MCP access tokens are no longer accepted. A protected MCP resource now rejects a bearer token once it has expired, both on the server and through the remote client. A refresh token is accepted only when the original authorization included theoffline_accessscope.#9991
0c3856fThanks @gustavovalverde! - The multi-sessionset-activeandrevokeendpoints now act only on the session the caller holds a signed cookie for. A request could previously activate or revoke a different session by naming its token in the request body without holding that session's cookie.#9890
d9c526bThanks @bytaesu! - Add an experimentaloauthPopupplugin (withoauthPopupClientandsignIn.popup) for popup-based OAuth sign-in. It lets an app sign in inside a cross-site iframe by completing OAuth in a popup and handing the session token back to the opener, where thebearerplugin authenticates with it. The API may change while it is experimental.#9991
0c3856fThanks @gustavovalverde! - The OIDC provider's RP-initiated logout endpoint (/oauth2/endsession) no longer logs a user out, or revokes their OAuth tokens, in response to a cross-site GET that carries only a session cookie. Logout authenticated by a validid_token_hintis unaffected.#10003
fdef997Thanks @gustavovalverde! - Google One Tap now requires a configured Google client ID and rejects the sign-in callback when none is set. A Google ID token issued for a different application is no longer accepted. Set the client ID on theoneTapplugin or onsocialProviders.google.#9993
baeaa00Thanks @gustavovalverde! - A one-time token can no longer be redeemed for a session more than once when redeemed concurrently.#9993
baeaa00Thanks @gustavovalverde! - A password reset token can no longer change the password more than once when used from several requests at the same time.#9993
baeaa00Thanks @gustavovalverde! - Submitting the same phone-number OTP from several requests at once can no longer sign in more than once or gain extra tries beyond the attempt limit.#9993
baeaa00Thanks @gustavovalverde! - Concurrent requests can no longer slip past the configured rate limit. The in-memory rate-limit store no longer grows without bound, and the database backend removes expired entries on its own. A custom rate-limit storage may implement a new optionalconsumemethod for strict enforcement; without it, the previous behavior is kept and a one-time warning is logged.#9987
7343284Thanks @bytaesu! - Deleting a team no longer breaks its pending invitations. The removed team is dropped from those invitations, which stay valid for their remaining teams or as plain organization-level invitations. Accepting an invitation that still references a missing team fails without consuming the invitation.#9993
baeaa00Thanks @gustavovalverde! - AddinternalAdapter.reserveVerificationValue. It atomically records a single-use marker (such as a replay tombstone) so that exactly one of several concurrent callers succeeds and the rest observe that the marker is already taken. Database-backed verification storage is atomic; secondary-storage-only verification is best-effort.#8760
8960f5fThanks @gustavovalverde! - Session refreshes now avoid duplicate/get-sessionrequests from focus and other browser session events. Client hooks keep stable data references when refetches return unchanged data, reducing unnecessary renders. Unmounting during an in-flight session request no longer leaves session state stuck in a loading state.#9993
baeaa00Thanks @gustavovalverde! - A Sign-In with Ethereum nonce can no longer be used to sign in more than once when submitted from several requests at the same time.#9979
5c289b5Thanks @SferaDev! - Stateless OAuth deployments can now read account info, access tokens, and refresh tokens after different server instances handle sign-in and later requests. Session refresh also keeps the OAuth account cookie instead of clearing it in that case.#9990
1dbf5bbThanks @gustavovalverde! - Hardens how requests are trusted across several flows. Rate limiting is now enforced even when a client IP cannot be determined, instead of being skipped. WhenbaseURLis not configured, password-reset and verification links use the current request's host rather than the host of the first request the server handled, and a request-scopedtrustedOriginscallback no longer affects other concurrent requests. The OAuth proxy, Google One Tap, and the Expo authorization proxy reject redirect and callback targets that are not intrustedOrigins. Google reCAPTCHA and Cloudflare Turnstile accept optionalexpectedActionandallowedHostnamesto reject tokens minted for a different action or hostname. Server-side fetches reject additional reserved IPv6 ranges, and malformed redirect parameters return a 400 instead of a 500.#9993
baeaa00Thanks @gustavovalverde! - An expired two-factor sign-in challenge can no longer complete login with a valid TOTP, OTP, or backup code, and the same challenge can no longer create more than one session when verified concurrently.#9993
baeaa00Thanks @gustavovalverde! - Submitting the same two-factor OTP from several requests at once can no longer sign in more than once or gain extra tries beyond the attempt limit.#9777
59e0ccbThanks @GautamBytes! - ClientupdateSessioncalls now accept inferred custom session fields frominferAdditionalFields.#9962
b803c61Thanks @Bekacru! - Validate roles when updating an organization member. Roles are now normalized into individual tokens and checked against the configured static and dynamic roles, so unknown or malformed role values are rejected instead of being persisted.Updated dependencies [
baeaa00,baeaa00,baeaa00,7343284,baeaa00,baeaa00,fdef997,baeaa00,baeaa00,fdef997,baeaa00,1dbf5bb,fdef997]:v1.6.16Compare Source
Patch Changes
#9974
cb1cbfaThanks @Bekacru! - Guard protected user fields in the admin plugin behind their dedicated permissions./admin/create-usernow requiresuser:set-rolewhen aroleis supplied (top-level or viadata.role), validates requested roles against the configured roles, requiresuser:banfor ban fields passed indata, and no longer letsdataoverrideemail,name, orrole./admin/update-usernow requiresuser:banforbanned/banReason/banExpires(revoking the user's sessions when banning and rejecting self-bans), requires the newuser:set-emailpermission foremail/emailVerified(with email validation, lowercasing, and uniqueness checks), and rejectspasswordupdates in favor of/admin/set-user-password. If you use a custom access control, addset-emailto your statements and grant it (andban) to roles that should be able to change those fields throughupdate-user.#9974
cb1cbfaThanks @Bekacru! - Require a provider account id when signing in through generic OAuth. The default userinfo handler previously fell back to an empty string when the provider response had nosub(orid), and the callback never checked the resolved account id. With certain non-OIDC providers that omitsub, accounts could be stored under the same empty id and a later sign-in could resolve to an existing account. The generic OAuth callback now rejects sign-in when no account id can be resolved, the default userinfo handler returns no profile when neithersubnoridis present, and the built-in OAuth callback also rejects an empty account id.#9974
cb1cbfaThanks @Bekacru! - Scope organization invitation team IDs to the invited organization.createInvitationnow validates that every requestedteamIdbelongs to the invitation's organization regardless of whetherteams.maximumMembersPerTeamis set, andacceptInvitationre-checks each stored team's organization before adding team membership. Previously, with the default unlimited team size, a team ID from another organization could be stored on an invitation and applied on acceptance.#9973
87e7aa5Thanks @gustavovalverde! - Email sign-in and sign-up now validate theOriginorRefererheader againsttrustedOriginseven when the request carries no cookies. Requests that send noOrigin/Refererheader and no Fetch Metadata (such as curl or server-to-server clients) are unaffected. A non-browser client that sends an untrustedOrigin/Refererwithout cookies now receives a 403 and must add that origin totrustedOrigins.#9974
cb1cbfaThanks @Bekacru! - Require/refresh-tokento only trust the account cookie when itsuserId,providerIdand (when supplied)accountIdmatch the resolved session user.#9967
893cf6cThanks @gustavovalverde! - Deleting a session now immediately stops/update-sessionand the account token endpoints (/get-access-token,/refresh-token,/account-info) from accepting it, when cookie cache is enabled alongside a database or secondary storage. Before, these routes kept serving the deleted session from the cached cookie until the cache expired. Deployments that store the session only in the cookie are unaffected.#9974
cb1cbfaThanks @Bekacru! - Bind the SIWE signed message to server state before creating a session. Previously/siwe/verifyonly checked that a nonce row existed for the wallet address and then delegated entirely toverifyMessage. Since the documentedverifyMessage(viem) performs signature recovery only — without inspecting the message body — a signature the wallet produced for a different message (an earlier nonce, another domain, or arbitrary content) could also satisfy verification against a freshly minted nonce.The plugin now parses the ERC-4361 message itself and requires its nonce, domain, address, and chain ID to match the server-issued nonce and configured
domain, and enforces the message'sExpiration Time/Not Beforebounds, before verifying the signature.messagemust now be a valid ERC-4361 message (which all standard SIWE clients produce); non-conforming or mismatched messages are rejected with a 401 (UNAUTHORIZED_SIWE_MESSAGE_MISMATCH,UNAUTHORIZED_SIWE_MESSAGE_EXPIRED, orUNAUTHORIZED_SIWE_MESSAGE_NOT_YET_VALID).verifyMessageimplementations should continue to perform signature recovery only.#9974
cb1cbfaThanks @Bekacru! - Separate SSO provider ids from the account-linking provider namespace used for social/OAuth providers. Previously an SSO provider registered with an id matching a configuredaccountLinking.trustedProvidersentry (e.g.google) was treated as a trusted provider and could implicitly link to an existing verified account with the same email.SSO registration now rejects provider ids that collide with a configured social provider, a
trustedProvidersentry, or a reserved built-in id. In addition, the OIDC and SAML callbacks no longer derive trust from atrustedProvidersname match — SSO trust comes solely from verified domain ownership (domainVerified).handleOAuthUserInfogains atrustProviderByNameoption (defaulttrue, preserving social-provider behavior) that the SSO plugin sets tofalse.#9965
5e49c56Thanks @gustavovalverde! - PassingactiveOrganizationId,activeTeamId, orimpersonatedByto/update-sessionnow returns a 400. Change these plugin-managed session fields through their dedicated endpoints instead, such asorganization.setActive.Updated dependencies [
cb1cbfa,cb1cbfa,cb1cbfa,cb1cbfa,cb1cbfa,cb1cbfa]:v1.6.15Compare Source
Patch Changes
#9875
1012b69Thanks @WilsonnnTan! - The admin plugin'sunbanUser,setRoleandadminUpdateUserendpoints used to callinternalAdapter.updateUserwithout checking that the target user existed, so when the caller passed an unknown id the underlying database error (for example Prisma'sP2025) bubbled up as a generic HTTP 500. those endpoints now mirror the existing guard inbanUser: look the user up viafindUserById, and throw a cleanNOT_FOUND(USER_NOT_FOUND) when no row is returned. Closes #9800.#9865
ad60333Thanks @ping-maxwell! - list-session endpoint now requires a fresh-age session check.#9811
0933c05Thanks @zeroknowledge0x! - Restore Kysely 0.28 and 0.29 compatibility for SQLite dialect introspection. The dialects now mirror Kysely's stable migration table names locally, avoiding strict ESM build failures in Turbopack without forcing consumers onto Kysely 0.29.#9919
b0ddfd3Thanks @gustavovalverde! - Run configured hooks through the whole OAuth sign-in flowhooks.before/hooks.afterconfigured on the auth instance now run for the OAuth authorization that continues after a user signs in, selects an account, or consents. They were being skipped there.Headers or cookies a
hooks.beforesets before returning its own response are no longer dropped, and ahooks.afterthat throws anAPIErrorno longer loses either its cookies or the error's headers.Updated dependencies []:
v1.6.14Compare Source
Patch Changes
#9877
2d9781aThanks @gustavovalverde! - Restore the normal emailed-invitation flow while documenting the stricter verification posture for organization invitations.Client-side
listUserInvitationsnow always requires a verified session email because it enumerates invitation IDs fromsession.user.email. The `requireEmailVeConfiguration
📅 Schedule: (UTC)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR was generated by Mend Renovate. View the repository job log.