Двухфакторный вход в Keycloak: как работает и где ломается
Прошлые посты были про то, откуда берутся данные о пользователе (федерация с AD, Kerberos) и как они попадают в токен. Теперь про второй фактор, потому что я про этот момент в прошлых постах забыл: где он хранится, как включается и почему иногда считается включённым, но не спрашивается.
Два слоя, которые постоянно путают
Двухфакторный вход в Keycloak — это две разные вещи:
- Сценарий входа (Authentication → Flows) — порядок действий: кого спрашивать, что требовать, при каких условиях
- Учётные данные пользователя (вкладка Credentials) — сам секрет: код в приложении, ключ безопасности, сертификат
Отсюда простое правило разбора: «второй фактор не спрашивают» — виноват сценарий. «Спрашивают, но не пускают» — виноваты данные или время.
Сценарий собирается из шагов. Шаги можно менять местами и помечать: обязательный, вариант на выбор, отключён. «Вариант на выбор» — значит подойдёт любой один. «Обязательный» — значит пройти нужно все по порядку. На этом и держится вся гибкость.
Что есть «из коробки»
- Одноразовые коды по времени или по счётчику — обычное приложение-аутентификатор. Самый частый вариант
- Ключи безопасности и встроенная биометрия (WebAuth)
- Вход по клиентскому сертификату
- Коды восстановления — резервный вход
- Принудительная настройка: при следующем входе система требует настроить код
Чего нет: кодов по SMS, push-уведомлений, кодов на почту. Это всегда отдельное расширение — а значит, внешняя зависимость и новый набор возможных проблем.
Настройки кодов: то, что потом долго и сложно менять
Для всего realm задаётся: тип кода, алгоритм, число цифр, период действия, окно допуска по времени, счётчик.
Что важно понимать:
- Окно допуска — сколько соседних интервалов принимается. Ноль — строго, но человек с отстающими часами будет страдать.
- Смена настроек ломает уже выданные секреты.
- Секрет для кодов хранится в базе Keycloak и попадает в выгрузку realm, но через веб он не виден.
Не всем и не всегда
Главная конструкция — условный второй фактор: отдельный шаг с проверкой.
Условия из коробки:
- Спрашивать, только если у человека уже настроен код
- Спрашивать, только если у человека есть определённая роль
Второе и есть рабочий способ не навязывать второй фактор всем пяти тысячам сотрудников, а закрыть им админку, удалённый доступ и финансовые системы.
Комбинировать условия можно, но осторожно: вложенные шаги читаются тяжело, и через полгода уже никто не помнит, зачем там третий уровень.
Повышение требований под конкретную систему
Сценарий: обычный вход — только пароль, но при заходе в критичный сервис нужно подтверждение.
Работает так: система запрашивает нужный уровень защиты, Keycloak сверяет его с картой уровней и, если текущему входу не хватает, прогоняет дополнительный шаг.
Что нужно, чтобы заработало:
- карта уровней защиты заполнена в настройках realm
- сценарий умеет выдать нужный уровень
- система действительно запрашивает этот уровень
Ключи безопасности: надёжнее, но сложнее
Для них задаётся отдельно: домен, допустимые адреса, требования к проверке пользователя.
Три решения, которые принимают до внедрения:
- Домен фиксируется и не должен меняться. Переехали на другой адрес — все зарегистрированные ключи перестали работать
- Нужен защищённый канал (HTTPS). Локально на своей машине работает, в тестовом контуре на обычном http — нет
- Синхронизируемые ключи (passkeys) удобнее, но это уже иногда не второй фактор, а единственный.
SMS и другие каналы
Штатных кодов по SMS нет. Нужно готовое расширение или своя разработка.
Вместе с ними приходит: зависимость от внешнего шлюза, стоимость, задержки доставки, утечка номеров и отдельная история с подменой сим-карты. Для админских доступов такой канал обычно не годится.
Как сбросить
Способы не остаться без доступа:
- Коды восстановления — выдаются заранее, человек хранит их сам
- Сброс администратором — убрать код у пользователя в консоли, он настроит заново
- Второй ключ — два устройства на одного человека
Если нет ни одного из трёх, то потерянный телефон = звонок в поддержку.
Как это связано с федерацией и AD
Важное и неочевидное:
- Секрет для кодов живёт локально в Keycloak, а не в AD. Сброс пароля в каталоге второй фактор не затрагивает
- Обратное тоже верно: требования к паролям в каталоге на второй фактор не влияют никак
- Пересоздание пользователя (новый внутренний идентификатор) стирает его учётные данные. Тот же человек становится новым пользователем без кодов и без ключей
Проблемы и что с ними делать
1. Включено, но не спрашивается
Самое частое и самое опасное. Причины по убыванию частоты:
→ Отдельный клиент переопределяет сценарий своим. Один такой клиент без требования кода — и защита обойдена
→ Прямой обмен пароля на токен (без формы входа) сценарий не проходит вовсе. Мобильное приложение или скрипт получает токен без второго фактора
→ Вход через внешний источник идёт по своему сценарию первого входа. Если кода там нет, такие люди входят без второго фактора
→ Пользователь создан вручную, без требования настроить код
Что делать: проверить все входы и все сценарии, а не только основной.
2. Код верный, но не принимается
→ Часы. Код живёт по времени; расхождение больше окна — отказ. Проверить часы на телефоне, а не только на сервере
→ Настройки сменили, а секрет остался старый — нужен перевыпуск
→ Человек вводит код от другого аккаунта в том же приложении
3. «Неверные данные» сразу после настройки
→ Для кодов по счётчику: нажали «обновить» в приложении, не введя код, — счётчик разошёлся. Лечится сбросом и повторной настройкой
→ Для кодов по времени: окно допуска выставлено в ноль «для строгости»
4. Потеряно устройство
→ Заявка в поддержку
→ Сброс администратором
В общем это, наверное, пока финальный пост на эту тему.