Браузерные ключи
Обычно 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) для ключа, чтобы украденный ключ не сжёг всю квоту тарифа.
- Ограничение — это сдерживающая мера, а не секрет. Держите отдельный серверный ключ без ограничений для работы с бэкендом.
Привязка ключа к сайту
-
Откройте проект в FastNear Dashboard и создайте (или выберите) API-ключ.
-
Включите Restrict to websites.
-
Перечислите через запятую домены, с которых обслуживается приложение:
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 документации сработало, а в приложении — нет
Сайт документации может подставлять сохранённый ключ для удобства — это не продовый шаблон. Поставляйте собственный браузерный ключ с ограничением, обслуживаемый с домена, указанного в ключе.
Нужен доступ и из браузера, и с бэкенда
Используйте два ключа: браузерный ключ с ограничением для фронтенда и серверный ключ без ограничений для бэкенда. Не пытайтесь использовать один ключ для обоих случаев.
Связанные руководства
- Аутентификация и доступ — серверный ключ по умолчанию и выбор способа передачи
- Аутентификация для агентов — режим выполнения для агентов и автоматизаций
- Справочник RPC