NuxtSeniorSystem design

Как реализовать аутентификацию в Nuxt 3? Что такое nuxt-auth и аналогичные подходы?

Аутентификацию в Nuxt 3 реализуют через модуль @sidebase/nuxt-auth (Auth.js под капотом) с OAuth-провайдерами или вручную через httpOnly cookie + server middleware + JWT. Модуль предоставляет composable useAuth() с методами signIn/signOut и глобальный route middleware.

Аутентификация в Nuxt 3: общий подход

Nuxt 3 не навязывает единственный способ аутентификации — вы можете использовать готовые модули, собственные composable-функции или интеграцию с внешними провайдерами. Выбор зависит от требований проекта: нужен ли OAuth, сессии на сервере или JWT в cookie.

Модуль nuxt-auth (sidebase)

Наиболее распространённый сторонний модуль — @sidebase/nuxt-auth. Он оборачивает Auth.js (бывший NextAuth.js) и предоставляет два режима:

  • authjs — serverHandler на базе Auth.js с поддержкой OAuth-провайдеров (GitHub, Google и др.), JWT и базы данных через адаптеры.
  • local — упрощённый режим для собственного REST API: логин/логаут через указанные endpoints, токен хранится в cookie или localStorage.
npx nuxi module add @sidebase/nuxt-auth

Конфигурация в nuxt.config.ts:

export default defineNuxtConfig({
  modules: ['@sidebase/nuxt-auth'],
  auth: {
    provider: {
      type: 'authjs'
    },
    globalAppMiddleware: true
  }
})

Серверный обработчик server/api/auth/[...].ts:

import { NuxtAuthHandler } from '#auth'
import GithubProvider from 'next-auth/providers/github'

export default NuxtAuthHandler({
  secret: process.env.AUTH_SECRET,
  providers: [
    GithubProvider.default({
      clientId: process.env.GITHUB_CLIENT_ID,
      clientSecret: process.env.GITHUB_CLIENT_SECRET
    })
  ]
})

В компоненте или странице:

const { data: session, signIn, signOut, status } = useAuth()
// status: 'authenticated' | 'unauthenticated' | 'loading'

Ручная реализация через useCookie и server middleware

Для полного контроля можно обойтись без сторонних модулей. Схема: логин через API-endpoint → получение JWT → сохранение в httpOnly cookie → server middleware проверяет токен на каждом запросе.

// server/api/login.post.ts
import { H3Event, setCookie } from 'h3'
import jwt from 'jsonwebtoken'

export default defineEventHandler(async (event: H3Event) => {
  const body = await readBody(event)
  // валидация credentials...
  const token = jwt.sign({ userId: user.id }, process.env.JWT_SECRET!, {
    expiresIn: '7d'
  })
  setCookie(event, 'auth_token', token, {
    httpOnly: true,
    secure: true,
    sameSite: 'lax',
    maxAge: 60 * 60 * 24 * 7
  })
  return { ok: true }
})
// server/middleware/auth.ts
import jwt from 'jsonwebtoken'

export default defineEventHandler((event) => {
  const token = getCookie(event, 'auth_token')
  if (token) {
    try {
      event.context.user = jwt.verify(token, process.env.JWT_SECRET!)
    } catch {
      deleteCookie(event, 'auth_token')
    }
  }
})

На клиенте защищённые страницы используют route middleware:

// middleware/protected.ts
export default defineNuxtRouteMiddleware(() => {
  const user = useUserStore()
  if (!user.isLoggedIn) {
    return navigateTo('/login')
  }
})

Альтернатива: nuxt-oidc-auth

Модуль nuxt-oidc-auth ориентирован на OpenID Connect и подходит, когда нужна полноценная OIDC-интеграция с корпоративными провайдерами (Keycloak, Azure AD). Он хранит сессию на сервере в зашифрованном cookie и не требует базы данных.

Подводные камни

  • AUTH_SECRET не задан — Auth.js молча работает в dev, но падает в production; всегда задавайте переменную явно.
  • globalAppMiddleware: true блокирует все страницы включая публичные — нужно явно помечать их через definePageMeta({ auth: false }).
  • Гидратация SSR/клиент — если состояние auth получено на сервере через useAuth(), а клиент обращается к нему до того как хранилище инициализировано, возникает рассинхронизация; используйте status === 'loading' для условного рендеринга.
  • Refresh-токены в режиме local не обновляются автоматически — нужно самостоятельно реализовывать перехватчик с повтором запроса.
  • CSRF-защита отсутствует в ручной реализации — при использовании cookie-аутентификации без samesite=strict необходимо добавлять CSRF-токен.
  • useCookie на сервере при SSR возвращает cookie из заголовков запроса, а не из document.cookie — не перепутайте контексты выполнения.
  • Хранение секретов — не кладите JWT_SECRET в .env файл, коммитящийся в репозиторий; используйте secrets менеджер.
  • Режим SPA — если ssr: false, серверная защита через middleware недоступна; вся защита только на клиенте, что небезопасно для чувствительных данных.

Common mistakes

  • Путать Nuxt authentication с похожим API из соседнего фреймворка.
  • Не объяснять, где код выполняется: сервер, клиент, build step или runtime.
  • Игнорировать влияние на hydration, cache, bundle size или безопасность.

What the interviewer is testing

  • Точно объясняет назначение механизма «Nuxt authentication».
  • Показывает корректный минимальный пример без выдуманных API.
  • Называет ограничения, failure modes и production-компромиссы.

Sources

Related topics