Стандартный OAuth 2.1
Инвойсбокс ID подключается по стандарту. Параметры и ответы называются так, как их ждут готовые
библиотеки OAuth, поэтому обмен не приходится писать руками. Библиотеке достаточно указать issuer —
https://api.invoicebox.ru, остальные адреса она прочитает из метаданных.
Что нужно получить заранее
Идентификатор приложения (client_id), список адресов возврата и набор прав запрашиваются у службы
поддержки. Права — это именованные наборы, те же, что видны в личном кабинете: приложение не может
попросить больше, чем ему разрешили при регистрации, а пользователь на экране согласия видит их
человеческими названиями, а не кодами.
Какие права бывают
Перечень полный — scope принимает только эти коды, через пробел.
| Код | Что разрешает |
|---|---|
merchant-read | просмотр заказов и платежей |
merchant-order | создание заказов |
merchant-refund | возвраты |
merchant-notification-read | просмотр журнала уведомлений |
merchant-notification-resend | переотправка уведомлений из журнала |
merchant-document-read | просмотр отчётных документов |
Просить больше, чем нужно, не надо. Пользователь видит запрошенное на экране согласия, и лишняя
строка — это причина отказать. Незнакомый код или право, которого у приложения нет, отклоняются с
invalid_scope.
Параметр scope можно не передавать — тогда запрашиваются все права, разрешённые приложению при
регистрации. Это не «минимум», а «максимум»: удобно начинать, но для боевого запуска перечисляйте
нужное явно. Список прав приложения со временем расширяется, и «все» завтра означает больше, чем
сегодня.
Со своей стороны мы просим у службы поддержки узкий список прав для новых приложений — ровно под задачу, а не «как у менеджера магазина». Если вам выдали больше, чем нужно, скажите: сузить список проще, чем потом объяснять пользователю, почему на экране согласия просят доступ к возвратам.
Что пользователь действительно разрешил, говорит не ваш запрос, а ответ: поле scope при обмене
кода и поле scopes в профиле. Проверять права нужно по
ним.
Секрет приложения выдаётся только тем, кто хранит его на сервере. Приложению, которое работает в браузере или на устройстве, секрет не нужен и не выдаётся: его невозможно там спрятать.
Метаданные сервера авторизации
Адреса не нужно хранить в коде — сервер сообщает их сам (RFC 8414).
- метод:
GET - ресурс:
/.well-known/oauth-authorization-server
{
"issuer": "https://api.invoicebox.ru",
"authorization_endpoint": "https://id.invoicebox.ru/oauth/authorize",
"token_endpoint": "https://api.invoicebox.ru/v3/security/oauth/token",
"revocation_endpoint": "https://api.invoicebox.ru/v3/security/oauth/revoke",
"response_types_supported": ["code"],
"grant_types_supported": ["authorization_code", "refresh_token"],
"code_challenge_methods_supported": ["S256"],
"token_endpoint_auth_methods_supported": ["client_secret_post", "none"]
}
Библиотеки OAuth читают этот документ сами, и обычно достаточно указать им issuer. Ответ 404
означает, что стандартные адреса в этой установке ещё не включены.
Обратите внимание, где что лежит. Сам документ — в корне хоста: его адрес выводится из issuer
по правилам стандарта, и клиент собирает его сам. А адреса обмена и отзыва берутся из документа
и лежат вместе с остальным API, под /v3/security/oauth/. Не собирайте их руками из issuer —
читайте из метаданных, тогда переезд адресов вас не коснётся.
Рядом лежит второй документ — /.well-known/oauth-protected-resource: он описывает уже сам API как
ресурс и называет сервер авторизации, у которого для него просят токен. Именно на него указывает
подсказка в отказе 401.
Как проходит вход
Четыре запроса, каждый на своей странице — по порядку, в котором они и делаются:
- Экран согласия — пользователь видит, какое приложение просит доступ и какие права, и разрешает или отклоняет.
- Обмен кода на токен — ваш сервер меняет одноразовый код на пару токенов.
- Обновление токена — когда срок access-токена истёк.
- Отзыв доступа — когда доступ больше не нужен.
Ниже — то, что относится к потоку целиком: ограничение токена одним сервисом, обязательность PKCE и коды ошибок.
Ограничение токена одним сервисом
Параметр resource (RFC 8707) говорит, для какого нашего сервиса нужен токен. Указали — токен
принимается только там; в другом сервисе он не сработает, даже если прав хватает.
Это защита от посредника. Приложение, которому доверили доступ к одному сервису, не должно уметь тем же токеном сходить в другой — а без указанного ресурса токен принимается всюду, где хватает прав.
Значение — адрес сервиса, целиком и без якоря, например https://mcp.invoicebox.ru/mcp. Незнакомый
адрес отклоняется с invalid_target: список известных ресурсов задаём мы, иначе токен получил бы
аудиторию, которую никто не проверяет. Указанный на первом шаге ресурс должен повториться при обмене
кода — иначе приложение получило бы доступ не туда, куда согласился пользователь.
PKCE обязателен
code_challenge и code_verifier нужны всем приложениям, включая серверные с секретом. Причина не в
формальности: код возвращается через браузер пользователя, а секрет приложения в этом обмене не
участвует — перехваченный код без code_verifier бесполезен, с секретом или без.
Поддерживается только метод S256. Приложения, зарегистрированные до этого требования, продолжают
работать по-прежнему, но при обновлении клиента стоит добавить PKCE: включение по одному приложению
делается по вашему запросу.
Ошибки
Отказы приходят по стандарту: код в поле error, пояснение для разработчика — в
error_description.
{
"error": "invalid_grant",
"error_description": "code: authorization code has expired"
}
| Код | Что случилось | Что делать |
|---|---|---|
invalid_request | не хватает параметра или он пустой | исправить запрос |
invalid_client | client_id неизвестен или приложение отключено | проверить идентификатор; отвечает 401 |
invalid_grant | код или токен обновления не подошёл: истёк, уже использован, выпущен для другого адреса возврата | пройти авторизацию заново |
unsupported_grant_type | такой способ получения токена не поддерживается | использовать authorization_code или refresh_token |
invalid_scope | запрошены права, которых у приложения нет | согласовать права с поддержкой |
invalid_target | незнакомый или несовпадающий resource | проверить адрес сервиса |
Читайте также
- Подключение — тот же поток по шагам, с кодом
- Справочник запросов — что нужно после входа: профиль и выход
- Сессия и безопасность — где держать токен, зачем
stateи PKCE - Авторизация запросов к API
- Безопасность работы с API — хранение токена и что делать при утечке