Auth.js (ранее NextAuth.js) — это популярная библиотека для аутентификации в Next.js-приложениях. Она предоставляет простой и гибкий способ настройки аутентификации с поддержкой множества провайдеров (например, Google, GitHub, Yandex и других). Однако часто возникает необходимость расширить стандартную сессию, чтобы добавить в нее дополнительные данные пользователя, такие как роль, дата создания аккаунта или другие поля. В этой статье мы рассмотрим, как расширить сессию в Auth.js, используя пример кода.
Зачем расширять сессию?
По умолчанию Auth.js предоставляет базовые данные о пользователе в сессии, такие как name, email и image. Однако в реальных приложениях часто требуется хранить и использовать дополнительные данные, например:
- Роль пользователя (администратор, модератор, пользователь).
- Идентификатор пользователя в базе данных.
- Дата создания и обновления аккаунта.
- Другие пользовательские поля.
Расширение сессии позволяет получить доступ к этим данным на клиенте и сервере, что упрощает разработку и улучшает функциональность приложения.
Пример расширения сессии в Auth.js
Рассмотрим пример кода, который расширяет сессию в Auth.js, добавляя в нее дополнительные поля пользователя.
1. Настройка NextAuth.js
Для начала настроим NextAuth.js с использованием Prisma в качестве адаптера. PrismaAdapter позволяет интегрировать Auth.js с базой данных, где хранятся данные пользователей.
typescriptimport NextAuth, { type DefaultSession } from "next-auth"; import { PrismaAdapter } from "@auth/prisma-adapter"; import { UserRole } from "@prisma/client"; import { prisma } from "@/prisma"; import type { Provider } from "next-auth/providers"; import Yandex from "next-auth/providers/yandex"; import GitHub from "next-auth/providers/github";
2. Расширение интерфейса сессии
Чтобы добавить дополнительные поля в сессию, необходимо расширить интерфейс Session из модуля next-auth. В данном примере мы добавляем поля id, role, createdAt и updatedAt.
typescriptdeclare module "next-auth" { interface Session { user: { id: string; name: string; email: string; emailVerified: string | null; image: string | null; role: UserRole; createdAt: Date; updatedAt: Date; } & DefaultSession["user"]; } }
3. Настройка провайдеров
Определяем провайдеры аутентификации. В данном примере используются Yandex и GitHub.
typescriptconst providers: Provider[] = [Yandex, GitHub]; export const providerMap = providers .map((provider) => { if (typeof provider === "function") { const providerData = provider(); return { id: providerData.id, name: providerData.name }; } else { return { id: provider.id, name: provider.name }; } }) .filter((provider) => provider.id !== "credentials");
4. Конфигурация NextAuth.js
Настраиваем NextAuth.js, используя PrismaAdapter и добавляем кастомный колбэк session, чтобы включить дополнительные данные пользователя в сессию.
typescriptexport const { handlers, signIn, signOut, auth } = NextAuth({ adapter: PrismaAdapter(prisma), providers, pages: { signIn: "/login", error: "/error", }, callbacks: { session({ session, user }) { session.user.id = user.id; session.user.role = user.role; session.user.createdAt = user.createdAt; session.user.updatedAt = user.updatedAt; return session; }, }, });
5. Использование расширенной сессии
Теперь, когда сессия расширена, вы можете использовать дополнительные данные пользователя в своих компонентах и API-роутах. Например:
typescriptimport { auth } from "@/auth"; export default async function Profile() { const session = await auth(); if (!session) { return <div>Необходимо авторизоваться</div>; } return ( <div> <h1>Профиль</h1> <p>Имя: {session.user.name}</p> <p>Роль: {session.user.role}</p> <p>Дата создания: {session.user.createdAt.toLocaleDateString()}</p> </div> ); }
Преимущества расширения сессии
-
Доступ к дополнительным данным
Расширение сессии позволяет получить доступ к данным, которые не включены в стандартную сессию Auth.js. -
Упрощение разработки
Вам не нужно делать дополнительные запросы к базе данных для получения данных пользователя, так как они уже доступны в сессии. -
Гибкость
Вы можете добавлять любые пользовательские поля, которые необходимы для вашего приложения.
6. Практическое применение расширенной сессии
Расширенная сессия может быть полезна в различных сценариях. Например:
-
Ролевая модель доступа
Если в вашем приложении есть разные роли пользователей (администратор, модератор, обычный пользователь), вы можете использовать полеroleдля управления доступом к определенным страницам или функциям.typescriptimport { auth } from "@/auth"; export default async function AdminPage() { const session = await auth(); if (!session || session.user.role !== "ADMIN") { return <div>Доступ запрещен</div>; } return ( <div> <h1>Административная панель</h1> <p>Добро пожаловать, {session.user.name}!</p> </div> ); } -
Отображение информации о пользователе
Вы можете использовать расширенные данные для отображения информации о пользователе на странице профиля.typescriptimport { auth } from "@/auth"; export default async function ProfilePage() { const session = await auth(); if (!session) { return <div>Необходимо авторизоваться</div>; } return ( <div> <h1>Профиль</h1> <p>Имя: {session.user.name}</p> <p>Email: {session.user.email}</p> <p>Роль: {session.user.role}</p> <p>Дата регистрации: {session.user.createdAt.toLocaleDateString()}</p> </div> ); } -
Логика на основе даты создания аккаунта
Если вам нужно реализовать логику, зависящую от даты создания аккаунта (например, показывать специальное сообщение для новых пользователей), вы можете использовать полеcreatedAt.typescriptimport { auth } from "@/auth"; export default async function WelcomeMessage() { const session = await auth(); if (!session) { return null; } const isNewUser = new Date().getTime() - session.user.createdAt.getTime() < 7 * 24 * 60 * 60 * 1000; // Проверяем, что пользователь зарегистрирован менее недели назад if (isNewUser) { return ( <div>Добро пожаловать! Мы рады видеть вас в нашем сообществе.</div> ); } return null; }
7. Безопасность и лучшие практики
При работе с расширенной сессией важно учитывать следующие аспекты безопасности:
-
Не передавайте чувствительные данные
Убедитесь, что вы не включаете в сессию данные, которые могут быть скомпрометированы (например, пароли или токены). -
Используйте HTTPS
Все данные сессии передаются между клиентом и сервером, поэтому важно использовать HTTPS для защиты от перехвата данных. -
Ограничивайте доступ к данным
Если вы используете ролевую модель, убедитесь, что доступ к данным ограничен в зависимости от роли пользователя. -
Регулярно обновляйте зависимости
Auth.js и связанные библиотеки (например, Prisma) регулярно обновляются. Убедитесь, что вы используете последние версии для получения исправлений уязвимостей.