# Авторизация и отзыв доступа

Source: <https://telegafirst.com/docs/authorization>
Locale: ru
releaseGitSha: 0bb11ef116e17ec64c802d5476eaff442e53d252
sourceContentDigest: dcc4152b7ba701a23e9af112d4bf8efc726723c9feffe12d90563ceff5ae299d
Version: 4

Выберите способ входа по субъекту, который выполняет действие. Для своего AI-агента войдите как человек через OAuth. Для серверной интеграции используйте выданный ей credential и его scopes. Покупатель входит в свой кабинет отдельной сессией; такой вход не даёт прав владельца бизнеса.

## Кто действует

| Субъект и credential | Область действия | Ограничение |
| - | - | - |
| Владелец или оператор через person OAuth (`OAuthGrant`) | Доступные этому человеку бизнесы и его текущий активный бизнес | Согласованные scopes и текущие права человека; оператор сохраняет роль оператора |
| Tenant API key (`ExternalApp`) | Бизнес интеграции и разрешённые scopes | Ключ не переключает общий активный указатель человека и не создаёт owner-полномочия |
| Headless/CI credential (`M2MCredential`) | Бизнес credential и выданные scopes | Реальный отдельный вид credential с проверкой статуса, отзыва и разрешений |
| Surface-session JWT | Контекст конкретной аутентифицированной поверхности | JWT сам по себе не доказывает право управлять бизнесом; требуется предусмотренная этой поверхностью проверка субъекта |
| Customer session | Собственные заказы, билеты и записи покупателя | Проверка tenant и принадлежности объекта покупателю; право оператора из неё не выводится |

`OAuthGrant`, `ExternalApp` и `M2MCredential` — реальные виды credential. Способ аутентификации не должен превращать человека в другого актора или давать дополнительные scopes. Сервер применяет одинаковые требования конкретной операции после разрешения credential. API key не является способом обойти отказ OAuth, тариф, readiness или live permissions.

`create_session`, `get_session_status` и `exchange_session_approval_code` относятся к сессиям входа/связывания внешней поверхности. Они не заменяют person OAuth подключения AI-клиента. Полученный surface/customer JWT нельзя использовать как доказательство полномочий владельца. Для buyer-объекта требуется customer guard; для управления tenant — собственная проверка доступного бизнеса и прав.

## Протокол Hub WS

Вместо опроса `get_session_status` можно получить исход сессии входа/связывания через WebSocket. Адрес сокета берите из поля `ws.url` ответа REST на создание сессии; там же `ws.protocol` равен `v1.sessions`. MCP-инструмент `create_session` это поле не возвращает.

**Аутентификация.** При открытии сокета передайте секрет `tgf_…` одним из двух способов: заголовком `X-Api-Key` или в `Sec-WebSocket-Protocol` значениями `v1.sessions, <ключ>` в этом порядке (сервер выбирает первое значение). Publishable-ключ `tgf_pub_` и секрет с неизвестным префиксом отвергаются. Scopes при открытии сокета не проверяются: соединение привязано к бизнесу ключа, а подписка возможна только на сессии, созданные этим же credential. Каждая подписка заново требует, чтобы этот credential был действующим и имел scope `sessions`: сокет отозванного или суженного ключа остаётся открытым, но первая же подписка закрывает его с `1008`. При отказе в аутентификации сокет сначала открывается, а затем закрывается с кодом `1008`.

**Сообщения клиента** — JSON-кадры:

* `{"action":"subscribe","sessionId":"<session_id>"}` — сервер отвечает `{"type":"subscribed","sessionId":"<session_id>"}`. Чужая, неизвестная или недоступная сессия закрывает сокет с `1008`.
* `{"action":"unsubscribe","sessionId":"<session_id>"}` — подписка снимается, ответа нет.

Любой другой кадр закрывает сокет с `1008`.

**События сервера.** Когда человек подтверждает или отклоняет вход в Telegram, подписанный сокет получает кадр `{"type":"session.approved","session_id":"<session_id>","approval_code":"<код>","user":{"seq_id":7},"timestamp":<мс>}` или `{"type":"session.denied","session_id":"<session_id>","user":null,"timestamp":<мс>}`. Это событие завершает подписку. Подписка заканчивается и с истечением срока сессии, но события об этом сервер не присылает: просроченную сессию проверяйте через `get_session_status`. `approval_code` затем обменивается через `exchange_session_approval_code`.

**Лимиты.**

| Лимит | Значение | Что происходит |
| - | - | - |
| Сокетов на один credential | 5 | шестой закрывается с `1008` |
| Сообщений клиента на сокет | 5 в секунду | сокет закрывается с `1008` |
| Размер входящего кадра | 4096 байт | сокет закрывается с `1009` |
| Простой без сообщений клиента | 30 минут | сокет закрывается с `1008` |
| Проверка живости | ping каждые 30 секунд | сокет без pong к следующей проверке обрывается без кадра закрытия |
| Подписок на сокет | 256 | лишняя подписка получает `{"type":"error","code":"subscription_limit","sessionId":"<session_id>","limit":256}`, сокет остаётся открытым |

Ping и pong не сбрасывают таймер простоя. При `subscription_limit` отпишитесь от сессий, которые больше не ждёте, и повторите подписку.

**Коды закрытия и отказы.**

| Код | Причина | Что делать |
| - | - | - |
| `1008` | Отказ аутентификации, превышен лимит, неверный кадр, чужая сессия, credential отозван или потерял scope `sessions`, простой | Исправьте причину; повтор без исправления закроется так же |
| `1009` | Входящий кадр больше 4096 байт | Отправляйте только кадры подписки |
| `1012` | Сервер перезапускается | Переподключитесь и подпишитесь заново |
| HTTP `503` при открытии | Сервер перезапускается; ответ несёт `Retry-After: 1` | Повторите подключение через указанное число секунд |

После переподключения подписки не восстанавливаются сами: отправьте `subscribe` заново. Если сессия завершилась, пока сокета не было, её исход покажет `get_session_status`.

## Подключение AI-агента человеком

1. Добавьте `https://mcp.telegafirst.com/api/v1/mcp` по [инструкции клиента](https://telegafirst.com/docs/mcp-guide). При HTTP 401 клиент читает `WWW-Authenticate` и начинает OAuth.
2. Прочитайте показанное согласие. Bundles объединяют понятные человеку группы операций, затем сервер раскрывает их в capability scopes. Само имя bundle не является отдельным полномочием.
3. Подтвердите доступ в Telegram от своего имени. Отказ не выпускает credential. В authorization-code flow клиент использует привязку к своему redirect URI, resource MCP и PKCE; произвольный код от другого клиента не подходит.
4. Обновите `tools/list` и проверьте `get_onboarding_state`. Для нового бизнеса следуйте фактическому `tools/list` и текущему `next_action`; доступные onboarding-инструменты описаны в [MCP-гайде](https://telegafirst.com/docs/mcp-guide). Продолжите [первую настройку](https://telegafirst.com/docs/getting-started#new-business).
5. Для существующего бизнеса проверьте активный slug. При доступном `list_accessible_bots` выберите бизнес из фактического списка; при необходимости используйте разрешённый `switch_active_bot` и повторно обновите `tools/list`.

Person OAuth разрешает активный бизнес через текущий выбор человека. Этот выбор общий для его подключений и чата платформенного бота. Вход оператора не делает его владельцем; наличие business в прежнем списке не доказывает, что доступ сохранился сегодня.

Успех подключения — действующий credential, ожидаемый активный бизнес и инструменты, соответствующие согласованным правам и readiness. Подтверждение входа не является подтверждением каждой денежной операции: её собственные scopes, подготовка, execution и необходимые owner-подтверждения сохраняются. [Права и ограничения](https://telegafirst.com/docs/scopes-and-permissions).

## Независимый device grant

Для диагностики без AI-клиента используйте [curl device grant](https://telegafirst.com/docs/curl-device-grant). Он регистрирует собственный public diagnostic client и получает собственную Telegram-ссылку. Не извлекайте токен или client identity из ChatGPT, Claude, Codex либо другого подключения.

Device flow запрашивает все девять существующих consent bundles. Перед подтверждением человеку показывают их права, включая customer data, формы, экспорт, записи каталога и финансовые сведения. Сервер связывает выданные scopes с показанным и принятым согласием. Отсутствующее, изменившееся, просроченное или отклонённое согласие не выдаёт grant.

Обезличенный контрактный ответ после успешного подтверждения и обмена; `<ACCESS_TOKEN>` — заглушка секрета, не готовый токен:

```json
{"access_token":"<ACCESS_TOKEN>","token_type":"Bearer","scope":"workspace-read customer-conversations-read bot-setup conversations storefront-and-marketing ai-and-knowledge access-and-integrations platform-support money-operations"}
```

Поле `scope` этого OAuth-ответа перечисляет bundles. В сохранённом grant находятся их раскрытые capability scopes; прямое сравнение этого поля с `_meta.scope` инструмента будет неправильным. В этом ответе нет `expires_in` и `refresh_token`; не переносите сюда lifecycle surface-session JWT. Device authorization code при этом имеет собственный короткий срок и polling interval, которые нужно соблюдать по ответу сервера.

Этот пример описывает форму ответа самостоятельного device-клиента и не подтверждает ручной вход в конкретном AI-хосте. Храните полученный секрет локально приватно; не вставляйте его в промпт, публичную переписку или отчёт диагностики.

## Текущие права и платное окно

Согласие задаёт верхнюю границу scopes. Исполнение учитывает актуальные полномочия владельца/участника, membership, revoke, активный бизнес, readiness, тариф, quota и resource limiter. Снятое разрешение участника не восстанавливается старым согласованным credential. Документация и прочитанная schema не дают дополнительные права.

Hub data plane открыт в активном пробном периоде (триал приравнен к AI Manager) любому credential бизнеса; при открытом платном окне любого плана, включая Starter, — личному OAuth-гранту владельца или оператора в пределах его прав; ключам интеграций (`ExternalApp`, `M2MCredential`) вне триала нужны `ai_manager`, `ai_coach` или `enterprise` **и открытое платное окно**. Бизнес без триала и без оплаченного окна (`free`), а также покупка одного topup data plane не открывают. Отсутствующая или истёкшая дата платного окна вне триала закрывает data plane. Конфигурационные операции и DX остаются доступными в пределах своих прав; их доступность не разрешает читать данные клиентов. [Точная scope-матрица](https://telegafirst.com/docs/scopes-and-permissions).

## Отзыв и ошибки входа

Владелец управляет выданными доступами в [настройках бизнеса](https://telegafirst.com/docs/business-settings). Когда owner-facing инструменты доступны, `list_connections` с `{}` возвращает подключения человека, host, последнее использование, название активного бизнеса и display `token_prefix`. Выберите нужное подключение и вызовите `revoke_connection` с `token_prefix` из этого списка. Нужны соответственно `credentials:read` и `credentials:write` и owner-session context; API key другого субъекта его не заменяет. Отзыв не требует второго owner-подтверждения. Если prefix неоднозначен, сервер отказывает с `CONFLICT`; не угадывайте target. Удаление коннектора из AI-клиента само по себе не доказывает отзыв на сервере.

После server-side revoke credential больше не аутентифицируется; старый список инструментов или сохранённая schema этого не меняют. Для восстановления доступа пройдите новый разрешённый вход. Обновление scopes требует существующего процесса согласования, а не ручного расширения данных токена.

| Отказ | Что проверить |
| - | - |
| HTTP 401 | Отсутствующий, неверный или отозванный credential и правильный endpoint; [INVALID\_API\_KEY](https://telegafirst.com/docs/errors#INVALID_API_KEY), [INVALID\_JWT](https://telegafirst.com/docs/errors#INVALID_JWT) |
| `INSUFFICIENT_SCOPE` | Нужные scopes операции, выданный и эффективный наборы, текущие permissions, план и платное окно; код не устанавливает точную причину отказа. [Ошибка](https://telegafirst.com/docs/errors#INSUFFICIENT_SCOPE) |
| `PLAN_UPGRADE_REQUIRED` | Поддерживаемый план, пробный период и открытое платное окно; [описание](https://telegafirst.com/docs/scopes-and-permissions#paid-window) |
| Device `authorization_pending` | Человек ещё не подтвердил; продолжайте polling с разрешённым interval |
| Device `slow_down` | Увеличьте polling interval на пять секунд |
| Device `access_denied` / `expired_token` | Прекратите polling; для нового входа создайте новое authorization |

Для поддержки передайте код ошибки и `traceId`, если сервер его вернул, без credentials и личных данных. [Справочник ошибок](https://telegafirst.com/docs/errors).

Тарифное ограничение data plane и отказ по живым правам различаются по тому, исправит ли их новое согласие. Если scope не был выдан credential, прямой MCP-вызов завершается до tool layer с HTTP `403` `INSUFFICIENT_SCOPE` и заголовком `WWW-Authenticate`. Если scope убран тарифным ограничением data plane (в том числе выданный раньше), вызов доходит до инструмента и возвращает ошибку инструмента `PLAN_UPGRADE_REQUIRED` без `WWW-Authenticate`; если убран живыми правами участника — `FORBIDDEN`. В REST тарифное ограничение даёт HTTP `403` `PLAN_UPGRADE_REQUIRED`, а невыданный scope — `INSUFFICIENT_SCOPE`. Повторное согласие, новый ключ, изменение permissions или замена credential не заменяют нужный план, пробный период и открытое платное окно.
