NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
pub.dev
A Flutter client package for integrating with Better Auth - a secure authentication platform.
Last release 1 months ago
04 Sep 2026
Ships unpredictably
gaps range from 9 days to 13 months
Nearly every release is documented
notes for 10 of 10 stable releases
Nothing withdrawn
no release was ever pulled
1 years old
10 releases · first in 2025
One column per month.
Aligns the client with Better Auth server 1.7 (backend in vigilant-spoon updated 1.6.9 → 1.7.2, including the extracted @better-auth/passkey and @bett
Aligns the client with Better Auth server 1.7 (backend in
vigilant-spoon updated 1.6.9 → 1.7.2, including the extracted
@better-auth/passkey and @better-auth/api-key packages).
setPassword (POST /set-password) removed — the route no longer exists
in 1.7. Use the reset-password flow instead.unlinkAccount now requires the local accountId from listAccounts;
the old providerId-based call is rejected by 1.7 servers.TwoFactorEnableResponse.totpURI is nullable and carries the new
method field — OTP-method enables return no totpURI/backup codes.TwoFactorEnableBody accepts method: "otp" | "totp".Account.issuer, accountInfo()
(GET /account-info), and explicit selectors on getAccessToken /
refreshToken (accountId or useAccountCookie).updateSession, deviceInfo (GET /device),
errorCodes (GET /error), oauthCallbackPost
(POST /callback/{provider} — e.g. Apple form_post), getOrganization,
getActiveMemberRole.deleteUser, email-OTP requestEmailChange
/ changeEmail / checkVerificationOtp / requestPasswordReset, admin
getUser / updateUser, organization getOrganization /
getActiveMemberRole.updateUser accepts username, displayUsername, phoneNumber.forgotPassword calls POST /request-password-reset
(/forget-password removed in 1.7).openApiReference calls GET /open-api/generate-schema
(/reference/openapi.json removed in 1.7).GET, matching the extracted
1.7 passkey package.Riverpod 3 support via the opt-in package:better_auth_flutter/riverpod.dart library (backed by flutter_riverpod: ^3.0.0): betterAuthStateProvider (Str
package:better_auth_flutter/riverpod.dart
library (backed by flutter_riverpod: ^3.0.0): betterAuthStateProvider
(StreamProvider<AuthState>, mirroring authStateChanges with its immediate
replay), betterAuthClientProvider, currentUserProvider, and
isAuthenticatedProvider. Importing it is optional — apps that do not use
Riverpod pay nothing for it.flutter_riverpod
3.x, flutter_secure_storage 11.x, freezed 4.x (generated code
regenerated), build_runner, retrofit_generator, json_annotation.
This raises the minimum toolchain to Dart ^3.13.0 / Flutter >=3.47.0.package:better_auth_flutter/plugins/passkey.dart,
client.passkey): registration/authentication options + verification,
passkey listing, rename, and deletion, with typed PasskeyRecord models.User/Session collect unknown server
keys into additionalFields instead of dropping them, with a typed
field<T>() accessor; the raw sign-up/sign-in/update variants
(signUpEmailRaw, signInEmailRaw, signInUsernameRaw, updateUserRaw)
accept flat-merged custom keys for writing.isUsernameAvailable), password verification
(verifyPassword), and Result.data/Result.error getters (ResultX).BetterAuthProvider re-fetches the session when
the device regains connectivity (refreshOnReconnect: false to opt out).enableWebCredentials (browser cookie handling for
cross-origin requests), redirectToUrl, and currentOrigin.MISSING_OR_NULL_ORIGIN.
Better Auth rejects any cookie-bearing non-GET request that arrives without an
Origin header, and it reads only that standard header — the flutter-origin
header this package sends is for the Expo-style proxy and is not consulted by
the origin check. Native HTTP clients never set Origin on their own, so
every mutating call made with a session cookie (update-user, delete-user,
change-password, …) was refused, while sign-in kept working because it
carries no cookie yet. initialize now derives Origin from the url you
pass it. Better Auth always trusts its own baseURL origin, so this needs no
trustedOrigins change on the server. Skipped on web, where the browser owns
the header; a caller-supplied dio keeps its own value if it sets one.Security fixes, a reachable public API, reactive auth state, and working bearer mode.
Security fixes, a reachable public API, reactive auth state, and working bearer mode.
This release is breaking. Every breaking change is bundled here so you migrate once. See the migration table at the end.
Bearer authentication that actually works.
initialize(mode: AuthMode.bearer) captures the token from the
set-auth-token response header and sends it as Authorization: Bearer.
Previously nothing read that header, so bearer mode could not obtain a token
at all. TokenStorage<String> (default InMemoryTokenStorage) controls
persistence, and BearerOptions.requireSignature is now honored.
Session refresh. BetterAuthFlutter.refreshSession() (single-flight),
automatic refresh on app resume via BetterAuthProvider (throttled;
refreshOnResume: false to opt out), and transparent deferSessionRefresh
handling (SessionResponse.needsRefresh → follow-up POST).
SecureStorage, backed by flutter_secure_storage with iOS keychain
chunking — now the default cookie store on native platforms. Hive and
SharedPreferences remain available as opt-in backends.
Typed social sign-in. SocialProvider enum and SignInSocialBody;
signInSocial now takes the typed body, with signInSocialRaw for providers
outside the enum (e.g. genericOAuth).
Browser-redirect social sign-in. initialize(callbackUrlScheme:) and
BetterAuthFlutter.signInWithProvider(...) drive the flutter_web_auth_2
flow and return a parsed SocialCallback (with the one-time-token handoff for
cookie-mode sessions). The dependency was declared but unused before.
New plugins: two_factor (typed TOTP / OTP / backup codes),
anonymous, magic_link, api_key, organization, multi_session, and
one_time_token. SignInEmailResponse gained twoFactorRedirect (and user
is now nullable) so callers can branch on a 2FA challenge.
A runnable example/ app (email/password, reactive gating, sign-out).
A barrel file. import "package:better_auth_flutter/better_auth_flutter.dart"
now resolves. It previously did not exist, so every snippet in the README and
docs failed to compile and consumers had to deep-import implementation paths.
Reactive auth state. BetterAuthFlutter.authStateChanges
(Stream<AuthState>), BetterAuthFlutter.onAuthChange (Stream<User?>),
and BetterAuthFlutter.authState for a synchronous read. State updates
automatically on sign-in, sign-up, sign-out, session refresh, and any 401.
The stream replays current state to new listeners, so subscribing late still
reports where things stand.
BetterAuthBuilder — a declarative auth gate with authenticated /
unauthenticated / loading / error branches. AuthInitial is distinct
from Unauthenticated, so the sign-in screen no longer flashes during cold
start while the stored session loads.
BetterAuthFlutter.refreshSession() and initialize(hydrateOnInit:) to
look the stored session up on startup (in the background — it does not block
main()).
Per-plugin libraries: package:better_auth_flutter/plugins/<name>.dart for
admin, bearer, email_otp, jwt, and phone. Admin and bearer previously had no
barrel at all.
BetterError.statusCode, plus isUnauthorized / isNetworkError. Failures
could not previously be told apart by status.
Transport-level error codes (NETWORK_ERROR, TIMEOUT, CANCELLED,
BAD_RESPONSE, UNAUTHORIZED, RATE_LIMITED) for failures carrying no
Better Auth error body. See BetterErrorCodes.
StorageInterface.deleteCookies(url) / deleteAll(), and
BetterAuthFlutter.clearCookies().
First test suite (70 tests) and CI.
Set-Cookie — on every failed request, in release builds.
Internal logging is now off by default and never logs headers, cookies, or
bodies. Opt in with BetterAuthFlutter.initialize(enableLogging: kDebugMode).Secure cookies are no longer sent over plain HTTP, and expired cookies
are no longer sent at all. CustomPersistCookieJar.loadForRequest returned
cookies straight from the durable store without applying any scoping. (The
underlying cookie_jar filter is also unreliable here, so the secure and
expiry rules are now enforced directly.)HiveStorage wrote
cookie expires as a DateTime but read it back as an int, throwing on
load. Every Better Auth session cookie carries an Expires attribute, so no
persisted session survived a restart. Cookie serialization now lives in one
shared, tested codec used by every storage backend, and tolerates rows written
by previous versions instead of crashing.response.data["code"],
which throws on a non-Map body (an HTML error page from a proxy, for example)
— from inside its own catch, so the exception escaped Result entirely.
Non-Map, List, and null bodies now all produce a Failure.BetterAuthFlutter.clearCookies(). Previously the store kept the
session cookie indefinitely.lib/source/ to lib/src/. Import the barrel instead.BetterAuthConsumer's builder now receives the current AuthState as a third
argument.BetterAuthProvider now subscribes to auth state, so descendants rebuild when
the session changes.client.jwt, client.admin, …) are cached per client instead
of constructing a new HTTP client on every property access.| Before | After |
|---|---|
import "package:better_auth_flutter/source/core/api/client/better_auth_client.dart"; |
import "package:better_auth_flutter/better_auth_flutter.dart"; |
deep source/plugins/... imports |
import "package:better_auth_flutter/plugins/jwt.dart"; |
BetterAuthConsumer(builder: (context, client) => …) |
BetterAuthConsumer(builder: (context, client, state) => …) |
StorageInterface with 2 methods |
4 methods — add deleteCookies and deleteAll |
default store HiveStorage (plaintext) |
SecureStorage (keychain) — existing users sign in once after upgrade |
createDioWithBearer(...) / dio.useBearerAuth(...) |
initialize(mode: AuthMode.bearer, tokenStorage: …) |
| logging always on | off unless initialize(enableLogging: true) |
polling getSession() for auth state |
authStateChanges / BetterAuthBuilder |
Signing out should now also call BetterAuthFlutter.clearCookies() to clear the
persisted session.
Existing StorageInterface implementations must add the two new methods. If you
relied on cookies persisting across restarts, note that this never actually
worked with the default backend (see above) — users will sign in once after
upgrading.
* Delete user
* Minor fixes
Add Social Sign In With All Providers (Redirection to be handled, using something like flutter_web_auth_2)
* Add send verification email * Add verify email * Add list accounts
* Minor fixes
* Add custom uri for backend
* Initial Release
Your coding agent can read these notes before it upgrades. Set up the MCP server →