Перейти к основному содержимому

Браузерные ключи

Обычно API-ключ FastNear живёт на бэкенде. Но если приложение обращается к FastNear напрямую из браузера, можно опубликовать ключ во фронтенде и ограничить его доменами своего сайта — тогда скопированный ключ трудно использовать где-то ещё. Это режим браузерного ключа (или UI-ключа).

Два режима, одна модель учётных данных:

РежимГде живёт ключКак защищён
Серверный ключ (по умолчанию)бэкенд, воркер, прокси, менеджер секретовхранится в секрете; никогда не отправляется клиентам. См. Аутентификацию и доступ.
Браузерный ключпоставляется в сборке фронтендаограничен по Origin/Referer сайта плюс лимит частоты на ключ. Эта страница.

Браузерный ключ — это не секрет: его может прочитать любой из исходного кода страницы. Ограничение делает повторное использование неудобным, а лимит частоты снижает ущерб, если ключ всё же скопировали. Для всего, что должно оставаться секретом, используйте серверный ключ.

Доступность

Ограничение по сайтам — функция платных тарифов. На бесплатном тарифе этот элемент управления отключён — повысьте тариф проекта в FastNear Dashboard, чтобы включить браузерные ключи.

Если нужно только правило

  • Создайте ключ в панели управления, включите Restrict to websites и перечислите свои домены.
  • Ключ с ограничением работает только из браузера на подходящем Origin (или Referer); всё остальное получает 403 origin_not_allowed — включая собственный бэкенд.
  • Вызов из браузера работает и через Authorization: Bearer ..., и через ?apiKey=...; RPC FastNear отвечает на предварительный запрос CORS, поэтому работают оба варианта.
  • Задайте лимит частоты (Rate cap) для ключа, чтобы украденный ключ не сжёг всю квоту тарифа.
  • Ограничение — это сдерживающая мера, а не секрет. Держите отдельный серверный ключ без ограничений для работы с бэкендом.

Привязка ключа к сайту

  1. Откройте проект в FastNear Dashboard и создайте (или выберите) API-ключ.

  2. Включите Restrict to websites.

  3. Перечислите через запятую домены, с которых обслуживается приложение:

    example.com, *.example.com
    • Совпадение по имени хоста — точное. example.com не покрывает www.example.com или app.example.com — добавьте каждый хост или используйте подстановочный шаблон.
    • *.example.com совпадает с любым прямым поддоменом (app.example.com, www.example.com).
    • На один ключ можно указать до 20 доменов.
    • Не указывайте схему, порт или путь — только имя хоста (app.example.com, а не https://app.example.com/).

Включение ограничения жёстко блокирует любой вызов без подходящего Origin/Referer, включая собственный серверный трафик с этим ключом. Для вызовов с бэкенда используйте отдельный ключ без ограничений.

Как применяется ограничение

Проверка выполняется на периметре, до того как запрос дойдёт до RPC, по выставленному браузером заголовку Origin (с запасным вариантом Referer):

ЗапросРезультат
Origin совпадает с разрешённым доменом✅ проходит
нет Origin, но совпадает Referer✅ проходит
Origin есть, но не в списке403 origin_not_allowed
нет ни Origin, ни Referer (например, curl или бэкенд)403 origin_not_allowed
поддомен разрешённого домена без подстановочного шаблона403 origin_not_allowed

Origin имеет приоритет над Referer — запрос с недопустимым Origin отклоняется, даже если Referer подошёл бы. Тело ответа 403{"error":"origin_not_allowed"}.

Ключ без ограничения по сайтам считается серверным: проверка источника пропускается, и он работает откуда угодно (поэтому держите его в секрете).

Вызов FastNear из браузера

RPC-эндпоинт FastNear возвращает разрешающие заголовки CORS и отвечает на предварительный запрос OPTIONS, поэтому браузерный fetch() работает напрямую — прокси не нужен.

// Запущено на https://app.example.com (разрешённый домен этого ключа)
const FASTNEAR_API_KEY = 'YOUR_BROWSER_KEY'; // ограничен доменом app.example.com

const res = await fetch('https://rpc.mainnet.fastnear.com', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${FASTNEAR_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    jsonrpc: '2.0',
    id: 1,
    method: 'block',
    params: { finality: 'final' },
  }),
});
const data = await res.json();

Браузер автоматически отправляет Origin сайта, поэтому периметр может применить ограничение. Форма с параметром ?apiKey= тоже работает и удобна, когда выставлять заголовки неудобно:

const res = await fetch(`https://rpc.mainnet.fastnear.com?apiKey=${FASTNEAR_API_KEY}`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'block', params: { finality: 'final' } }),
});
примечание

Если браузерный вызов превышает лимит частоты, ответ 429 пока может не содержать заголовков CORS, поэтому браузер покажет его как обычную сетевую ошибку, а не как JSON-сообщение о лимите. Внезапный сбой fetch под нагрузкой стоит трактовать как возможное срабатывание лимита.

Ограничение масштаба ущерба

Опубликованный ключ рано или поздно скопируют. Два механизма удерживают цену этого низкой:

  • Лимит частоты (Rate cap) — задайте лимит на ключ (запросов в минуту) ниже тарифного по умолчанию. Тогда украденный ключ сможет потратить не больше этого лимита, а не всю квоту. Оставьте поле пустым, чтобы использовать значение тарифа по умолчанию.
  • Ротация (Rotate) — при злоупотреблении ключом выпустите новое значение, сохранив те же ограничения и лимит. Обновите сайт новым значением; старое значение перестаёт работать на периметре вскоре после синхронизации изменения.

Это сдерживающая мера, а не секрет

предупреждение

Заголовки Origin и Referer выставляет браузер, но небраузерный клиент (curl, скрипт) может их подделать. Поэтому ограничение по сайтам останавливает случайное повторное использование ключа, вытащенного со страницы, но это не строгая граница безопасности.

Что это значит на практике:

  • Риск утёкшего браузерного ключа — злоупотребление квотой и расходами: кто-то накручивает потребление по вашему тарифу. API-ключи FastNear — это учётные данные для лимитов и биллинга, а не ключи аккаунта NEAR, поэтому утёкший браузерный ключ не может переводить средства или подписывать транзакции по вашим аккаунтам.
  • Настоящая подстраховка — это лимит частоты (ограничивает ущерб) и ротация (прекращает его).
  • Никогда не помещайте в браузер учётные данные, которые должны оставаться секретом. Для всего чувствительного или неограниченного используйте серверный ключ за своим бэкендом.

Частые проблемы

403 origin_not_allowed от curl или с бэкенда

Так и должно быть — ключ с ограничением работает только из браузера на разрешённом домене. Бэкенды и curl не отправляют Origin/Referer. Для бэкенд-трафика используйте отдельный серверный ключ без ограничений.

Работает на example.com, но не на www.example.com

Совпадение по имени хоста — точное. Добавьте www.example.com к ключу или используйте *.example.com, чтобы покрыть поддомены.

Браузерный вызов падает без внятной ошибки

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

В UI документации сработало, а в приложении — нет

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

Нужен доступ и из браузера, и с бэкенда

Используйте два ключа: браузерный ключ с ограничением для фронтенда и серверный ключ без ограничений для бэкенда. Не пытайтесь использовать один ключ для обоих случаев.

Связанные руководства