JavaRush /Курсы /Модуль 4: Node.js, Next.js и Angular /Управление сессией пользователя:

Управление сессией пользователя: auth() в Server Components

Модуль 4: Node.js, Next.js и Angular
11 уровень , 2 лекция
Открыта

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() не предназначена для этого.

Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ