Better Auth for self-hosted TypeScript auth, where your database owns the users; Clerk for managed auth with prebuilt UI and orgs/MFA out of the box (web SDK, @clerk/expo on React Native). One condition overrides both: if the backend already bundles auth (Supabase / Firebase), use that instead of adding a second identity system.
running Better Auth with Magic Link + any OAuth provider + database-backed state storage → upgrade to ≥1.7.7 NOW (CVE/GHSA-965c-763c-88jm, CVSS 9.1 critical account takeover, no user interaction needed); see note: MAGIC LINK CVE
new self-hosted / own-database auth → Better Auth (TS-first, framework-agnostic; 2FA/passkeys/orgs via plugins)
already on NextAuth / Auth.js → Auth.js (keep it on maintenance; plan the migration to Better Auth rather than deepening the investment)
managed service / fastest ship / prebuilt sign-in UI → Clerk (per-MAU pricing; @clerk/expo on RN)
enterprise SSO / SAML / an existing IdP → Auth0 (react-native-auth0 on RN)
backend is Supabase or Firebase → Supabase Auth / Firebase Auth (the backend's bundled auth)
on react-native-firebase < 26 → React Native Firebase v26 once the app is on the New Architecture (firebase.auth() becomes getAuth(app)); without New Arch, stay on v25 deliberately
hand-rolling OAuth/sessions (expo-auth-session or custom) → expo-auth-session on RN (read the Copenhagen Book first; session tokens live in Keychain/Keystore via RB-E-STORAGE, never AsyncStorage — RB-E-SECURITY)
P2P / Holepunch app → n/a (no auth server: identity is keypair-based; RB-E-P2P owns it)
agent-facing product (AI agents authenticating to your app) → Agent Auth Protocol (Better Auth × Vercel; early — track it, do not build on it yet)
Low confidence — fast-moving or lightly-vetted domain: treat the pick as a vetted lead and prototype before committing.
Options & tradeoffs
the field considered — and why each one isn’t the default here
option
tradeoff
evidence
Better Auth
TS-first, framework-agnostic, self-hosted (your DB owns the users); 2FA/passkeys/organizations via plugins; very active. 1.7.0 (2026-08-18) makes database joins stable under advanced.database.joins — a config rename if you had opted in; latest 1.7.7 (2026-09-30, verified vs npm) — a MANDATORY security upgrade, see note: MAGIC LINK CVE. See also note: STEWARDSHIP
12.6M/wk · ships in 1/34
Auth.js / NextAuth (maintenance)
the long-time Next.js default, now under Better Auth's stewardship: security + bug fixes continue, the stated path transitions users to Better Auth; not formally deprecated. @auth/core 0.41.3 and next-auth 4.24.15, both 2026-07-20 (verified vs npm)
Clerk
managed auth SaaS with prebuilt React components (sign-in, orgs, MFA) + a first-class Expo SDK, @clerk/expo 4.6.9 (2026-09-23, verified vs npm; the older @clerk/clerk-expo is deprecated); fastest to ship; per-MAU pricing + vendor dependency
ships in 1/34
Auth0 (react-native-auth0)
the enterprise IdP — SSO/SAML/federation; RN SDK active: 5.11.1 (2026-09-08, verified vs its CHANGELOG) deprecates the client-side Management API and the legacy MFA methods on the auth client; see note: AUTH0
224k/wk
backend-bundled — Supabase Auth / Firebase Auth
already included with the backend (@react-native-firebase/auth on RN, 26.4.0, 2026-09-05, verified vs npm); use it rather than bolting on a second identity system. v26 requires the New Architecture; see note: REACT NATIVE FIREBASE v26
377k/wk · ships in 1/34
expo-auth-session (DIY)
Expo's browser-based OAuth/OIDC primitive — the hand-rolled lane on RN; you own token/session handling (Keychain via RB-E-STORAGE) and the correctness burden (see reading: The Copenhagen Book)
v26 makes every natively-bridged package New-Architecture-only and removes the namespaced API — bump the packages together, switch firebase.auth()-style calls to modular getAuth(app), and drop .then() where the TurboModule API is now synchronous. Below New Arch the supported position is to stay on v25.
Auth is decided by who owns the user row: your database (self-hosted, Better Auth), a vendor (managed, Clerk), or the backend you already run (Supabase / Firebase). Feature lists converge; ownership does not, and it is expensive to reverse. A second identity system beside a backend's bundled one means two sources of truth about the same person. If you hand-roll sessions, the correctness of the session mechanics matters more than the library. Confidence is low because this entry's judgment is young, not because the options are immature.
MAGIC LINK CVE (2026-09-30, verified vs the GitHub security advisory + the v1.7.7 release notes): GHSA-965c-763c-88jm, CVSS 9.1 CRITICAL, affects 1.4.0-beta.18 through 1.7.6 when ALL THREE hold: the Magic Link plugin is enabled with default token storage, at least one OAuth provider is configured, and state storage is database-backed. An attacker starts an OAuth sign-in flow for ANY target email, then repurposes the returned state value to complete Magic Link auth — no access to the victim's inbox, no completed OAuth callback, no user interaction, full session with the account's permissions. A second bug in the same release let OAuth Proxy accept a sign-in STATE value as a provider profile. Fix: upgrade to 1.7.7. This is not a drop-in version bump: upgrade every server sharing verification storage together, request fresh Magic Links (existing ones from before the patch are invalid), restart pending OAuth/SAML sign-ins, and update any CUSTOM identifier hasher to preserve purpose prefixes; no DB migration is required. Until upgraded, mitigate by switching to cookie-backed state storage, changing token storage config, or disabling Magic Link or OAuth.
STEWARDSHIP (2026-07-16, verified vs the first-party announcement; registry re-verified 2026-09-24): Better Auth JOINED VERCEL (2026-07-07) with a stated open-source and framework/platform-agnostic commitment; its Agent Auth Protocol work continues under Vercel. Better Auth had ALREADY acquired Auth.js/NextAuth and maintains it (security/bugs) while transitioning users toward Better Auth. The registry shows the two lanes: better-auth 1.7.7 (2026-09-30) active; @auth/core 0.41.3 and next-auth 4.24.15 both last published 2026-07-20. DELIBERATE NO-MIGRATE-RULE (same policy as ANIMATION's Rive case): Auth.js is NOT formally deprecated, so it stays a when-clause, not churn; the tripwire on next-auth's npm deprecation flag adds the next-auth → better-auth migrate rule when it fires.
CLERK EXPO SDK (2026-09-24, verified vs npm): @clerk/clerk-expo (last 2.20.0, 2026-08-04) carries an npm deprecation — "Migrate to @clerk/expo by following the Core 3 upgrade guide"; @clerk/expo is at 4.6.9. → Expo apps on the old package migrate as part of Clerk's Core 3 upgrade.
REACT NATIVE FIREBASE v26 (2026-08-07, verified vs the Invertase release post): the biggest architectural cut in the library's nine years, and it is gated — every package with a native bridge now REQUIRES the New Architecture (Codegen TurboModules), so v26 is only reachable once the app is on New Arch; the maintainers' explicit advice otherwise is to stay on v25. Three changes travel with it: all 19 packages migrated JS→TypeScript (the prerequisite for TurboModule specs), the deprecated NAMESPACED API is removed so modular calls (getAuth(app)) are the only surface — matching the firebase-js-sdk docs people already copy from — and CI now diffs the TypeScript shapes against firebase-js-sdk so API drift fails on Invertase's side instead of in your build months later. Migration trap: TurboModules let APIs be synchronous where firebase-js-sdk is synchronous, so code calling .then() on what is now void breaks.
AUTH0 (2026-09-24, verified vs the react-native-auth0 CHANGELOG): 5.9 (2026-07-07) added passwordless OTP for database connections; 5.10 (2026-07-17) added MFA support; 5.11 (2026-07-31) added IPSIE session_expiry enforcement and passkeys on web; 5.11.1 (2026-09-08) deprecates the client-side Management API and the legacy MFA methods on the auth client → code using either should move off them now.
CROSS-REFERENCES: RB-E-STORAGE owns token storage (Keychain/Keystore); RB-E-SECURITY owns the threat model; RB-E-P2P owns keypair identity; RB-E-META-FRAMEWORKS owns the web server story that session handling is entangled with.
HISTORY:
2026-10-01 REOPENED: Better Auth critical Magic Link account-takeover CVE (GHSA-965c-763c-88jm, CVSS 9.1) — mandatory upgrade to 1.7.7, promoted to the top when-clause.
2026-09-24 CORRECTED: the Expo SDK was named as @clerk/clerk-expo, which npm now deprecates for @clerk/expo; "@auth/core last publish 2025-10" was superseded by the 2026-07-20 publishes.
2026-09-10 GRADUATED drafted → reviewed: long-form Explanation written; confidence stays low.
2026-07-16 GAP CLOSED: auth had no entry among the prior 42; opened on TWiR #290 (Better Auth joins Vercel).
Canonical reading
Editorial annotations on why each piece matters — the articles themselves are the originals; read them there.
The free, open, community-maintained guideline for implementing auth from first principles — server-side tokens, sessions, password auth + reset, email verification, OAuth, MFA, WebAuthn, CSRF, open redirects — meant to be read alongside the OWASP cheat sheets. THE canonical reference when you hand-roll any part of auth instead of adopting a library above; its author sunset the Lucia auth library INTO this book, the lesson being that auth is a design problem more than a dependency.
Carries a PLATFORM deprecation this entry had no home for: Android's legacy GoogleSignInClient (Google Play services) is deprecated and slated for removal, with Credential Manager as the replacement — and much of the existing RN Google-sign-in field still targets the old API, so it misses Credential Manager's bottom-sheet flow, automatic sign-in and structured error handling. The post introduces the authors' own @thoughtbot/react-native-social-auth (Credential Manager on Android, Google Sign-In SDK 8+ on iOS with Firebase App Check and custom nonces, TypeScript-first, Expo config plugin), so treat the library pick as vendor advocacy; the deprecation and the capability checklist are the durable part. It stops at obtaining the credential — session/token handling is still yours (Keychain via RB-E-STORAGE, never AsyncStorage).
The reviewed long-form essay behind this entry — the why, not a how-to. Also on GitHub.
About authentication & identity in React and React Native
The question that organises everything: who owns the user row?
Almost every argument about auth libraries is really an argument about one thing —
whether the canonical record of "who your users are" lives in your database or in
someone else's service. Everything else (which SDK, which UI components, which
protocol) follows from that answer, and the answer is expensive to reverse later
because it determines who can read, migrate, and delete your identity data.
That is why this entry does not open with a feature comparison. Feature lists across
auth products converge fast — everyone ships passkeys eventually. Ownership does not
converge, and it is the decision you are actually making.
Two secondary questions fall out of the first:
Do you already have an identity system? If your backend bundles auth, you almost
certainly should not add a second one.
Are you hand-rolling the session? If so, the library choice matters far less than
whether you get the session mechanics right — and that is where the real damage is done.
The default, and why
Self-hosted TypeScript auth → Better Auth. Managed auth with prebuilt UI, organizations
and MFA → Clerk. Backend already bundles auth (Supabase / Firebase) → use that.
The reasoning behind each leg:
Better Auth wins the self-hosted lane on ownership plus surface area: your database
owns the users, it is framework-agnostic rather than tied to one meta-framework, and the
things teams eventually need — 2FA, passkeys, organizations — arrive as plugins rather
than as a migration to a different product. Its stewardship position also became unusually
strong: it acquired Auth.js/NextAuth, and then joined Vercel in 2026-07 with a stated
open-source and framework-agnostic commitment. Read that consolidation carefully in both
directions — it means the self-hosted lane now has one clear maintained answer, and it
means a single vendor sits behind both that answer and the framework many of its users
deploy on.
Clerk wins the managed lane not because managed auth is better but because the thing
teams actually buy is the prebuilt UI plus organizations and MFA, and Clerk ships those
with a first-class Expo SDK, so a React and React Native product gets one identity system
rather than two integrations. You pay in per-MAU pricing and vendor dependency, which is
the honest trade: you are renting the user row. The Expo SDK is now @clerk/expo; the older
@clerk/clerk-expo carries an npm deprecation pointing at Clerk's Core 3 upgrade guide, so
an Expo app still on it has a package migration to plan.
Backend-bundled auth wins whenever it applies, and the reason is not technical merit —
it is that a second identity system means two sources of truth about the same person,
two session lifetimes, and a reconciliation job nobody wants to own. "Already included"
beats "slightly better" here more often than engineers expect.
The entry carries confidence: low, and the distinction matters: the options are
mature and widely deployed. What is young is this entry's editorial judgment about them,
because auth was a domain gap in the corpus until 2026-07.
The landscape, and when each one wins
Auth.js / NextAuth is the case that needs stating precisely, because "maintenance"
is easy to over-read. It is under Better Auth's stewardship: security and bug fixes
continue (@auth/core and next-auth both published on 2026-07-20), and the stated path
transitions users toward Better Auth. It is not formally deprecated — which is exactly why the corpus refuses to ship a migrate rule for it. A
migrate rule is an instruction to spend a team's time; that instruction should wait for a
formal deprecation or EOL, not for a vibe about momentum. Until then it is a when-clause:
if you are already on it, plan the migration rather than deepening the investment.
Auth0 wins where the requirement is not "authentication" but federation — SSO, SAML,
an existing corporate IdP. That is a procurement-shaped requirement, and the enterprise IdP
is the shape that fits it. Its React Native SDK stays actively developed — and 5.11.1
(2026-09-08) deprecates the client-side Management API and the legacy MFA methods on the
auth client, so code using either should move off them.
expo-auth-session is the DIY lane on React Native: a browser-based OAuth/OIDC primitive
where you own token handling, session lifetime, and the correctness burden. Choosing it is
choosing to implement the parts the other options hide. That is legitimate — and it is why
the entry points at the Copenhagen Book before it points at any code.
The React Native Firebase v26 line, and why it is the sharpest edge here
If your answer is "backend-bundled Firebase", there is a hard gate you cannot design
around. @react-native-firebase v26 is the largest architectural cut in the library's
history, and it is conditional: every package with a native bridge now requires the
New Architecture, because the native surface moved to Codegen TurboModules. You cannot
adopt v26 on a Legacy-Arch app. The maintainers' own advice in that situation is to stay
on v25 deliberately, and "deliberately" is the operative word — a pinned major with a
recorded reason is engineering; an accidental one is debt.
Two changes travel with it and both are real work: the deprecated namespaced API is
removed, so firebase.auth() becomes getAuth(app) and modular calls are the only
surface; and the packages moved to TypeScript, which is the prerequisite for the
TurboModule specs. The upgrade therefore sequences: New Architecture first, then v26,
then the namespaced-to-modular rewrite — not in any other order.
Tradeoffs and failure modes to name out loud
Two identity systems. The most common self-inflicted wound in this area: bolting a
dedicated auth product onto a backend that already had auth. Every subsequent bug is a
synchronization bug.
Storing session tokens wrong. This is the failure that actually leaks users. Tokens
belong in the Keychain/Keystore (see RB-E-STORAGE), never in AsyncStorage (see
RB-E-SECURITY). No auth library saves you from getting this wrong on the client.
Hand-rolling sessions without reading the theory first. If you take the
expo-auth-session lane, the correctness burden is yours: fixation, rotation, expiry,
revocation. Read the Copenhagen Book before writing the code, not after the review.
Reading a stewardship change as an endorsement. Better Auth joining Vercel and
acquiring Auth.js consolidates the lane, which is genuinely useful. It also concentrates
it. Both facts are true; the entry states both rather than picking the flattering one.
Treating "maintenance" as "dead". Auth.js still ships security fixes. Migrating off
it is a planned move, not an emergency.
How it interacts with the rest of the stack
Auth is a boundary concern, so it touches more of the corpus than most entries.
Token storage belongs to RB-E-STORAGE and the surrounding threat model to
RB-E-SECURITY. On web, session handling is entangled with your meta-framework's
server story (RB-E-META-FRAMEWORKS) — which is part of why framework-agnostic matters
in the self-hosted lane. In a P2P / Holepunch app the entire question dissolves:
there is no auth server, identity is keypair-based, and RB-E-P2P owns it instead.
A newer axis is worth watching but not betting on: agent-facing products, where AI agents
authenticate to your app rather than people. The Agent Auth Protocol work sits there. It
is early, and the entry says so.
In one paragraph
Decide who owns the user row before you compare SDKs. If your backend already bundles auth,
use it — a second identity system costs more than any feature it buys. If you want to own
the data, Better Auth is the maintained framework-agnostic answer in that lane, with the
caveat that the lane has consolidated under one vendor. If you want to ship fastest and
are content to rent identity, Clerk gives you the UI, organizations and MFA across React
and Expo in one system. Reach for Auth0 when the requirement is federation, and for
expo-auth-session only when you intend to own the session mechanics — in which case read
the theory first, and put the tokens in the Keychain.