В интеграциях с внешними приложениями часто используется протокол OAuth 2.0. Он позволяет приложению получить доступ к данным пользователя без передачи пароля. В этой статье разбирается практический сценарий: получение access_token, обновление токена, работа с ошибками и использование токена аккаунта для фоновых операций.
Подробная диаграмма последовательности процесса авторизации.
Далее описан алгоритм авторизации по протоколу OAuth 2.0.
1 Инициация — получение параметров аккаунта
Пользователь переходит из страницы настройки интеграции в стороннее приложение. В URL передаются параметры аккаунта: account_id и account_name
https://%domain%.ru/api/oauth2/auth?account\_id=<идентификатор аккаунта>&account_name=<наименование аккаунта>
Стороннее приложение сохраняет account_id (идентификатор аккаунта) и account_name(наименование аккаунта). Они потребуются при создании подключения и получении токена аккаунта.
2 Перенаправление на сервер аутентификации
Приложение перенаправляет пользователя на сервер аутентификации для получения кода авторизации — authorization code :
https://id.provider.com/authorize
Параметры запроса:
|
Параметр |
Описание |
|
|
Идентификатор стороннего приложения |
|
|
URL, на который сервер авторизации перенаправляет пользователя после успешной авторизации. |
|
|
Запрашиваемые права стороннего приложения |
|
|
Защита от подделки |
https://id.provider.com/authorize?client_id=1xx1x111-1x11-1111-1xx1-x1xx1xx1xx1x&redirect_uri=http://example.com/callback&scope=<права стороннего приложения>&state=123
После успешного входа сервер возвращает временный код авторизации, который может быть использован только один раз — authorization code. Время жизни кода ограничено.
3 Получение access_token и refresh_token (обмен кода на токены)
Сервер стороннего приложения выполняет POST-запрос к серверу аутентификации:
curl -X POST https://id.provider.com/token \ -H "Authorization: Basic base64(client_id:client_secret)" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "code=AUTHORIZATION_CODE" \ -d "grant_type=authorization_code" \ -d "redirect_uri=https://your-app.com/callback"
Параметры запроса:
|
Параметр |
Описание |
|
|
Временный код, полученный на предыдущем шаге |
|
|
|
|
|
URL возврата (должен совпадать с указанным ранее) |
В ответе приходит json с access_token и refresh_token. Формат успешного ответа, если access_token получен:
{ "token_type": "Bearer", "user_id": "1111111ч-11x-1111-xx11-x1x111x11111", "expires_in": 3600, "expires_at": "2026-01-01T10:10:10+03:00", "access_token": "<accesstoken>", "refresh_token": "<refreshtoken>", "refresh_expires_in": 2500000, "refresh_expires_at": "2028-01-01T12:04:54+03:00"}
Параметры ответа:
|
Параметр |
Описание |
|
|
Всегда |
|
|
Уникальный идентификатор пользователя |
|
|
Время жизни |
|
|
Дата и время истечения |
|
|
Токен доступа (короткоживущий, обычно 1 час) |
|
|
Токен для обновления |
|
|
Время жизни |
|
|
Дата и время истечения |
Формат ответа при ошибке
{ "error": "invalid_grant", "error_description": "Code is expired."}
После получения access_token приложение создаёт подключение в ресурсном сервере:
curl -X POST https://account.provider.com/api/rest/create.json \ -H "Authorization: Bearer <access_token>" \ -H "Content-Type: application/json" \ -d '{}'
В случае успешного запроса, в ответе вернется app_id — идентификатор подключения.
4 Как обновить access_token
Срок жизни access_token ограничен. После истечения срока жизни токена пользователю необходимо вновь пройти авторизацию. Чтобы не проходить авторизацию заново, когда access_token истекает, его обновляют через refresh_token. refresh_token всегда выдается с access_token в одном ответе.
curl -X POST https://id.provider.com/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=refresh_token" \ -d "refresh_token=<указать полученный ранее refresh_token>" \ -d "client_id=<Идентификатор стороннего приложения >"
В результате токен обновится или появится информация об ошибке.
После получения access_token приложение создаёт подключение в ресурсном сервере с помощью запроса:
curl -X POST https://account.provider.com/api/rest/create.json \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{}'
В случае успешного запроса, в ответе вернется app_id — идентификатор подключения.
5 Токен аккаунта для фоновых процессов
После получения пользовательского access_token и refresh_token возникает вопрос: что делать, если интеграции нужно работать в фоне — без участия пользователя? В таких случаях используется токен аккаунта (account_token).
Без токена аккаунта фоновые операции привязаны к конкретному пользователю. Если пользователь выйдет из системы или его сессия истечёт — интеграция перестанет работать. Токен аккаунта привязан не к пользователю, а к аккаунту, и может работать независимо.
Пример запроса на получение access_token аккаунта
curl -X POST https://id.provider.com/token \ -H "Authorization: Basic base64(client_id:client_secret)" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=account_token" \ -d "access_token=USER_ACCESS_TOKEN" \ -d "account_client_id=111x1111-x111-x111-xx1x-111x11x111xx" \ -d "account_id=111"
Что важно учесть
-
Для фоновых операций используй токен аккаунта — он не привязан к сессии пользователя и подходит для автоматических сценариев.
-
access_tokenимеет ограниченный срок жизни — следует обновлять его заранее черезrefresh_token, чтобы избежать сбоев в работе интеграции -
Не выводить токены в логи
-
Заложить права доступа не только на сервере, но и в приложении, чтобы корректно обрабатывать ошибки
ссылка на оригинал статьи https://habr.com/ru/articles/1054840/