---
title: "Подключение через OAuth"
description: "Авторизуйте MCP-клиенты и CLI ThunderPhone без передачи API-ключа."
---

OAuth позволяет приложению подключаться к одной организации ThunderPhone с одобренными вами разрешениями. Клиенты каталогов должны использовать OAuth по умолчанию. API-ключи организации по-прежнему доступны для клиентов, которым требуется вручную настроенный токен Bearer.

## Одобрите подключение

Начните подключение в вашем MCP-клиенте. Войдите в ThunderPhone, проверьте название приложения и запрошенные разрешения, выберите организацию и нажмите **Одобрить**. Нажмите **Отклонить**, если вы не начинали подключение или не доверяете приложению. Названия приложений предоставляются их разработчиками и не являются подтверждением проверки.

Разрешения на чтение предоставляют доступ к указанным данным, включая записи и расшифровки, если запрошено `calls:read`. Разрешения на запись могут изменять или удалять ресурсы; звонки, кампании, покупка номеров и развёртывания могут приводить к расходам или влиять на продакшен. Ваша роль в организации по-прежнему применяется.

Для подключения через CLI откройте ссылку для проверки, показанную в терминале, сравните восьмизначный код, выберите организацию и одобрите подключение. Простое открытие ссылки не предоставляет доступ. Срок действия кодов истекает через 15 минут.

## Отключите приложение

Откройте **Организация → API-ключи → Авторизованные приложения** в панели управления и выберите **Отозвать**. Это отзовёт выбранную вами авторизацию для текущей организации, включая её токены доступа и обновления. Если хотите снова авторизовать приложение, повторно подключитесь из него.

## Обнаружение для MCP-клиентов

Используйте URL сервера `https://api.thunderphone.com/v1/mcp`. Запрос без действительной аутентификации получает `401` с:

```http
WWW-Authenticate: Bearer resource_metadata="https://api.thunderphone.com/.well-known/oauth-protected-resource"
```

Получите этот документ, затем получите метаданные сервера авторизации по адресу `https://api.thunderphone.com/.well-known/oauth-authorization-server`. Метаданные ресурса также доступны по адресу `/.well-known/oauth-protected-resource/v1/mcp`. Используйте возвращённые конечные точки вместо их формирования вручную. Идентификатор ресурса: `https://api.thunderphone.com/v1/mcp`.

Сервер поддерживает код авторизации с **S256 PKCE**, сменяемые токены обновления, публичную динамическую регистрацию клиентов, отзыв и предоставление авторизации для устройств. Секреты клиентов и неявные предоставления не поддерживаются. Обнаружение OpenID также доступно по адресу `/.well-known/openid-configuration`; оно включает те же поля сервера авторизации, а также `subject_types_supported: ["public"]` и конечную точку userinfo. ID-токены и документы метаданных Client ID (CIMD) не поддерживаются.

### Зарегистрируйте публичный клиент

Отправьте JSON в `POST /v1/oauth/register`:

```json
{
  "client_name": "My MCP client",
  "redirect_uris": ["http://127.0.0.1:8765/callback"],
  "token_endpoint_auth_method": "none",
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"]
}
```

Сохраните возвращённый `client_id`. Перенаправления должны использовать HTTPS либо HTTP на `127.0.0.1` или `localhost`. Зарегистрируйте точный URI обратного вызова, включая порт и путь. Фрагменты и встроенные учётные данные отклоняются. Необязательные `client_uri` и `logo_uri` должны использовать HTTPS; ThunderPhone не получает их во время регистрации. Для регистрации действует ограничение частоты запросов. Зарегистрированные клиенты не истекают и остаются зарегистрированными при отзыве подключения. HTTPS-обратные вызовы включают `https://chatgpt.com/connector/oauth/<id>` и `https://chatgpt.com/connector_platform_oauth_redirect`. Каждое подключение может зарегистрировать собственного клиента.

### Код авторизации

Откройте обнаруженную конечную точку авторизации с `client_id`, точным зарегистрированным `redirect_uri`, `response_type=code`, случайным `state`, `scope`, `code_challenge`, `code_challenge_method=S256` и `resource=https://api.thunderphone.com/v1/mcp`. Вычислите challenge как SHA-256-дайджест нового высокоэнтропийного PKCE-верификатора в формате base64url без заполнения. Проверьте возвращённые `state` и `iss` перед обменом кода. Каждый ответ авторизации, включая отказ и ошибки протокола, указывает издателя через `iss`, в точности совпадающего с обнаруженным `issuer`. Ошибки недействительного клиента или обратного вызова возвращаются локально без перенаправления на этот обратный вызов.

Выполните обмен через `POST /v1/oauth/token`, используя кодирование формы (JSON также принимается):

```text
grant_type=authorization_code
client_id=<your client id>
code=<single-use authorization code>
redirect_uri=<exact registered redirect URI>
code_verifier=<original PKCE verifier>
resource=https://api.thunderphone.com/v1/mcp
```

Необязательный параметр `resource` принимается как в запросах авторизации, так и в запросах токенов, включая обмены обновления и устройства. Если он не указан, по умолчанию используется обнаруженный MCP-ресурс. Если он указан, то должен в точности совпадать с этим ресурсом; другие значения возвращают `invalid_target`. Токены доступа содержат эту аудиторию, а MCP отклоняет токены с отсутствующей или другой аудиторией с кодом `401` и запросом обнаружения.

Запросы авторизации и коды истекают через 10 минут. Каждый ответ с токеном содержит `access_token`, `token_type` (`Bearer`), `expires_in` (по умолчанию 3600 секунд), `refresh_token`, `scope`, `organization_id` и `organization_name`. Передавайте токены доступа только через заголовок `Authorization: Bearer`. Никогда не помещайте токены в URL-адреса, журналы, системы контроля версий или чаты.

### Обновление и отзыв

Обновляйте токен с `grant_type=refresh_token`, `client_id`, `refresh_token` и `resource` на конечной точке токенов. Атомарно сохраните новый токен обновления и прекратите использовать старый. Токены обновления истекают через 30 дней без успешного обновления. Необязательный `scope` может сузить предоставленные разрешения. `offline_access` всегда включён, а токены обновления всегда выдаются. Первоначальный запрос без `scope` предоставляет только `offline_access`, поэтому клиентам следует запрашивать необходимые разрешения.

Повторное использование кода и сменяемого токена обновления отзывает всю авторизацию. Сериализуйте обновления внутри клиента; повторное воспроизведение успешно обменённых учётных данных не является безопасной стратегией повтора.

Чтобы отключиться, отправьте `token` и `client_id` в `POST /v1/oauth/revoke`. Отзыв любого токена отзывает его авторизацию, включая все выданные из него токены. Неизвестный токен возвращает успех, не раскрывая, существует ли он. Сеансы панели управления могут перечислять собственные авторизации через `GET /v1/oauth/grants` и отзывать одну через `DELETE /v1/oauth/grants/<id>`, при этом `X-ThunderPhone-Org` выбирает организацию.

### Авторизация устройства

Авторизация устройства ограничена предварительно зарегистрированными клиентами; динамически зарегистрированные клиенты получают `unauthorized_client`. Предварительно зарегистрированный публичный клиент `thunderphone-cli` поддерживает авторизацию устройства и обновление. Отправьте `client_id=thunderphone-cli` и `scope` в `POST /v1/oauth/device/code`. Покажите пользователю `user_code` и `verification_uri` либо откройте `verification_uri_complete`.

Опрашивайте конечную точку токенов с `grant_type=urn:ietf:params:oauth:grant-type:device_code`, `client_id` и `device_code`, ожидая не менее возвращённого `interval` (5 секунд). Продолжайте при `authorization_pending`. При `slow_down` используйте новый `interval`, возвращённый в ответе (увеличенный на 5 секунд), для каждого последующего запроса. Остановитесь при `access_denied`, `expired_token` или любой другой ошибке. Никогда не подтверждайте код устройства автоматически.

Предварительно зарегистрированный клиент `thunderphone-mcp` принимает `http://127.0.0.1/callback` и `http://localhost/callback` на любом порту. Схема, хост, путь и запрос должны совпадать; обмен токена должен использовать точный URI перенаправления, включая порт, из авторизации. Динамически зарегистрированные клиенты требуют точного совпадения URI перенаправления, включая порт. Динамически зарегистрируйте другой обратный вызов, если нужен другой путь.

### Проверки идентификации аккаунта и домена рабочего пространства

Запрашивайте оба `openid email` вместе с областями операций, необходимыми вашему клиенту. Вызовите обнаруженный `userinfo_endpoint` (`GET /v1/oauth/userinfo`) с токеном доступа в заголовке Bearer. Успешный ответ содержит:

```json
{
  "sub": "123",
  "email": "person@example.com",
  "email_verified": true,
  "name": "Example User",
  "org_id": 456
}
```

`sub` — стабильный идентификатор пользователя; `org_id` — организация, выбранная во время согласия. Конечная точка требует обе области идентификации и возвращает `403`, если отсутствует любая из них. Она возвращает `403` с `error=access_denied`, если у аккаунта нет профиля с подтверждённым email, вместо утверждения, что неподтверждённому email можно доверять. Недействительные, истёкшие, отозванные токены или токены с неверной аудиторией возвращают `401`. Токены пользовательских сеансов и ключи API организации не могут вызывать userinfo. ID-токен не выдаётся.

## Доступные разрешения

| Категория | Области доступа |
| --- | --- |
| Агенты и импорт агентов | `agents:read`, `agents:write` |
| Звонки | `calls:read`, `calls:write` |
| Номера телефонов, заблокированные звонящие и VoIP | `numbers:read`, `numbers:write` |
| База знаний | `knowledge:read`, `knowledge:write` |
| Кампании | `campaigns:read`, `campaigns:write` |
| Интеграции, конечные точки вебхуков, серверы MCP | `integrations:read`, `integrations:write` |
| Голоса | `voices:read` |
| Тестовые сценарии, тестовые запуски, валидация | `testing:read`, `testing:write` |
| Выставление счетов | `billing:read` |
| Идентификация аккаунта и подтверждённый email | `openid`, `email` (оба обязательны для userinfo) |
| Постоянное подключение | `offline_access` (всегда включено) |

GET, HEAD и OPTIONS используют области доступа для чтения; остальные методы используют области доступа для записи. Изменения голосов и данных выставления счетов недоступны через OAuth; `POST /v1/voices/preview` использует `voices:read`, поскольку позволяет прослушать голос без изменения его конфигурации. Инструменты MCP применяют область доступа базовой операции REST. Передача данных между организациями запрещена, даже если пользователь, предоставляющий авторизацию, состоит в обеих организациях. Другие категории API, включая управление API-ключами и настройки учётной записи пользователя, недоступны через OAuth. При отсутствии разрешения для операции REST возвращается `403` с `WWW-Authenticate: Bearer error="insufficient_scope", scope="..."`. Недействительные или истёкшие токены доступа возвращают `401`.


### Сигналы аутентификации инструментов MCP

Каждый инструмент в `tools/list` включает `securitySchemes: [{"type": "oauth2", "scopes": ["agents:read"]}]` с областью доступа операции REST этого инструмента. Публичные инструменты документации используют пустой список областей доступа и по-прежнему требуют аутентифицированного подключения.

Для действительного токена без области доступа инструмента возвращается HTTP `200` с JSON-RPC `result`, содержащим `isError: true`, пояснительный текст в `content` и `_meta["mcp/www_authenticate"]`. Последний представляет собой массив с запросом Bearer, содержащим `resource_metadata`, `error="insufficient_scope"`, `error_description` и необходимую область доступа `scope`. Инструмент не выполняется. Используйте этот запрос, чтобы запросить расширенное согласие. При отсутствии или недействительности аутентификации по-прежнему возвращается HTTP `401` с `WWW-Authenticate`; при ошибках области доступа REST по-прежнему возвращается HTTP `403`.

## Хранение учётных данных

API запускает `python manage.py oauth_cleanup` каждый час в стейджинге и продакшене. Команда удаляет истёкшие запросы авторизации и коды устройств. Истёкшие токены доступа, коды авторизации и хеши токенов обновления удаляются только после отзыва их гранта или после того, как всё семейство становится неактивным. Использованные хеши сохраняются, пока в семействе есть действующий токен обновления, код авторизации, одобренный код устройства или токен доступа, поэтому очистка не может отключить обнаружение повторного воспроизведения.
