Настройка 2FA в Keycloak через Telegram-бота

Граница. Keycloak из коробки поддерживает TOTP, WebAuthn, SMS-шлюзы и email-OTP. Telegram в этом списке нет. Чтобы бот доставлял одноразовые коды, требуется собственный Authentication SPI-провайдер, JAR-артефакт и сборка дистрибутива.

Настройка 2FA в Keycloak через Telegram-бота

Лид: почему это не из коробки

Решение — неофициальное, community-уровня, с разной степенью поддержки. Это первое, что нужно зафиксировать до старта работ.

Telegram — не гарантированный канал. Доставка зависит от региона, нагрузки на Bot API и политики платформы. Для критичных контуров такой 2FA — точка отказа, а не усиление.

Кастомный код исполняется в адресном пространстве Keycloak. Уязвимость в плагине — уязвимость в аутентификации. Аудит JAR-файла обязателен.

Далее — разбор архитектуры, требований и пошаговый алгоритм развёртывания.

Архитектура: где в Keycloak живёт 2FA

Keycloak построен поверх JBoss/WildFly (до версии 17) и Quarkus (v17+). Аутентификация — набор потоков (Flows), состоящих из Execution-шагов. Каждый шаг — реализация интерфейса Authenticator. Внутренний SPI открыт для расширений: подключение нового метода равно регистрации собственного AuthenticatorFactory в виде JAR-файла, который Keycloak загружает из директории провайдеров.

Telegram-2FA в этой модели — ещё один Authenticator. На входе он получает учётные данные пользователя, на выходе проверяет одноразовый код, отправленный ботом. Логика:

1. После успешной проверки пароля Keycloak смотрит атрибут telegramId в профиле.

2. Если атрибут существует — провайдер вызывает Telegram Bot API и отправляет 6-значный OTP в личный чат с пользователем.

3. Код валидируется в течение TTL (по умолчанию 30–60 секунд).

4. При совпадении — сессия открывается.

Стандартная длина OTP — 6 цифр. Это компромисс между энтропией и удобством ввода. Более длинные коды поддерживаются спецификацией TOTP RFC 6238, но в Telegram-реализациях обычно фиксированы.

Коробочного Telegram-провайдера в Keycloak нет. Любой плагин — сторонний код с неопределённым уровнем поддержки.

Требования к инфраструктуре

Перед развёртыванием — три контрольных точки.

1. Telegram-бот. Регистрируется через @BotFather в клиенте Telegram. Команда /newbot возвращает API Token — уникальный идентификатор бота. Токен хранится в переменных окружения Keycloak, не в открытом конфиге. Формат хранения — секрет в vault (HashiCorp Vault, Kubernetes Secrets, AWS Secrets Manager), не plaintext в keycloak.conf.

2. Атрибут telegramId в профиле пользователя. Keycloak должен знать, какому chat_id отправлять сообщение. Варианты:

  • ручное добавление атрибута через админ-консоль;
  • импорт через LDAP/AD-mapper;
  • самостоятельная регистрация через кастомную тему (требует фронтенд-разработки).

Без атрибута провайдер не работает. Это деградация, не отказ — пользователь не сможет пройти 2FA.

3. Совместимость версий. Начиная с v17 Keycloak перешёл на Quarkus, и структура дистрибутива изменилась. JAR-файлы провайдеров теперь размещаются в /opt/keycloak/providers/. До v17 — /standalone/deployments/. Команда сборки дистрибутива — kc.sh build (Quarkus) вместо --auto-config (WildFly).

ПараметрKeycloak до v17 (WildFly)Keycloak v17+ (Quarkus)
Директория для JAR/standalone/deployments//opt/keycloak/providers/
Команда сборки--auto-config или standalone.shkc.sh build
Время холодного старта30–60 секунд5–15 секунд
Потребление памяти (базовое)~512 MB~256 MB
Способ конфигурацииXML + propertiesEnv vars + properties

Инструкции от 2021 года и ранее к актуальным версиям (24.x, 25.x) не применимы. Это первый источник ошибок при миграции.

Алгоритм развёртывания

Шесть шагов от нулевого состояния до работающего потока.

1. Получить токен бота через @BotFather в Telegram. Сохранить токен в защищённое хранилище.

2. Собрать или загрузить JAR-провайдер. Варианты: open-source проекты (проверить дату последнего коммита, количество открытых issues, наличие тестов) или собственная разработка на Java с использованием org.keycloak.authentication.Authenticator и org.keycloak.authentication.AuthenticatorFactory. В обоих случаях — code review. JAR загружается в доверенную среду.

3. Разместить JAR в директории провайдеров. Для Quarkus-версии: cp keycloak-telegram-authenticator.jar /opt/keycloak/providers/.

4. Пересобрать дистрибутив: ./bin/kc.sh build. Команда индексирует новые провайдеры и регистрирует их в classpath.

5. Настроить переменные окружения:

Порт для взаимодействия с Telegram Bot API — 443 (HTTPS). Самоподписанные сертификаты исключены.

6. Сконфигурировать поток аутентификации. В админ-консоли: AuthenticationFlows → дублировать стандартный Browser Flow → переименовать копию (например, Browser with Telegram 2FA) → добавить Execution шаг типа Telegram OTP с уровнем Required → привязать поток к realm.

После сохранения — рестарт Keycloak. Без рестарта новые AuthenticatorFactory не зарегистрируются.

Проверка работоспособности

Два слоя контроля.

Серверный. Лог Keycloak (/opt/keycloak/data/log/keycloak.log или stdout в контейнере). Искать строки инициализации провайдера:

Отсутствие этих строк — признак того, что JAR не подхвачен. Проверить путь, пересобрать (kc.sh build), рестартовать.

Пользовательский. Тестовый вход: ввести логин/пароль → Keycloak запрашивает OTP → в Telegram приходит сообщение с кодом → ввод кода → сессия открыта. Если код не приходит — проверить:

  • наличие атрибута telegramId у пользователя;
  • сетевую доступность до api.telegram.org:443 из контейнера Keycloak;
  • валидность токена через curl https://api.telegram.org/bot<TOKEN>/getMe;
  • отсутствие блокировки Telegram на уровне провайдера/региона.

Тестовая проверка занимает 5 минут. Пропуск этого этапа — основная причина «не работает» в логах поддержки.

Сравнение методов 2FA в Keycloak

Прежде чем вводить Telegram как второй фактор, — матрица альтернатив.

МетодУровень защитыЗависимость от внешних системСтоимостьСовместимость с Keycloak
TOTP (Google Authenticator, FreeOTP)ВысокийНетБесплатноИз коробки
WebAuthn (YubiKey, Touch ID)КриптографическийНет$20–50 за устройствоИз коробки
Email OTPСреднийSMTP-серверБесплатноИз коробки
SMS OTPНизкий (SIM-swap)SMS-шлюз$0.01–0.05 за сообщениеЧерез провайдер
Telegram OTP (кастомный SPI)СреднийTelegram Bot APIБесплатноЧерез сторонний JAR

Telegram-2FA проигрывает WebAuthn по криптографической стойкости, TOTP — по автономности, но выигрывает по UX в тех организациях, где Telegram — рабочий мессенджер. Bot API как канал доставки используется далеко за пределами ИБ: от интернет-магазинов до медиа-порталов со спортивными рассылками.

Ограничения и риски

Пять технических угроз, которые нужно учитывать до утверждения метода.

  • Отсутствие официального плагина. Red Hat не выпускает Telegram-провайдер. Все реализации — community-проекты. Поддержка ограничена issues на GitHub, SLA отсутствует. Точные лимиты Telegram API на отправку сообщений могут варьироваться в зависимости от нагрузки на бота.
  • Зависимость от Telegram. Доставка сообщений в Telegram не гарантирована. Возможны блокировки или сбои API. Регионы с ограничениями (Китай, Иран, отдельные провайдеры в РФ) — постоянный риск отказа второго фактора. Совместимость конкретных open-source плагинов с самыми последними минорными версиями Keycloak требует индивидуальной проверки.
  • Аудит стороннего кода. JAR из непроверенного источника без аудита — уязвимость нулевого дня в аутентификации. Минимум: проверка зависимостей (mvn dependency:tree), статанализ (SpotBugs, SonarQube), контрольные суммы в CI.
  • Утечка токена бота. Токен в открытом конфиге — компрометация бота. Злоумышленник получает возможность рассылать сообщения от имени сервиса. Хранение — только в vault.
  • Атрибут telegramId как атака. Если атрибут редактируется пользователем (через self-service), злоумышленник подменяет chat_id и перехватывает OTP. Решение — read-only атрибут, редактирование только администратором.
Сторонний JAR без аудита — это не «удобное расширение». Это потенциальная уязвимость в аутентификации.

Чек-лист перед выводом в продакшн

1. JAR-провайдер получен из проверенного источника, выполнен code review.

2. Токен бота хранится в vault, не в keycloak.conf.

3. Атрибут telegramId заполнен у всех пользователей потока.

4. Сетевая связность keycloak → api.telegram.org:443 подтверждена.

5. Тестовый вход выполнен с верификацией кода в Telegram.

6. Логи Keycloak содержат строки инициализации провайдера.

7. В Fallback-потоке (Browser Flow) настроен альтернативный метод 2FA на случай недоступности Telegram.

8. SLA на поддержку плагина зафиксирован: кто реагирует на CVE, кто обновляет.

Итоги

Telegram-2FA в Keycloak — рабочая, но нишевая конфигурация. Применима там, где Telegram — рабочий стандарт коммуникации, а TOTP/WebAuthn по каким-то причинам не подходят: например, при массовом онбординге сотрудников без смартфонов с приложениями-аутентификаторами.

Коробочного решения нет. Каждый этап — разработка или установка стороннего кода, аудит, контроль токенов, проверка fallback-сценариев. Без выполнения этих шагов Telegram-2FA — это не второй фактор, а иллюзия защиты.

Где Telegram-2FA не нужен — везде, где есть WebAuthn. Аппаратный ключ дешевле, безопаснее и не зависит от сторонних сервисов. Всё остальное — компромисс.

Частые вопросы

Почему нельзя использовать Telegram для 2FA в Keycloak сразу после установки?
Keycloak из коробки поддерживает только TOTP, WebAuthn, SMS-шлюзы и email-OTP. Telegram отсутствует в этом списке, поэтому для его подключения необходимо реализовать и внедрить собственный Authentication SPI-провайдер.
Где хранить токен Telegram-бота для Keycloak?
Токен бота должен храниться в защищенном хранилище (HashiCorp Vault, Kubernetes Secrets или AWS Secrets Manager). Хранение токена в открытом виде в конфигурационных файлах недопустимо.
Как Keycloak понимает, какому пользователю отправлять код в Telegram?
Провайдер использует атрибут telegramId в профиле пользователя. Если этот атрибут отсутствует, провайдер не сможет отправить сообщение, что приведет к невозможности прохождения 2FA.
Нужно ли перезапускать Keycloak после добавления JAR-файла провайдера?
Да, после размещения JAR-файла в директории провайдеров и выполнения команды сборки (например, kc.sh build для Quarkus) необходимо выполнить рестарт сервера, чтобы новые AuthenticatorFactory были зарегистрированы.
Что делать, если код из Telegram не приходит при входе?
Проверьте наличие атрибута telegramId у пользователя, сетевую доступность api.telegram.org:443 из контейнера Keycloak, валидность токена бота и отсутствие региональных блокировок Telegram.