Si vous avez livré une application Next.js ou TypeScript full-stack ces dernières années, vous vous êtes probablement battu avec l'authentification. NextAuth (devenu Auth.js) est le choix de facto depuis 2020, mais quiconque a migré entre des versions majeures, débogué une URL de callback, ou tenté d'ajouter les organisations et la 2FA sait à quel point cela peut devenir pénible. Clerk résout l'expérience développeur mais vous enferme dans un SaaS payant. Supabase Auth vous lie à Supabase. Auth0 a des tarifs entreprise.
En 2026, une nouvelle option a pris la tête : Better Auth. Open source, auto-hébergée, entièrement type-safe, agnostique au framework, et architecturée pour que les parties dont vous n'avez pas besoin restent hors de votre bundle. Ce guide explique ce qu'elle est, pourquoi elle a été adoptée, et comment la mettre en production.
La réponse en 30 secondes
Better Auth est une bibliothèque d'authentification TypeScript qui vous donne l'auto-hébergement façon NextAuth avec l'expérience développeur façon Clerk. Elle prend en charge email/mot de passe, OAuth, magic links, passkeys, authentification à deux facteurs, organisations et fonctions admin via un système de plugins propre. Vous possédez la base de données, vous possédez les sessions, et les types circulent de bout en bout du serveur au client sans étape de génération manuelle.
Choisissez Better Auth si vous voulez un contrôle total de votre stack d'authentification sans la réécrire de zéro, et si vous en avez assez de combattre votre bibliothèque d'authentification à chaque mise à jour.
Pourquoi les équipes migrent loin de NextAuth
Les plaintes sont remarquablement cohérentes entre les équipes qui changent :
- Configuration éparpillée. Auth.js v5 a divisé la configuration entre plusieurs fichiers et contextes d'exécution. Une simple configuration OAuth s'étend facilement sur quatre fichiers avant de fonctionner.
- Fuites de type-safety. Les types de session nécessitent une augmentation de module, et les types générés ne reflètent pas les champs personnalisés sans travail manuel.
- Friction sur le runtime Edge. Le middleware qui parle à une base de données nécessite une configuration séparée. La séparation entre Edge et Node n'est pas étanche.
- Plugins de seconde classe. Ajouter la 2FA ou les organisations signifie l'écrire soi-même ou bricoler des paquets communautaires.
- Migrations risquées. Les bumps de version majeure ont cassé sessions, flux de redirection et configurations de fournisseurs plus d'une fois.
Better Auth a été conçue en réponse directe à ces problèmes. La thèse : l'authentification est une infrastructure essentielle, donc la bibliothèque doit être une bibliothèque, pas un framework qui a des opinions sur la disposition de vos fichiers.
Architecture de base
Better Auth s'exécute comme un seul ensemble de routes API montées sous /api/auth/*. Vous la configurez une fois dans un fichier serveur, et la même configuration alimente vos server actions, route handlers, et le SDK client. Tout est du TypeScript pur — pas de DSL, pas d'étape de codegen, pas de modules virtuels.
Une configuration Next.js minimale ressemble à ceci :
import { betterAuth } from "better-auth"
import { drizzleAdapter } from "better-auth/adapters/drizzle"
import { db } from "@/db"
export const auth = betterAuth({
database: drizzleAdapter(db, { provider: "pg" }),
emailAndPassword: { enabled: true },
socialProviders: {
google: {
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
},
},
})Cet objet unique est la source de vérité. Le handler est monté à un seul endroit :
import { auth } from "@/lib/auth"
import { toNextJsHandler } from "better-auth/next-js"
export const { GET, POST } = toNextJsHandler(auth)Et le SDK client tient en une ligne :
import { createAuthClient } from "better-auth/react"
export const authClient = createAuthClient()Le client infère ses types directement depuis la configuration serveur. Ajoutez un plugin côté serveur, et les méthodes correspondantes apparaissent côté client. Aucune étape de regénération, aucune augmentation de type manuelle.
Adaptateurs de base de données et propriété
Better Auth livre des adaptateurs de première partie pour Drizzle, Prisma, Kysely et MongoDB. Le schéma est généré par la CLI et vit dans votre code source comme n'importe quelle autre migration. Sessions, comptes et utilisateurs sont stockés dans votre base de données — il n'y a pas de service externe qui détient l'état.
Génération du schéma :
npx @better-auth/cli generate
npx @better-auth/cli migrateLes tables générées suivent des noms conventionnels : user, session, account, verification. Vous pouvez étendre la table user avec des champs arbitraires via la configuration, et ces champs restent typés de bout en bout :
export const auth = betterAuth({
user: {
additionalFields: {
role: { type: "string", defaultValue: "member" },
companyId: { type: "string", required: false },
},
},
})session.user.role est désormais typé comme string partout — serveur, client, middleware. Aucun fichier d'augmentation manuel requis.
Le système de plugins est la fonctionnalité phare
Le système de plugins est là où Better Auth dépasse toute alternative. Chaque capacité est livrée comme un plugin que vous activez. Le bundle ne porte que ce que vous activez.
import { twoFactor, organization, admin, passkey, magicLink } from "better-auth/plugins"
export const auth = betterAuth({
plugins: [
twoFactor(),
organization({ allowUserToCreateOrganization: true }),
admin(),
passkey({ rpName: "Noqta" }),
magicLink({ sendMagicLink: async ({ email, url }) => sendEmail(email, url) }),
],
})Chaque plugin ajoute ses propres routes, tables de base de données et méthodes client. Le SDK client les découvre automatiquement :
await authClient.twoFactor.enable({ password: "..." })
await authClient.organization.create({ name: "Noqta" })
await authClient.passkey.addPasskey()
await authClient.signIn.magicLink({ email: "user@example.com" })Les plugins officiels disponibles en 2026 couvrent l'authentification à deux facteurs, les magic links, les passkeys (WebAuthn), les organisations et équipes, l'outillage admin, les clés API, les sessions anonymes, le multi-session, le mode fournisseur OIDC et le rate limiting. Les plugins communautaires étendent cela avec SAML, SSO et flux personnalisés.
Sessions et middleware
Les sessions sont basées sur JWT par défaut mais peuvent être basculées en sessions de base de données via un seul flag de configuration. Dans les deux cas, lire la session dans n'importe quel contexte est uniforme :
import { auth } from "@/lib/auth"
import { headers } from "next/headers"
const session = await auth.api.getSession({ headers: await headers() })
if (!session) redirect("/login")Le même appel fonctionne dans les Server Components, Route Handlers, Server Actions et middleware. Le middleware n'a pas besoin d'une configuration séparée compatible Edge — Better Auth fournit un check de session léger qui s'exécute sur Edge sans accès à la base de données :
import { getSessionCookie } from "better-auth/cookies"
import { NextResponse } from "next/server"
export async function middleware(request: Request) {
const sessionCookie = getSessionCookie(request)
if (!sessionCookie) return NextResponse.redirect(new URL("/login", request.url))
return NextResponse.next()
}Pour une validation complète de session dans le middleware vous pouvez appeler l'API, mais le check du cookie suffit pour la plupart de la protection de routes et évite un aller-retour base de données à chaque requête.
Type-safety de bout en bout
C'est la partie qui surprend vraiment les gens venant de NextAuth. Vous ajoutez un champ au modèle utilisateur dans la configuration, et trois choses se produisent automatiquement :
- La migration de schéma de base de données ajoute la colonne.
- Le type
session.usercôté serveur inclut le champ. - Le hook client
authClient.useSession()retourne le champ avec le bon type.
Pas d'augmentation next-auth.d.ts, pas de dérive de types client-serveur, pas de as any. Les plugins étendent les types de la même manière — activez le plugin organisation et session.activeOrganization apparaît comme un champ typé des deux côtés.
Performance et taille de bundle
Better Auth est construite autour du tree-shaking. La bibliothèque de base sans plugins ajoute environ 25 Ko gzippés au bundle client. Chaque plugin que vous activez ajoute son propre code client, mais les plugins que vous n'activez pas ne contribuent en rien. NextAuth v5 par comparaison expédie environ 50 Ko et tire des fournisseurs que vous n'utilisez peut-être pas.
Côté serveur, le traitement des requêtes est un petit dispatch sur les routes configurées. Pas de réflexion, pas de chargement de modules au moment de la requête. Les démarrages à froid sur Vercel et Cloudflare Workers sont sensiblement plus rapides qu'avec NextAuth.
Où Better Auth a encore des aspérités
Elle n'est pas parfaite. Quelques zones à connaître avant adoption :
- La documentation s'améliore mais reste inégale. Les docs de plugins sont parfois minces, et il faut occasionnellement lire les sources pour comprendre un flag.
- Les plugins communautaires varient en qualité. Tenez-vous-en aux plugins officiels en production jusqu'à ce qu'un plugin communautaire ait un historique.
- Le SSO entreprise (SAML) est maintenu par la communauté. Si vous avez besoin de SAML pour des ventes B2B, évaluez le plugin SAML avec soin ou couplez Better Auth à un fournisseur SSO dédié.
- La migration depuis NextAuth n'est pas automatique. Sessions, hashes de mots de passe et liens de comptes doivent tous être déplacés délibérément. Prévoyez une fenêtre de migration unique.
Pattern de migration depuis NextAuth
La migration la plus propre que nous avons exécutée ressemble à ceci :
- Mettez Better Auth en place à côté de NextAuth dans la même app sous un préfixe différent (par exemple
/api/auth-v2/*). - Migrez les tables user, account et session. Le schéma de Better Auth est suffisamment similaire pour qu'une seule migration SQL couvre la plupart des champs.
- Pour les utilisateurs basés sur mot de passe, gardez l'ancienne colonne de hash et utilisez le hook
verifyPasswordde Better Auth pour valider l'ancien hash à la première connexion, puis re-hachez vers le nouveau format. - Pour les utilisateurs OAuth, les liens de compte se transfèrent avec un renommage de colonne. Aucune ré-authentification requise.
- Basculez le SDK client fonctionnalité par fonctionnalité derrière un feature flag. Faites tourner les deux en parallèle pendant une semaine pour attraper les cas limites.
- Décommissionnez NextAuth une fois les métriques stables.
Nous avons exécuté cette migration sur une application Next.js de production en mars 2026. Le temps d'arrêt total fut de zéro, le nombre de bugs la première semaine fut de trois, et l'équipe n'a pas regardé en arrière.
Quand ne pas utiliser Better Auth
Quelques cas où c'est le mauvais choix :
- Vous avez besoin d'une UI hébergée aujourd'hui et n'avez pas de bande passante d'ingénierie. Clerk vous donne un composant prêt à l'emploi, une gestion d'utilisateurs hébergée et la conformité SOC 2 dès la sortie de la boîte. Better Auth vous donne des primitives.
- Vous êtes profondément intégré dans Supabase. Supabase Auth est correcte, s'intègre avec RLS, et il n'y a pas de gain de migration si Supabase est déjà votre stack.
- Vous avez besoin de SAML SSO avec des contrats de support fournisseur. Auth0 et WorkOS existent pour une raison.
Pour tous les autres — la plupart des équipes SaaS indépendantes et la plupart des applications Next.js — Better Auth est désormais le défaut que nous recommandons chez Noqta au démarrage d'un nouveau projet.
Pour démarrer
Installation et scaffolding :
npm install better-auth
npx @better-auth/cli initLa CLI vous guide à travers le choix d'adaptateur de base de données, génère le schéma, crée le fichier de configuration d'authentification et configure le client. En quinze minutes vous pouvez avoir email/mot de passe, Google OAuth et une session fonctionnelle dans une nouvelle app Next.js.
La documentation vit sur le site officiel, et le code source est sur GitHub sous licence MIT. La bibliothèque est sur une cadence de release régulière avec une roadmap claire et le genre de tracker d'issues qui obtient des réponses en jours, pas en semaines.
L'authentification était la partie de chaque projet que nous redoutions de toucher. Avec Better Auth, c'est devenu la partie que nous mettons en place en premier et oublions ensuite.