Проверка авторизации в loader'ах

В TanStack Router loader — это функция, которая выполняется перед рендерингом маршрута и отвечает за подготовку данных, необходимых для компонента. Одним из ключевых применений loader’ов является проверка авторизации пользователя и управление доступом к защищённым маршрутам.

Основные принципы проверки авторизации

  1. Асинхронная природа loader’ов Loader может быть асинхронной функцией, что позволяет выполнять запросы к серверу или проверять токены аутентификации перед отображением компонента. Асинхронность важна для случаев, когда авторизация требует валидации JWT, проверки сессии или загрузки данных пользователя.

  2. Доступ к объекту context и params Loader получает объект context, содержащий глобальные данные приложения, и params, включающие параметры маршрута. Проверка авторизации часто строится на наличии токена в контексте или на данных из глобального состояния, например, Redux, Zustand или React Context.

import { createRouter } from '@tanstack/router';
import { redirect } from '@tanstack/router';

const router = createRouter({
  routes: [
    {
      path: '/dashboard',
      component: Dashboard,
      loader: async ({ context }) => {
        if (!context.user?.isAuthenticated) {
          throw redirect('/login');
        }
        return null;
      },
    },
  ],
});

В этом примере loader проверяет, авторизован ли пользователь, и при отсутствии авторизации выполняет перенаправление на страницу входа.

Управление доступом на основе ролей

Для сложных приложений часто требуется проверка роли пользователя:

loader: async ({ context }) => {
  const user = context.user;
  if (!user) throw redirect('/login');
  if (!user.roles.includes('admin')) throw redirect('/unauthorized');
  return user;
}

В данном случае loader проверяет не только факт авторизации, но и наличие определённой роли, что позволяет ограничить доступ к административным страницам.

Централизованная обработка авторизации

Чтобы избежать дублирования кода проверки авторизации на каждом маршруте, можно создать универсальную функцию requireAuth:

function requireAuth(user, redirectTo = '/login') {
  if (!user?.isAuthenticated) {
    throw redirect(redirectTo);
  }
  return user;
}

// Использование
loader: ({ context }) => requireAuth(context.user)

Такой подход улучшает читаемость и поддерживаемость маршрутов.

Обработка ошибок авторизации

TanStack Router позволяет ловить ошибки loader’ов через ErrorBoundary. Это особенно полезно, если проверка авторизации может возвращать кастомные ошибки:

{
  path: '/dashboard',
  component: Dashboard,
  loader: ({ context }) => requireAuth(context.user),
  errorComponent: AuthErrorPage,
}

Если loader выбрасывает исключение, AuthErrorPage получает объект ошибки и может отображать сообщение пользователю.

Поддержка асинхронной проверки токена

Часто проверка авторизации требует запроса к API для проверки действительности токена:

loader: async ({ context }) => {
  const token = context.user?.token;
  const response = await fetch('/api/verify-token', {
    headers: { Authorization: `Bearer ${token}` },
  });

  if (!response.ok) throw redirect('/login');

  const userData = await response.json();
  return userData;
}

В этом примере loader гарантирует, что маршрут будет доступен только после успешной валидации токена на сервере.

Вывод данных пользователя в компонент

Loader может возвращать объект с данными пользователя, которые затем становятся доступными компоненту маршрута:

loader: async ({ context }) => {
  const user = requireAuth(context.user);
  return { user };
}

// В компоненте
function Dashboard({ loaderData }) {
  return <div>Добро пожаловать, {loaderData.user.name}</div>;
}

Это позволяет компонентам оставаться чистыми и сосредоточенными только на отображении данных.

Лучшие практики

  • Минимизировать логику в компонентах: все проверки авторизации и редиректы должны выполняться в loader’ах.
  • Использовать централизованные функции проверки: для упрощения сопровождения и повторного использования кода.
  • Обрабатывать ошибки через ErrorBoundary: это упрощает вывод сообщений и управление доступом.
  • Асинхронная проверка: всегда учитывать задержки при обращении к API или проверке токена.

Таким образом, loader’ы TanStack Router предоставляют мощный инструмент для управления доступом, позволяя реализовать гибкую и безопасную систему авторизации на уровне маршрутов.