lenec ru

← все посты

Better Auth vs NextAuth vs Lucia: что выбрать в Node-проекте

19K

За последние два года я перебрал в работе все три библиотеки на разных проектах. Где-то нужен был быстрый 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.

Комментарии 0

  • Будьте первым, кто оставит комментарий.

Войдите, чтобы оставить комментарий.