Как реализовать аутентификацию в 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-компромиссы.