1. Управление сессией в Server Components
В современных приложениях на Next.js, особенно после появления App Router и Server Components, очень важно уметь получать информацию о текущем пользователе на серверной стороне. Это позволяет:
- Показывать разные данные для разных пользователей (например, личный кабинет, настройки, заказы).
- Защищать отдельные страницы или части интерфейса.
- Реализовывать авторизацию на уровне сервера (например, скрывать определённые блоки или делать редиректы).
Если раньше в Page Router мы использовали getSession() или getServerSession(), то теперь, с App Router и Server Components, появился более простой и удобный способ — функция auth().
Что такое функция auth() и зачем она нужна?
Функция auth() — это новый API из пакета next-auth, который предназначен для получения информации о текущей сессии пользователя непосредственно в Server Component, Server Action или Route Handler. Она возвращает объект сессии (или null, если пользователь не авторизован).
Почему это важно? Потому что Server Components выполняются на сервере, и у них нет доступа к браузерным cookies напрямую; все данные должны быть получены через серверные API.
Вот как это выглядит на практике:
// app/page.js (или .tsx)
import { auth } from "next-auth";
export default async function HomePage() {
const session = await auth();
return (
<main>
{session ? (
<div>
<h1>Добро пожаловать, {session.user.name}!</h1>
<p>Ваш email: {session.user.email}</p>
</div>
) : (
<p>Пожалуйста, войдите в систему.</p>
)}
</main>
);
}
Обратите внимание: функция auth() асинхронная, её нужно вызывать с await внутри асинхронного компонента или функции.
Как работает auth() под капотом
Когда вы вызываете auth() в Server Component, Next.js автоматически передаёт все необходимые данные (cookies, заголовки) в функцию, чтобы она могла проверить, есть ли у пользователя действующая сессия. Если сессия есть, возвращается объект с информацией о пользователе, если нет — null.
Структура возвращаемого объекта обычно такая:
{
user: {
name: "Иван Иванов",
email: "ivan@example.com",
image: "https://..."
},
expires: "2024-07-01T12:34:56.789Z"
}
Поля могут различаться в зависимости от провайдера и вашей конфигурации.
2. Защита страницы с помощью auth()
Допустим, у нас есть страница профиля пользователя, которую могут видеть только авторизованные пользователи.
// app/profile/page.js
import { auth } from "next-auth";
import { redirect } from "next/navigation";
export default async function ProfilePage() {
const session = await auth();
if (!session) {
// Если пользователь не авторизован — отправляем на страницу входа
redirect("/api/auth/signin");
}
return (
<div>
<h1>Профиль пользователя</h1>
<p>Имя: {session.user.name}</p>
<p>Email: {session.user.email}</p>
</div>
);
}
Здесь мы используем функцию redirect() из Next.js для перенаправления неавторизованных пользователей на страницу входа.
3. Как использовать auth() в Server Actions
Server Actions — это новый способ отправлять данные с формы напрямую на сервер (без отдельного API-эндпоинта). Иногда нужно знать, кто отправил форму. С auth() это делается просто:
// app/actions.js
"use server";
import { auth } from "next-auth";
export async function saveProfile(formData) {
const session = await auth();
if (!session) {
throw new Error("Требуется авторизация!");
}
// Теперь вы точно знаете, кто отправил форму
const email = session.user.email;
// ...дальнейшая обработка
}
4. Как использовать auth() в Route Handlers (API)
Иногда вам нужно проверить сессию не в компоненте, а в API-эндпоинте:
// app/api/user/route.js
import { auth } from "next-auth";
export async function GET(request) {
const session = await auth();
if (!session) {
return new Response("Не авторизован", { status: 401 });
}
return Response.json({
name: session.user.name,
email: session.user.email,
});
}
5. Сравнение с getServerSession()
До появления функции auth() в Server Components часто использовали getServerSession(). Вот как выглядел старый способ:
import { getServerSession } from "next-auth";
import { authOptions } from "@/app/api/auth/[...nextauth]/route";
export default async function Page() {
const session = await getServerSession(authOptions);
// ...
}
Недостатки:
- Нужно явно передавать authOptions (что не всегда удобно).
- Больше “шумного” кода.
- Не так удобно для Server Actions и Route Handlers.
Преимущества auth():
- Не требует передачи authOptions.
- Более лаконично, меньше кода.
- Универсально для Server Components, Server Actions и Route Handlers.
6. Практический пример: отображение меню пользователя
Давайте доработаем ваше учебное приложение: добавим в шапку сайта компонент, который показывает имя пользователя и ссылку на выход, если он вошёл, или ссылку на вход — если нет.
// app/components/UserMenu.js
import { auth } from "next-auth";
import Link from "next/link";
export default async function UserMenu() {
const session = await auth();
if (!session) {
return <Link href="/api/auth/signin">Войти</Link>;
}
return (
<div>
<span>Привет, {session.user.name}!</span>
<Link href="/api/auth/signout">Выйти</Link>
</div>
);
}
Теперь этот компонент можно использовать в любом Server Component — например, в layout:
// app/layout.js
import UserMenu from "./components/UserMenu";
export default function RootLayout({ children }) {
return (
<html>
<body>
<header>
<UserMenu />
</header>
{children}
</body>
</html>
);
}
7. Особенности и нюансы работы с auth()
- Асинхронность
Функция auth() всегда асинхронная, поэтому не забудьте объявлять компоненты как async и использовать await. - SSR и кеширование
Поскольку сессия зависит от cookies, Next.js автоматически отключает кеширование для Server Components, использующих auth(). Это важно: если вы видите предупреждение о кешировании — не пугайтесь, всё работает как надо. - Структура объекта session
По умолчанию объект session содержит поля user (с именем, email, картинкой) и expires. Если вы добавляете кастомные поля в callback'ах NextAuth, они тоже появятся в объекте. - Безопасность
Не полагайтесь на данные session на клиенте для проверки доступа! Всегда выполняйте критичные проверки на сервере.
8. Типичные ошибки при работе с auth() в Server Components
Ошибка №1: Забыт await перед auth()
// Ошибка!
const session = auth(); // вернёт Promise, а не объект
Правильно:
const session = await auth();
Ошибка №2: Использование auth() в Client Component
Функция работает только в Server Components, Server Actions и Route Handlers. Если попытаться вызвать её в Client Component, получите ошибку компиляции.
Ошибка №3: Попытка использовать session до получения
Если вы делаете несколько запросов параллельно, убедитесь, что session уже получена, прежде чем использовать её поля.
Ошибка №4: Ожидание, что session всегда будет
Не забывайте: если пользователь не авторизован, auth() вернёт null. Обрабатывайте этот случай явно!
Ошибка №5: Попытка получить session в middleware
Для middleware используйте другой подход (например, парсинг cookies вручную или через специальные утилиты), потому что auth() не предназначена для этого.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ