Better Auth vs NextAuth vs Lucia: что выбрать в Node-проекте
За последние два года я перебрал в работе все три библиотеки на разных проектах. Где-то нужен был быстрый OAuth с Google и парой социалок, где-то — кастомная регистрация с подтверждением email и магическими ссылками, где-то — отдельный API на Hono без Next.js. У каждой библиотеки нашлась своя ниша. Расскажу, что я в итоге беру и почему.
Что у нас на столе
Все три — TypeScript-первые, все три не пытаются быть SaaS, все три живут в open source. На этом сходство заканчивается.
- NextAuth (Auth.js) — старожил, изначально под Next.js, теперь умеет SvelteKit и Express. Концепция — провайдеры и колбэки.
- Lucia — минималистичный конструктор. Тонкий слой, в котором ты сам собираешь логин-флоу из примитивов.
- Better Auth — самый молодой из трёх, но за полтора года стал моим default-выбором. Pluggable, framework-agnostic, c хорошим набором плагинов из коробки.
NextAuth (Auth.js)
NextAuth выручает, когда у тебя классический сценарий: есть Next.js, нужно «логин через гугл и email-пароль, забыть и забить». Несколько провайдеров включаются за пять строк, базы данных подключается адаптером.
Что я в нём люблю:
- Огромный список готовых OAuth-провайдеров. Если у тебя нестандартный, типа Github Enterprise или Apple — почти наверняка есть готовый.
- Колбэки
signIn,jwt,session. Гибко вмешаться можно почти в любой момент. - Документация и комьюнити. Любой вопрос гуглится мгновенно.
Что не нравится:
- Концепция «всё через колбэки». Пять провайдеров и три флоу — и колбэки превращаются в простыню. Поддерживать тяжко.
- Поддержка не-Next-фреймворков долго была формальной. Сейчас лучше, но ощущение «гость в чужом доме» остаётся.
- Нет внятного встроенного rate limiting и защиты от brute force. Реализуешь сам.
- Ему свойственно жонглировать JWT и сессиями вперемешку. По умолчанию JWT, и многие забывают переключиться, когда нужно.
Когда беру: типичный SaaS на Next.js, у которого нет нестандартных требований к auth.
Lucia
Lucia — крайняя сторона спектра. Она не пытается быть фреймворком авторизации. Это набор примитивов: создать сессию, проверить сессию, инвалидировать. Всё.
В чём её прелесть:
- Никакой магии. Если хочешь точно понимать, как происходит вход — Lucia заставит написать это руками.
- Маленький размер. Зависимости — пара пакетов.
- Полная свобода в БД-слое. Можно писать на голом SQL, если хочется.
В чём минус: всё, что в других библиотеках готово (OAuth, magic link, email verification, 2FA), здесь ты собираешь сам. Это нормально для команды, у которой уже была система авторизации, и она хочет переехать на типизированный TS-стек, не выкинув бизнес-логику. И мучительно для проекта, в котором надо «быстро».
Дополнительно: главный автор библиотеки в начале 2024 года объявил, что Lucia переходит в режим «обучающего материала», а активная разработка останавливается. Ставить новый проект на стагнирующий пакет в 2026 я бы не стал. Lucia остаётся хорошим референсом, как сделать сессии руками. Но как зависимость — уже не в первой тройке.
Когда беру: на новых проектах — нет. На старых, где она уже стоит — мигрирую постепенно.
Better Auth
Better Auth разводит роли вежливо: ядро у него тонкое, как у Lucia, а сверху живёт большая россыпь плагинов. Хочешь email-пароль — плагин. Magic link — плагин. OAuth — плагин. 2FA, организации, passkeys, multi-tenant — всё это плагины, которые включаются и конфигурируются ровно там, где нужны.
Что я ценю:
- Один централизованный инстанс, который ты собираешь один раз и подключаешь к любому фреймворку. Я ставил на Next.js, на Hono, на Express — везде интеграция занимает 5–10 строк.
- Адаптеры под Drizzle и Prisma. У меня везде Drizzle, и оно прямо работает.
- Из коробки сессии в куках с серверной валидацией. Никаких JWT по умолчанию (если не хочешь).
- Rate limiting — встроенный, конфигурируется параметрами.
- Хорошая клиентская библиотека:
signIn,signUp,useSessionна React-стороне, всё типизировано.
Что не идеально:
- API чуть-чуть меняется от версии к версии. До 1.0 я ловил пару переименованных опций. После 1.0 стало стабильнее.
- Документация толковая, но местами не успевает за фичами. На редкий плагин стоит смотреть в исходник.
- Не такой огромный список OAuth-провайдеров, как у NextAuth. Все ходовые есть; для редких пишешь свой generic OAuth.
Кодовый сравнительный пример
Сценарий: email/пароль + Google OAuth + сессии в куках.
NextAuth
import NextAuth from 'next-auth';
import Google from 'next-auth/providers/google';
import Credentials from 'next-auth/providers/credentials';
export const { handlers, signIn, signOut, auth } = NextAuth({
providers: [
Google({ clientId: process.env.GOOGLE_ID!, clientSecret: process.env.GOOGLE_SECRET! }),
Credentials({
credentials: { email: {}, password: {} },
async authorize(creds) {
// ... ручная проверка пароля
return user ?? null;
},
}),
],
session: { strategy: 'database' },
});Better Auth
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_ID!, clientSecret: process.env.GOOGLE_SECRET! },
},
});Lucia
// здесь будет 100+ строк, потому что email/password, OAuth и сессии
// надо собирать руками. Покажу один кусок.
import { Lucia } from 'lucia';
import { DrizzleSQLiteAdapter } from '@lucia-auth/adapter-drizzle';
export const lucia = new Lucia(
new DrizzleSQLiteAdapter(db, sessionTable, userTable),
{ sessionCookie: { attributes: { secure: process.env.NODE_ENV === 'production' } } },
);
// + отдельные обработчики /signup, /login, /oauth/google/callback ...Где какая удобнее
СценарийЧто братьЯ понимаю, таблиц HTML-санитайзер не пропустит, поэтому списком:
- Стандартный SaaS на Next.js, нестандартный OAuth. NextAuth остаётся проще: список провайдеров шире.
- Кастомные флоу: invite-only, magic links, организации, passkeys, 2FA. Better Auth — плагины уже написаны.
- Не-Next API на Hono или Express. Better Auth — единственный, кто ровно туда ложится.
- Edge runtime, маленький бандл. Better Auth с jose. NextAuth с edge-вариантом адаптеров — тоже решает, но настройка чуть тоньше.
- Полностью кастомная авторизация со своими токенами. Lucia как референс, скорее всего собрать руками.
Безопасность по умолчанию
Что я смотрю в первые минуты после установки любой из библиотек:
- Куки
HttpOnly,Secure,SameSite=Lax. Better Auth ставит правильно по умолчанию, у NextAuth это поведение зависит отuseSecureCookies. - Сессии серверные. JWT в куках я применяю только если действительно нужен stateless и я готов закрыть глаза на сложность инвалидации.
- Rate limiting на
/sign-in,/sign-up,/forgot-password. У Better Auth встроено, у NextAuth — добавляешь сам, у Lucia — собираешь. - CSRF. Better Auth и NextAuth закрывают это по умолчанию. На своих флоу через Lucia надо помнить и добавлять.
Что я выбираю в 2026
Стартовая точка — Better Auth. На любом новом проекте я начинаю с него и свечу плагины ровно те, что нужны. Если оказывается, что нужен экзотический OAuth-провайдер, которого в Better Auth нет — добавляю generic OAuth-плагин или на конкретное направление беру NextAuth.
NextAuth остаётся хорошим выбором, если у тебя уже стоит и команда привыкла. Переезжать ради Better Auth ради переезда — нет смысла. Переехал бы я, если бы стало нужно несколько новых флоу: organizations, invites, magic links сразу — здесь Better Auth выигрывает заметно.
Lucia в 2026 я не запускаю на новых проектах. Старые сервисы постепенно увожу либо на Better Auth, либо на свой минимальный обработчик сессий, написанный по мотивам Lucia.