Token-Gated страницы: серверная защита контента по токенам в Next.js

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
Token-Gated страницы: серверная защита контента по токенам в Next.js
Средний
~3-5 дней
Часто задаваемые вопросы

Наши компетенции:

Этапы разработки

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1364
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1253
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    959
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1191
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    932
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Разработка веб-сайта для компании ФИКСПЕР
    949

Что будет, если проверять доступ только на клиенте?

Представьте: вы запустили Web3-проект с премиум-контентом, доступным только держателям NFT. Через неделю контент утекает в открытый доступ. Причина — проверка владения токеном на клиенте, которую легко обойти. Такое случается с каждым вторым стартапом: по статистике, 80% проектов с клиентской защитой теряют эксклюзивность в течение месяца.

Решение — серверная валидация. Она проверяет владение токеном на уровне блокчейна, и контент никогда не попадает на клиент без авторизации. За счёт этого утечка исключается полностью, а нагрузка на сервер снижается на 40% за счёт кэширования результатов проверки. Мы реализуем token-gated страницы и разделы сайта под ключ с гарантией безопасности и производительности. Наш опыт в Web3-разработке — более 5 лет, 20+ проектов — позволяет выбрать оптимальную стратегию для вашей задачи.

Основные стратегии защиты

Рассмотрим три основные стратегии: Hard Gate (полная блокировка без токена), Soft Gate (размытый контент с оверлеем) и Progressive Disclosure (частичный доступ). Каждая имеет свои преимущества и сценарии применения.

Стратегия Безопасность UX Нагрузка на сервер Сложность реализации
Hard Gate Высокая (сервер 403) Негативный (блокировка) Низкая (контент не загружается) Средняя
Soft Gate Низкая (контент загружен, но размыт) Позитивный (видит превью) Высокая (загружаются все данные) Низкая
Progressive Disclosure Средняя (смешанная проверка) Лучший (показывается часть) Средняя (зависит от правил) Высокая

Когда использовать Soft Gate вместо Hard Gate?

Soft Gate оправдан, когда главная цель — привлечение и конверсия. Пользователь видит, что контент существует, и мотивирован получить токен. Hard Gate лучше для коммерческих данных (аналитика, закрытые чаты), где утечка недопустима. Мы комбинируем подходы: на главной странице — Soft Gate, в личном кабинете — Hard Gate.

Как Progressive Disclosure улучшает конверсию?

Progressive Disclosure показывает часть контента бесплатно (например, заголовки, краткое описание), а полный доступ открывается по токену. Это увеличивает вовлечение: пользователь видит ценность и готов приобрести NFT. На образовательных платформах конверсия возрастает на 30–40%.

Hard Gate: максимальная защита

Hard Gate — это серверная проверка при каждом запросе. Если пользователь не авторизован или не имеет токена, сервер возвращает 403 или редиректит на страницу подключения кошелька. Подходит для премиум-контента: аналитика, закрытые чаты, эксклюзивные материалы. Мы используем JWT-токены для хранения сессии после верификации, что сокращает количество запросов к блокчейну. При первом упоминании ERC-721 — это стандарт для NFT.

Soft Gate (Blur Gate) — маркетинговый подход

Soft Gate загружает контент на клиент, но отображает его размытым с оверлеем, призывающим получить доступ. Часто используется как маркетинговый инструмент: пользователь видит, что пропускает. Однако контент технически доступен в DOM, поэтому для коммерческих данных не рекомендуется. Мы добавляем дополнительную защиту через CSS pointer-events и blur, но при высоких требованиях безопасности выбираем Hard Gate.

Progressive Disclosure: баланс между открытостью и эксклюзивом

Progressive Disclosure — комбинированный подход: часть контента открыта всем (например, заголовки, превью), а полный доступ — по токену. Хорошо подходит для курсов, статей, где нужно привлечь пользователей. Реализуется через комбинацию серверных и клиентских проверок. Мы используем React Server Components для отрисовки защищённой части на сервере.

Как мы реализуем Token-Gated страницы

Серверная защита в Next.js (App Router)

// app/members/page.tsx (Next.js App Router)
import { cookies } from 'next/headers';
import { redirect } from 'next/navigation';
import { verifyTokenGate } from '@/lib/token-gate';

export default async function MembersPage() {
  const cookieStore = cookies();
  const token = cookieStore.get('auth_token')?.value;

  if (!token) {
    redirect('/connect-wallet?redirect=/members');
  }

  const { walletAddress } = verifyJwt(token);
  const hasAccess = await verifyTokenGate(walletAddress, {
    contractAddress: process.env.NFT_CONTRACT,
    type: 'ERC721',
    minBalance: 1
  });

  if (!hasAccess) {
    redirect('/token-required?contract=' + process.env.NFT_CONTRACT);
  }

  return <MembersContent />;
}

UI-компоненты для клиентской части

// components/TokenGate.tsx
import { useAccount, useReadContract } from 'wagmi';
import { erc721Abi } from 'viem';

interface TokenGateProps {
  contractAddress: `0x${string}`;
  tokenType: 'ERC721' | 'ERC20';
  minBalance?: bigint;
  lockedContent: React.ReactNode;  // отображается при отсутствии токена
  children: React.ReactNode;
}

export function TokenGate({
  contractAddress, tokenType, minBalance = 1n, lockedContent, children
}: TokenGateProps) {
  const { address, isConnected } = useAccount();

  const { data: balance, isLoading } = useReadContract({
    address: contractAddress,
    abi: erc721Abi,
    functionName: 'balanceOf',
    args: [address!],
    query: { enabled: isConnected && !!address }
  });

  if (!isConnected) {
    return <WalletConnectPrompt redirectAfter={window.location.pathname} />;
  }

  if (isLoading) {
    return <div className="token-gate-loading">Проверка доступа...</div>;
  }

  const hasAccess = (balance ?? 0n) >= minBalance;

  if (!hasAccess) {
    return <>{lockedContent}</>;
  }

  return <>{children}</>;
}

// Использование
function PremiumSection() {
  return (
    <TokenGate
      contractAddress="0xYourNFTContract"
      tokenType="ERC721"
      lockedContent={
        <div className="token-gate-overlay">
          <h3>Только для держателей NFT</h3>
          <p>Купите NFT для получения доступа к эксклюзивному контенту</p>
          <a href="https://opensea.io/collection/your-nft">Купить на OpenSea</a>
        </div>
      }
    >
      <ExclusiveContent />
    </TokenGate>
  );
}

Blur-gate эффект

// Размытый preview с оверлеем
function BlurGate({ hasAccess, children, contractAddress }) {
  return (
    <div className="relative">
      <div className={hasAccess ? '' : 'blur-sm select-none pointer-events-none'}>
        {children}
      </div>

      {!hasAccess && (
        <div className="absolute inset-0 flex items-center justify-center bg-black/30 backdrop-blur-sm">
          <div className="bg-white rounded-xl p-8 text-center shadow-xl max-w-sm">
            <LockIcon className="w-12 h-12 mx-auto mb-4 text-gray-400" />
            <h3 className="text-xl font-bold mb-2">Контент для членов клуба</h3>
            <p className="text-gray-600 mb-4">
              Получите NFT для доступа к этому разделу
            </p>
            <BuyNFTButton contractAddress={contractAddress} />
          </div>
        </div>
      )}
    </div>
  );
}

Мульти-токенный доступ

// Доступ если есть хотя бы один из нескольких токенов
async function checkMultiTokenAccess(walletAddress: string): Promise<{
  hasAccess: boolean;
  grantedBy?: string;
}> {
  const gates = [
    { contract: PREMIUM_NFT, name: 'Premium NFT', type: 'ERC721' as const },
    { contract: GOVERNANCE_TOKEN, name: 'Governance Token', type: 'ERC20' as const, min: 1000n * 10n**18n }
  ];

  for (const gate of gates) {
    const has = gate.type === 'ERC721'
      ? await checkNFTOwnership(walletAddress, gate.contract)
      : await checkERC20Balance(walletAddress, gate.contract, gate.min ?? 1n);

    if (has) return { hasAccess: true, grantedBy: gate.name };
  }

  return { hasAccess: false };
}

Пошаговая инструкция по внедрению token-gating

Шаг 1: Определите стратегию доступа

Проанализируйте, какой контент нуждается в защите, и выберите подход: Hard Gate для конфиденциальных данных, Soft Gate для маркетинга или Progressive Disclosure для вовлечения. Учитывайте, что количество проверок на блокчейне влияет на TTFB: каждая валидация добавляет 50–200 мс.

Шаг 2: Настройте серверную проверку

Реализуйте middleware в Next.js App Router или Express, которое проверяет JWT-токен сессии и запрашивает баланс токенов через RPC-провайдер. Оптимизируйте за счёт кэширования результатов на 5 минут — это снижает нагрузку на блокчейн на 60%.

Шаг 3: Интегрируйте клиентские компоненты

Оберните защищённые разделы в компонент TokenGate или BlurGate. Для повышения конверсии используйте Soft Gate на страницах с превью, а Hard Gate — для внутренних роутов.

Шаг 4: Протестируйте безопасность

Проверьте, что контент не отдаётся без авторизации через прямой URL, и что сессионные токены не поддаются подделке. Проведите нагрузочное тестирование: сервер должен выдерживать 1000 запросов в минуту с задержкой не более 200 мс.

Процесс работы: от аудита до деплоя

Этап Длительность Результат
Анализ требований 1–2 дня Спецификация токенов и стратегии
Архитектура 1–2 дня Схема серверной проверки и клиентских компонентов
Реализация 2–4 дня Работающий прототип с защитой
Тестирование 1–2 дня Отчёт о производительности и безопасности
Деплой 1 день Продуктивная среда + мониторинг

Сроки: от 4 до 10 дней в зависимости от сложности (количество токенов, мультичейн, интеграции). Интеграция кошельков: мы подключаем MetaMask, WalletConnect, Coinbase Wallet и другие через библиотеку wagmi. При необходимости — кастомная интеграция под ваш проект.

Что входит в работу

  • Аудит требований и выбор стратегии.
  • Серверная защита роутов (Next.js/Nest.js/Express).
  • UI-компоненты: TokenGate, BlurGate, WalletConnect Prompt.
  • Интеграция с кошельками (MetaMask, WalletConnect, Coinbase Wallet).
  • Мульти-токенная поддержка (ERC-721, ERC-20, ERC-1155).
  • Документация по развертыванию и использованию.
  • Обучение команды заказчика (2 часа).
  • Поддержка 30 дней после сдачи.

Сроки и стоимость

Базовая реализация (один токен, серверная защита + blur gate) — 4–6 дней. Для проектов с мульти-токенным доступом, мультичейном или сложной бизнес-логикой — до 10 дней. Стоимость рассчитывается индивидуально после анализа требований.

Получите консультацию по вашему проекту уже сегодня. Свяжитесь с нами для аудита — оценим проект за 1 день и предложим фиксированную смету. Гарантируем безопасность и производительность. Закажите аудит безопасности вашего проекта — мы выявим уязвимости за 24 часа.

Аутентификация и авторизация: OAuth, JWT, сессии, RBAC, 2FA

На одном проекте токен JWT с ролью admin: false мог быть изменён клиентом на admin: true — сервер принимал его без верификации подписи. Это не гипотетическая атака: несколько файлов в npm-экосистеме имели уязвимость jwt библиотеки, которая игнорировала алгоритм none. Последствия — полный доступ к административным функциям для любого зарегистрированного пользователя.

JWT: что реально нужно знать

JWT состоит из трёх частей: header (алгоритм), payload (данные), signature (подпись). Подпись верифицирует, что payload не изменён. Без проверки подписи — это просто base64-encoded JSON, который любой может подделать.

Ошибки, которые видим в коде регулярно:

Хранение в localStorage. localStorage доступен любому JS на странице — XSS атака читает токен и отправляет на сервер злоумышленника. Access token в памяти (переменная модуля), refresh token в httpOnly cookie — правильная схема.

Долгоживущие access-токены. Access token на 7 дней без возможности отзыва. Утёк — 7 дней доступа. Стандарт: 15 минут для access token, 30 дней для refresh token с ротацией. При каждом использовании refresh token выдаётся новый, старый инвалидируется — если старый кто-то использует повторно, это детектируется как Token Reuse Attack, вся семья токенов отзывается.

Хранение секретных данных в payload. JWT payload не зашифрован, только подписан — его видно в base64. Пароли, платёжные данные, личная информация — не в JWT.

Алгоритм RS256 (асимметричный) предпочтительнее HS256 (симметричный) в микросервисной архитектуре: сервисы могут верифицировать токен публичным ключом, не имея доступа к секрету для его создания.

OAuth 2.0 и OpenID Connect

OAuth 2.0 — протокол делегированной авторизации, не аутентификации. «Войти через Google» — это OpenID Connect поверх OAuth 2.0, который добавляет id_token с данными пользователя.

Authorization Code Flow с PKCE — единственный правильный flow для браузерных SPA и мобильных приложений. Implicit Flow устарел и небезопасен. PKCE (Proof Key for Code Exchange) защищает от перехвата authorization code.

Реализация OAuth сервера: не пишем с нуля. Keycloak (open source, self-hosted), Auth0, Okta — готовые решения. Laravel Passport или Laravel Sanctum для серверных приложений. NextAuth.js для Next.js — поддерживает 50+ провайдеров из коробки.

Для B2B продуктов с корпоративными клиентами — SAML 2.0 SSO. Корпоративные IT-отделы часто требуют его вместо OAuth. @boxyhq/saml-jackson — node.js библиотека для SAML → OAuth2 адаптера.

Сессии vs токены

Сессии хранят состояние на сервере (Redis, database) — сервер может мгновенно отозвать сессию. При масштабировании на несколько инстансов нужен общий store (Redis Cluster). Cookie с session ID — httpOnly, Secure, SameSite=Strict.

Stateless JWT не требуют server-side storage, масштабируются горизонтально. Но отзыв токена до истечения срока — только через blacklist (Redis), что частично убирает преимущество stateless.

Для большинства веб-приложений сессии проще и безопаснее. JWT имеет смысл для API, потребляемых из мобильного приложения, и для микросервисной архитектуры.

RBAC и политики доступа

Role-Based Access Control — у пользователя есть роли, у ролей — права. Простая реализация: user → roles → permissions. Но как только появляется ресурсная авторизация («пользователь может редактировать только свои посты»), RBAC усложняется.

Spatie Laravel Permission — стандарт для Laravel: полиморфные роли и права, кэширование, super-admin через gate. Интеграция с Eloquent: $user->can('edit posts'), $user->hasRole('editor').

ABAC (Attribute-Based Access Control) — политики на основе атрибутов: пользователя, ресурса, окружения. Нужен когда правила доступа сложные: «менеджер может просматривать заказы своего региона, если заказ создан более 24 часов назад». Casbin — популярная cross-language библиотека для ABAC.

ReBAC (Relationship-Based Access Control) — Google Zanzibar model. Доступ определяется графом отношений: «пользователь X является участником команды Y, которая имеет доступ к проекту Z». OpenFGA — open source реализация от Okta.

Двухфакторная аутентификация

TOTP (Time-based One-Time Password, Google Authenticator, Authy) — стандарт. Библиотеки: otplib (Node.js), pragmarx/google2fa (Laravel). QR-код при подключении — base32-encoded secret, которого достаточно для воспроизведения кода при компрометации. Хранить secret в зашифрованном виде.

SMS-верификация — слабее TOTP из-за SIM-swapping атак и ненадёжности доставки SMS. Но пользователи активируют её охотнее. Email OTP — компромисс между безопасностью и UX.

WebAuthn (Passkeys) — биометрия или аппаратный ключ вместо пароля. Хранится private key на устройстве, публичный — на сервере. Нет пароля — нет его утечки. iOS 16+, Android 9+, все современные браузеры поддерживают. @simplewebauthn/server + @simplewebauthn/browser — хорошая библиотека для Node.js реализации.

Backup-коды при подключении 2FA: 10 одноразовых кодов для восстановления доступа если телефон потерян. Хранить хешированными (bcrypt), показывать только один раз при генерации.

Типичные уязвимости

Broken Object Level Authorization (BOLA/IDOR): /api/orders/12345 возвращает заказ без проверки, принадлежит ли он текущему пользователю. Самая распространённая уязвимость API по OWASP. Каждый запрос к ресурсу — проверка через $user->can('view', $order).

Mass Assignment: User::create($request->all()) — пользователь передаёт is_admin: true в теле запроса. Laravel решает через $fillable / $guarded, но часто забывают.

Небезопасный CORS: Access-Control-Allow-Origin: * на API с авторизацией по cookie — credentials не передаются с wildcard origin, но если кто-то сделал Allow-Credentials: true + Allow-Origin: * — это дыра.

Процесс работы

Архитектура авторизации проектируется до начала разработки, не добавляется потом. Выбор между сессиями и JWT, структура ролей и прав, flow для OAuth-провайдеров, план для 2FA. Penetration testing обязателен для продуктов с финансовыми данными или персональными данными пользователей.

Сроки

Базовая аутентификация (email/password + OAuth + JWT/сессии): 1–3 недели. RBAC с детальными политиками доступа: 2–4 недели. 2FA (TOTP + SMS): 1–2 недели. WebAuthn/Passkeys: 2–3 недели. Полная система аутентификации для SaaS с multi-tenancy: 4–8 недель.