Аутентификация
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. Именно его видит
корректно аутентифицированный клиент всякий раз, когда запрос выходит за
пределы выданного токену, а при запрете по умолчанию это любой запрос, под
который токен не выпускали явно.
Отличайте его от соседей:
| статус | код | что произошло |
|---|---|---|
| 401 | UNAUTHORIZED | токен отсутствует, повреждён, истёк или отозван — вы вообще не аутентифицированы |
| 403 | INSUFFICIENT_SCOPE | вы аутентифицированы; у этого токена нет области доступа, которую требует эндпоинт |
| 404 | <DOMAIN>_NOT_FOUND | аутентифицированы, область доступа есть; ресурса не существует |
403 никогда не повод для повтора. Повтор с тем же токеном даст тот же отказ, потому что в запросе ничего не изменилось, — вместо этого перевыпустите токен.
См. также
- Быстрый старт — выпуск токена, единожды показываемый секрет и ротация с 24-часовым льготным периодом
- Ошибки — плоский конверт и то, какие отказы имеет смысл повторять
- Лимиты частоты — другой 4xx, который встречает рабочая
интеграция, и тот единственный 403 (
IP_NOT_ALLOWED), что не про области доступа - Справочник API — авторитет по тому, какие сущность и действие требует конкретный эндпоинт