Перейти к содержанию

Web3: домен, сеть и срок подписи

Оглавление курса «Web3: вход, смарт-аккаунты и индексатор» · Урок 4 из 30.

Правильная подпись подтверждает только точное сообщение, которое подписано. Если сервер принимает любой домен, сеть или срок, криптография не спасает неверную политику входа. В этом уроке сопоставим поля SIWE с ожидаемым challenge и рассмотрим границы конфигурации origin. Результат — сообщение для другого сайта или другой попытки не создаёт сессию библиотеки.

Предполагаются выдача challenge и атомарное потребление nonce. Проверка подписи появится следующим шагом. Программы не запускались; мы разбираем серверную политику по первичному стандарту и собственным входам. Учебный домен library.example и сеть31337 остаются явными значениями конфигурации, не production-параметрами ProfessorWeb.

Ожидаемые поля принадлежат серверу

Сервер знает свой допустимый домен и URI. Он также знает адрес, nonce, срок и сеть сохранённого challenge. Клиент приносит сообщение для проверки, но не выбирает ожидаемые значения заново в том же запросе. Если взять expectedDomain из JSON посетителя, сравнение станет бесполезным: человек просто пришлёт одинаковые ложные строки с обеих сторон.

Сравнение domain учитывает стандартное представление authority, включая порт, если он используется. Для локального сервиса с конкретным портом эта часть важна. Нельзя срезать всё после двоеточия универсальным правилом и считать любые сервисы одного host одинаковым назначением. Инфраструктура proxy отдельно определяет, какие внешние адреса являются допустимыми.

URI тоже является назначением входа, а не свободным возвратным URL. Открытый redirect после аутентификации имеет собственные ограничения. Проверка SIWE не делает безопасной произвольную ссылку, по которой браузер уйдёт после получения сессии. В нашем учебном маршруте URI фиксирован и не зависит от пользовательского параметра навигации.

Разбор без изменения байтов

parseSiweMessage помогает прочитать поля, но подпись проверяется для исходного сообщения. Не следует разобрать его, заново собрать с удобными пробелами и проверить уже другую строку. Точный текст сохранён в challenge и сопоставляется до дальнейшего шага.

import { getAddress } from 'viem';
import { parseSiweMessage } from 'viem/siwe';

export function checkChallengeFields(message, challenge, now = new Date()) {
  if (message !== challenge.message) throw new Error('Сообщение изменено');
  const fields = parseSiweMessage(message);
  if (fields.domain !== 'library.example'
      || fields.uri !== 'https://library.example/account/login'
      || fields.chainId !== 31337
      || fields.version !== '1'
      || fields.nonce !== challenge.nonce
      || !fields.address
      || getAddress(fields.address) !== getAddress(challenge.address)) {
    throw new Error('Назначение входа не совпадает');
  }
  if (Date.parse(challenge.expiresAt) <= now.getTime()) {
    throw new Error('Challenge истёк');
  }
  return fields;
}

Это функция сопоставления для выданного нами формата, не универсальный parser всех вариантов SIWE. Проверка стандарта и криптографической подписи также выполняется выбранной библиотекой. При ошибке разбора функция не выдаёт нормализованный пустой объект как допустимый вход. Размер сообщения ограничивается HTTP-адаптером до обработки.

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

Время выдачи и истечения

Время Issued At сообщает, когда challenge был создан. Expiration Time ограничивает пригодность. Not Before, если используется, задаёт нижнюю границу. Сервер сопоставляет значения с записью и учитывает собственные часы. Дата из будущего не должна автоматически увеличивать разрешённый срок только потому, что подпись правильная.

Допустимый сдвиг часов является политикой конкретной системы. Нельзя рекомендовать произвольное большое окно всем сайтам ради удобства. Наш challenge создаётся сервером, поэтому браузерные часы не выбирают его срок. При длительном ожидании кошелька сервер может отказать в истёкшей попытке и выдать новую по действию человека.

Повторная криптографическая проверка после срока не делает подпись неверной математически. Она просто больше не удовлетворяет прикладным условиям входа. Это различие важно для сообщений: «Попытка входа истекла» полезнее необоснованного «Кошелёк подписал неправильно». Человек понимает, что начать заново, не раскрывая секреты.

Сеть контрактного адреса

Обычный адрес может выглядеть одинаково в нескольких сетях. Для контрактного аккаунта код и правила подписи выбираются именно в сети сообщения. Проверка ERC-1271 через произвольный endpoint другой цепочки может ответить совершенно иной логикой. Поэтому серверный Public Client выбирается по разрешённой конфигурации, а chainId сообщения должен ей соответствовать.

Даже для EOA сеть остаётся частью назначения сессии, если так сформирован challenge. Не следует удалять её проверку на основании того, что восстановление обычной подписи не обращается в сеть. Прикладной договор сообщения включает поле независимо от конкретного алгоритма аккаунта.

Для поддержки нескольких сетей сервер имеет известную таблицу clients и допустимых вариантов. Произвольный RPC URL из сообщения не принимается. Иначе маршрут аутентификации превратится в сетевой прокси с неизвестным источником ответов и новыми рисками инфраструктуры. Адрес аккаунта не позволяет человеку выбрать произвольный сервер проверки.

Назначение и ресурсы

Дополнительные SIWE resources могут описывать разрешённые отношения с ресурсами, но сервер не выдаёт автоматически любые роли из списка, принесённого клиентом. Вход всё равно проходит политику сайта. Если приложение использует resources, их значения заранее определяются challenge и проверяются после разбора. Базовый курс не добавляет скрытого разрешения на публикацию или перевод.

Для упражнения возьмите правильную подпись и замените domain, URI, сеть или срок в сопутствующем ожидаемом объекте клиента. Сервер должен опираться на собственную запись и отвергнуть несоответствие. Затем рассмотрите истечение во время проверки: атомарное потребление повторно проверяет срок. Ожидаемый итог — проверка назначения и криптография дополняют друг друга. Правила полей приведены в ERC-4361.

Публичный домен и серверный адрес

За reverse proxy сервер может видеть внутреннее имя и порт, которые отличаются от публичного origin. Настройка входа берёт ожидаемое внешнее назначение из контролируемой конфигурации и доверяет только определённым proxy-заголовкам. Произвольный Forwarded от клиента не становится источником истины.

Если сайт переезжает на другой домен, это новая политика сообщения и сессии. Старый challenge не должен автоматически приниматься новым сервисом лишь потому, что в базе сохранился тот же адрес. Пользователь видит новое назначение и подписывает новый вход. Сохранение учебных URL ProfessorWeb относится к статическому сайту и не отменяет явного домена аутентификации демонстрационного кабинета.

Конфигурация нескольких доменов

Локальная версия и production получают отдельные разрешённые origin. Не создаём правило «принимать любой поддомен», если задача требует лишь одного сайта. Для второго домена заводим явную конфигурацию и отдельный поток входа; подпись первого домена не становится общей сессией всей организации.

Оглавление серии