Credentials handling

Модель доступа к API и роль токенов

Экосистема Mapbox построена вокруг токенов доступа, которые определяют возможность обращения к API, стилям и тайлам. В контексте Mapbox GL JS ключевым элементом является access token, передаваемый в клиентское приложение.

Токен выполняет три функции:

  • аутентификация запросов к Mapbox API
  • идентификация проекта/аккаунта
  • применение ограничений (scopes, URL restrictions)

В Mapbox GL JS он задаётся глобально:

import mapboxgl fr om 'mapbox-gl';

mapboxgl.accessToken = 'pk.abc123...';

Важно различать типы токенов:

  • Public token (pk.) — используется в браузере
  • Secret token (sk.) — используется только на сервере
  • Temporary token — краткосрочные токены с ограниченным временем жизни

Разделение public и secret токенов

Public token

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

  • разрешённые домены (Allowed URLs)
  • ограниченные scopes (например, только чтение тайлов)
  • отсутствие прав на изменение аккаунта

Типичная ошибка — использование public token без ограничений, что приводит к злоупотреблению квотой.


Secret token

Используется исключительно на серверной стороне:

  • генерация временных токенов
  • управление стилями через Mapbox APIs
  • доступ к административным операциям

Никогда не должен попадать в клиентский бандл. Даже при использовании SSR (Next.js, Nuxt) он должен оставаться в server runtime.


Ограничение токенов (Token Restrictions)

В панели Mapbox Studio задаются ограничения:

Ограничение по URL (Allowed URLs)

Позволяет ограничить использование токена конкретными доменами:

  • https://example.com
  • http://localhost:3000

Работает на уровне HTTP referer и origin.

Ограничение по scope

Примеры scope:

  • styles:read
  • tiles:read
  • datasets:read

Минимально необходимый набор принципиально снижает риск злоупотреблений.


Хранение токена в клиентских приложениях

Переменные окружения

В современных сборщиках используются .env файлы:

VITE_MAPBOX_TOKEN=pk.abc123
mapboxgl.accessToken = import.meta.env.VITE_MAPBOX_TOKEN;

Важно учитывать различия:

  • Vite: import.meta.env
  • Webpack: process.env
  • Next.js: process.env.NEXT_PUBLIC_*

Любая переменная, доступная в браузере, считается публичной.


Проблема утечек через bundle

Токен неизбежно попадает в JS-бандл. Поэтому:

  • его нельзя считать секретом
  • безопасность достигается только ограничениями
  • необходимо регулярно ротировать ключи при подозрении на компрометацию

Server-side proxy для повышения безопасности

Один из подходов — проксирование запросов через backend.

Схема:

Browser → Backend → Mapbox API

Преимущества:

  • скрытие secret token
  • контроль запросов
  • кэширование тайлов
  • rate limiting

Пример (Node.js):

app.get('/tiles/:z/:x/:y', async (req, res) => {
  const url = `https://api.mapbox.com/.../${req.params.z}/${req.params.x}/${req.params.y}?access_token=${process.env.MAPBOX_SECRET}`;

  const response = await fetch(url);
  const buffer = await response.arrayBuffer();

  res.setHeader('Content-Type', 'application/x-protobuf');
  res.send(Buffer.from(buffer));
});

Динамическая выдача токенов

Для продвинутых сценариев используется генерация временных токенов:

  • пользователь аутентифицируется на backend
  • backend запрашивает Mapbox API
  • выдаёт токен с ограниченным TTL

Преимущества:

  • ограничение времени жизни (например, 10 минут)
  • привязка к пользователю
  • минимизация риска повторного использования

Ротация токенов

Регулярная ротация снижает последствия компрометации:

Практика:

  • хранить несколько активных токенов
  • вводить новый токен заранее
  • постепенно выводить старый
  • мониторить usage analytics

Особенно важно при публичных репозиториях.


Безопасность при CI/CD

При сборке фронтенда часто возникает проблема случайного раскрытия токенов.

Рекомендации:

  • хранить токены в secret storage (GitHub Actions Secrets, GitLab CI Variables)
  • запрещать вывод env в логах
  • проверять bundle анализатором (webpack-bundle-analyzer)

CSP и ограничения выполнения

Content Security Policy влияет на загрузку ресурсов Mapbox:

Пример политики:

connect-src https://api.mapbox.com;
img-src https://*.tiles.mapbox.com;

Без корректной CSP:

  • тайлы не загружаются
  • стили частично ломаются
  • шрифты игнорируются

Ошибки, связанные с credentials

401 Unauthorized

Причины:

  • неверный токен
  • отсутствующий token
  • просроченный key

403 Forbidden

Причины:

  • домен не добавлен в allowed URLs
  • превышен scope
  • блокировка аккаунта

429 Rate Limit

Причины:

  • превышение квоты запросов
  • утечка токена
  • отсутствие кеширования

Безопасное использование в SPA

SPA архитектуры наиболее уязвимы, так как весь код открыт:

Практические меры:

  • минимальный scope токена
  • ограничение доменов
  • использование CDN кеширования тайлов
  • избегание генерации токена на клиенте

Работа с несколькими окружениями

Часто используется разделение:

  • development token
  • staging token
  • production token

Пример конфигурации:

const tokenMap = {
  development: 'pk.dev...',
  staging: 'pk.staging...',
  production: 'pk.prod...'
};

mapboxgl.accessToken = tokenMap[process.env.NODE_ENV];

Логирование и мониторинг использования токенов

Mapbox Dashboard предоставляет статистику:

  • количество запросов
  • типы API вызовов
  • география использования
  • ошибки авторизации

Анализ этих данных позволяет выявлять:

  • утечки токенов
  • аномальную активность
  • неправильные конфигурации

Практика минимизации риска компрометации

Основные принципы:

  • всегда использовать public token с ограничениями
  • secret token никогда не передавать в frontend
  • контролировать referrer whitelist
  • включать rate limiting на backend
  • регулярно ротировать ключи
  • мониторить usage

Интеграция в современные фреймворки

Next.js

export const mapToken = process.env.NEXT_PUBLIC_MAPBOX_TOKEN;

Важно: всё, что начинается с NEXT_PUBLIC_, становится доступным клиенту.


Vite

mapboxgl.accessToken = import.meta.env.VITE_MAPBOX_TOKEN;

Webpack

new DefinePlugin({
  'process.env.MAPBOX_TOKEN': JSON.stringify(process.env.MAPBOX_TOKEN)
});

Типовые архитектурные ошибки

  • хранение secret token в React коде
  • отсутствие ограничения по доменам
  • использование одного токена для всех окружений
  • отсутствие мониторинга usage
  • игнорирование rate limit

Эти ошибки приводят к прямым финансовым потерям из-за исчерпания квоты.


Кэширование как часть стратегии безопасности

Кэширование снижает количество запросов к API и уменьшает риск злоупотребления:

  • CDN для тайлов
  • browser cache headers
  • server-side tile caching

Итоговые инженерные принципы эксплуатации credentials

  • токен — это не секрет, а идентификатор с ограничениями
  • безопасность достигается политиками доступа, а не скрытием
  • архитектура должна учитывать неизбежную утечку public token
  • server-side слой необходим для чувствительных операций