Обзор
Cabinet поддерживает два способа авторизации через Telegram:
Оба способа работают параллельно. Когда
TELEGRAM_OIDC_ENABLED=true, Cabinet показывает кастомную кнопку с popup-авторизацией. Иначе — стандартный iframe-виджет Telegram.
Telegram OIDC (рекомендуемый)
OIDC (OpenID Connect) — стандартный протокол авторизации. Telegram реализует его черезoauth.telegram.org с поддержкой PKCE.
Официальная документация Telegram: Telegram Login — OpenID Connect
Эндпоинты протокола
Шаг 1: Регистрация приложения в BotFather
- Откройте Mini App @BotFather
- Выберите вашего бота
- Перейдите в Bot Settings → Web Login
- Зарегистрируйте Allowed URLs — укажите все домены, с которых будет выполняться авторизация:
- Origin кабинета:
https://cabinet.example.com - Redirect URI (если используете Authorization Code Flow напрямую):
https://cabinet.example.com/auth/telegram/callback
- Origin кабинета:
- BotFather отобразит Client ID и Client Secret — сохраните их
Client ID — это числовой ID вашего бота (тот же, что в
BOT_TOKEN до двоеточия). Например, для токена 1234567890:AABBCCdd... Client ID = 1234567890.Шаг 2: Настройка .env бота
Доступные scopes
Cabinet запрашивает scopes
openid и profile. Scope phone не используется.
Структура id_token
После авторизации Telegram возвращает JWTid_token с подписью RS256. Пример декодированного токена:
Как работает (пошагово)
- Пользователь открывает страницу входа Cabinet
- Frontend запрашивает конфигурацию виджета с API бота (публичный эндпоинт, без авторизации)
- Если
oidc_enabled=true— загружается JavaScript SDK Telegram (telegram-login.js?3) - SDK инициализируется с
client_idи callback-функцией: - Пользователь нажимает кнопку «Войти через Telegram»
- SDK открывает popup-окно авторизации на
oauth.telegram.org - Пользователь видит имя и аватар бота, подтверждает вход
- Popup закрывается, SDK вызывает callback с
{id_token: "eyJ…"}или{error: "..."} - Frontend отправляет
id_tokenна API бота - Бот загружает публичные ключи JWKS (кэшируются на 1 час)
- Бот валидирует JWT-подпись и claims
- Бот создаёт/находит пользователя, возвращает JWT-токены Cabinet
- Пользователь авторизован и перенаправляется на главную страницу
JavaScript SDK
Cabinet использует Telegram Login SDK. Доступные методы:
Параметры инициализации (InitOptions):
Структура callback:
Валидация id_token на сервере
Бот выполняет следующие проверки при полученииid_token:
- Подпись — загружает публичные ключи JWKS, находит ключ по
kidиз заголовка JWT, проверяет подпись RS256 - Издатель —
issдолжен бытьhttps://oauth.telegram.org - Аудитория —
audдолжен совпадать сTELEGRAM_OIDC_CLIENT_ID - Срок действия —
expне должен быть в прошлом - Обязательные claims — проверяется наличие
exp,iat,iss,aud,sub - Replay-защита — каждый
id_tokenможет быть использован только один раз (хэш хранится до 10 минут)
Ротация ключей (JWKS)
Telegram может ротировать ключи подписи. Бот автоматически обновляет JWKS-кэш:Rate Limiting
ЭндпоинтPOST /cabinet/auth/telegram/oidc защищён rate limiter:
- 10 запросов в 60 секунд на один IP-адрес
- При превышении — HTTP 429 с заголовком
Retry-After - Режим fail-closed: при ошибке rate limiter запросы отклоняются
Создание и привязка аккаунтов
При авторизации через OIDC:- Существующий пользователь (по Telegram ID) — выполняется вход, обновляются поля
first_name,username,last_nameиз актуальных claims - Новый пользователь — создаётся аккаунт с данными из claims. Если передан
referral_codeилиcampaign_slug— применяются соответствующие бонусы - Неактивный аккаунт — авторизация отклоняется с HTTP 403
Совместимость с другими OIDC-системами
Telegram OIDC совместим со стандартными OIDC-провайдерами и может использоваться с:- Keycloak — как внешний Identity Provider
- Authentik — через Generic OIDC
- Auth0 — через Custom Social Connection
Telegram не предоставляет отдельный UserInfo endpoint. Все claims содержатся в
id_token. Некоторые OIDC-библиотеки могут требовать настройки для пропуска запроса UserInfo.Telegram Widget (legacy)
Стандартный iframe-виджет Telegram. Используется, когда OIDC отключен (TELEGRAM_OIDC_ENABLED=false).
Настройка домена в BotFather
- Откройте @BotFather в Telegram
- Выберите вашего бота
- Bot Settings → Domain → укажите домен кабинета (например,
cabinet.example.com)
Кастомизация виджета
Внешний вид виджета настраивается через переменные окружения или через Admin Cabinet → Настройки:Настройки виджета можно менять без перезапуска бота через Admin Cabinet → Настройки. Значения из базы данных имеют приоритет над переменными окружения.
Как работает
- Cabinet загружает iframe-виджет Telegram Login на странице входа
- Пользователь нажимает кнопку и подтверждает вход в Telegram
- Telegram возвращает данные пользователя (id, first_name, auth_date, hash) с HMAC-SHA256 подписью
- Cabinet отправляет данные на API бота
- Бот проверяет подпись через
SHA256(BOT_TOKEN)и валидируетauth_date(не старше 24 часов) - Бот возвращает JWT-токены для авторизованной сессии
OIDC vs Widget — сравнение
Конфигурационный API
GET /cabinet/branding/telegram-widget
Публичный эндпоинт (без авторизации). Возвращает конфигурацию для страницы входа. Ответ:
Frontend использует
oidc_enabled и oidc_client_id чтобы выбрать способ авторизации: OIDC popup или legacy widget.
POST /cabinet/auth/telegram/oidc
Валидация id_token и авторизация пользователя. Запрос:
Ответ (200):
Итоговая настройка .env
Пример с виджетом и OIDC:Проверка
API: проверка конфигурации
oidc_enabled: true и oidc_client_id с ID бота.
Widget (если OIDC выключен)
- Откройте Cabinet в браузере
- На экране входа должна появиться iframe-кнопка Telegram
- Нажмите — откроется авторизация Telegram
- После подтверждения — вход в Cabinet
OIDC (если включен)
- На странице входа отображается кастомная кнопка «Войти через Telegram»
- При нажатии откроется popup-окно авторизации
- После подтверждения popup закроется и пользователь авторизован
Устранение проблем
Кнопка «Войти через Telegram» не появляется
- Проверьте конфигурацию:
curl -s https://hooks.example.com/cabinet/branding/telegram-widget | jq - Если
oidc_enabled: false:- Проверьте
TELEGRAM_OIDC_ENABLED=trueв.env - Проверьте что
TELEGRAM_OIDC_CLIENT_IDзаполнен - Перезапустите бота
- Проверьте
- Если OIDC выключен, но виджет тоже не появляется:
- Домен кабинета добавлен в BotFather → Bot Settings → Domain?
VITE_TELEGRAM_BOT_USERNAMEуказан верно (без@)?- Страница загружается по HTTPS?
Popup открывается, но сразу закрывается
- URL кабинета зарегистрирован в BotFather → Bot Settings → Web Login → Allowed URLs?
- Убедитесь что домен в
CABINET_URLсовпадает с зарегистрированным
”Telegram OIDC is not configured” (400)
TELEGRAM_OIDC_ENABLED=trueв.env?TELEGRAM_OIDC_CLIENT_IDне пустой?- Перезапустили бота после изменений?
”Invalid or expired Telegram OIDC token” (401)
“Unknown kid in id_token” в логах
Telegram ротировал ключи подписи. Бот автоматически обновит JWKS. Если ошибка повторяется:- Проверьте доступность
https://oauth.telegram.org/.well-known/jwks.jsonс вашего сервера: - Убедитесь что нет блокировки исходящих HTTPS-запросов к
oauth.telegram.org - Проверьте DNS-резолвинг:
Rate limit (429)
Эндпоинт OIDC ограничен 10 запросами в 60 секунд на IP. Это защита от брутфорса. В нормальной работе лимит не должен срабатывать. Если срабатывает в production:- Проверьте что reverse proxy передаёт реальный IP пользователя (заголовок
X-Forwarded-For) - Без этого все запросы идут с IP прокси и быстро исчерпывают лимит
