Аутентификация

Bearer-токены API, модель областей доступа «сущность плюс действие» и почему запрет по умолчанию означает отказ, а не разрешение.

Каждый запрос к публичному API несёт bearer-токен:

GET /v1/tables HTTP/1.1
Host: api.foxguide.io
Authorization: Bearer fgd_live_0123456789abcdef...

Токены выпускаются в интерфейсе платформы под пользовательской сессией, а не через этот API. Управление токенами живёт на /v1/api-tokens, и этот путь намеренно не входит в публичную поверхность — токен нельзя выпустить токеном. Секрет показывается один раз, при создании; платформа хранит только его хеш и больше никогда не сможет показать вам сам секрет.

Область доступа — это сущность, умноженная на действие

Токен несёт список областей доступа. Каждая область называет одну сущность и разрешённые над ней действия из набора read, write, delete:

{
  "scopes": [
    { "entity": "table",  "actions": ["read", "write"] },
    { "entity": "export", "actions": ["read"] }
  ]
}

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

Запрет по умолчанию и что это значит на практике

Авторизация работает на отказ (fail-closed). Запрос разрешается только тогда, когда токен несёт область доступа с сущностью этого эндпоинта и в списке действий этой области есть то действие, которое эндпоинт выполняет. Всё остальное отклоняется.

Два случая стоит назвать прямо, потому что именно они удивляют интеграторов:

  • Токен, у которого вообще нет списка областей доступа, отклоняется, а не разрешается. Отсутствующий список трактуется ровно так же, как пустой.
  • Токен с read на сущности отклоняется на эндпоинтах write этой же сущности. Действия не иерархичны, и write не подразумевает delete.

INSUFFICIENT_SCOPE — отказ, который вы встретите на деле

Когда токен аутентифицирован, но не имеет области доступа под то, что запросил, API отвечает 403 с плоским конвертом ошибки и кодом INSUFFICIENT_SCOPE:

HTTP/1.1 403 Forbidden
Content-Type: application/json

{
  "error": "INSUFFICIENT_SCOPE",
  "message": "API token does not have scope export:write"
}

Поле message называет оба члена отказа — сущность и действие, — поэтому исправление механическое: перевыпустите токен, добавив эту сущность и это действие в список областей доступа.

INSUFFICIENT_SCOPE — основной отказ публичного API. Именно его видит корректно аутентифицированный клиент всякий раз, когда запрос выходит за пределы выданного токену, а при запрете по умолчанию это любой запрос, под который токен не выпускали явно.

Отличайте его от соседей:

статускодчто произошло
401UNAUTHORIZEDтокен отсутствует, повреждён, истёк или отозван — вы вообще не аутентифицированы
403INSUFFICIENT_SCOPEвы аутентифицированы; у этого токена нет области доступа, которую требует эндпоинт
404<DOMAIN>_NOT_FOUNDаутентифицированы, область доступа есть; ресурса не существует

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

См. также

  • Быстрый старт — выпуск токена, единожды показываемый секрет и ротация с 24-часовым льготным периодом
  • Ошибки — плоский конверт и то, какие отказы имеет смысл повторять
  • Лимиты частоты — другой 4xx, который встречает рабочая интеграция, и тот единственный 403 (IP_NOT_ALLOWED), что не про области доступа
  • Справочник API — авторитет по тому, какие сущность и действие требует конкретный эндпоинт

← Вся документация