В интеграциях с внешними приложениями часто используется протокол OAuth 2.0. В этой статье разбирается практический сценарий: получение access_token, обновление токена, работа с ошибками и использование токена аккаунта для фоновых операций. Статья будет полезна системным аналитикам и backend-разработчикам, которые проектируют интеграции с внешними API, используют OAuth 2.0 и хотят разобраться в практических сценариях — включая фоновые операции. Читать далее
В интеграциях с внешними приложениями часто используется протокол OAuth 2.0. Он позволяет приложению получить доступ к данным пользователя без передачи пароля. В этой статье разбирается практический сценарий: получение access_token, обновление токена, работа с ошибками и использование токена аккаунта для фоновых операций.
Подробная диаграмма последовательности процесса авторизации.

Диаграмма процесса авторизации по OAuth 2.0
Далее описан алгоритм авторизации по протоколу OAuth 2.0.
1 Инициация - получение параметров аккаунтаПользователь переходит из страницы настройки интеграции в стороннее приложение. В URL передаются параметры аккаунта: account_id и account_name
https://%domain%.ru/api/oauth2/auth?account\_id=<идентификатор аккаунта>&account_name=<наименование аккаунта>Стороннее приложение сохраняет account_id (идентификатор аккаунта) и account_name(наименование аккаунта). Они потребуются при создании подключения и получении токена аккаунта.
Приложение перенаправляет пользователя на сервер аутентификации для получения кода авторизации — 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. Время жизни кода ограничено.
Сервер стороннего приложения выполняет 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 — идентификатор подключения.
Срок жизни 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 — идентификатор подключения.
После получения пользовательского 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, чтобы избежать сбоев в работе интеграции
Не выводить токены в логи
Заложить права доступа не только на сервере, но и в приложении, чтобы корректно обрабатывать ошибки
| # | Наименование новости | Тональность | Информативность | Дата публикации |
|---|---|---|---|---|
| 1 | Оптимизация без AI: как я автоматизировал API-ручки и типы | -2 | 5 | 29-06-2026 |
| 2 | Микрофронтенды. Стабильная интеграция нескольких SPA-приложений. Часть 1 | 0 | 5 | 29-06-2026 |
| 3 | Микрофронтенды. Стабильная интеграция нескольких SPA-приложений. Часть 2 | 0 | 5 | 30-06-2026 |
| 4 | DTO, schema, model, entity: почему в коде всё называется User | 0 | 7 | 01-07-2026 |
| 5 | Настройка AI-агентов для ускорения бизнес процессов компании | 0 | 7 | 03-07-2026 |
| 6 | Как считать экономическую эффективность внедрения ИТ-решений. Переводим функционал в деньги | 3 | 7 | 09-07-2026 |
| 7 | Полный гайд по JavaScript-коду отслеживания в Matomo. Часть 1 | 0 | 7 | 08-07-2026 |
| 8 | Как я научил Claude заказывать продукты в Яндекс Лавке (и что для этого пришлось отреверсить) | 0 | 10.18 | 22-07-2026 |
| 9 | Как я навайбкодил каталог бесплатных парковок Петербурга и России | 5 | 7 | 07-07-2026 |
| 10 | Baseline: май 2026 | 0 | 5 | 29-06-2026 |