Александр Есин / блог

Федерация в Keycloak с AD: как это устроено внутри

25 октября 2026

Прошлый пост был про то, что попадает в токен. Этот — про то, откуда данные берутся до этого, и что происходит в момент логина. Потому что федерация — не «настроил и забыл», а конвейер из пяти стадий, и ломается он всегда на одной из них.

Две модели, которые постоянно путают

Прежде чем разбирать поток нужно развести два разных механизма:

  • User Federation — AD выступает источником пользователей. Идентичность создаётся там, Keycloak её подтягивает: аутентификация идёт по паролю источника, атрибуты читаются оттуда.
  • Identity Brokering — AD выступает внешним провайдером входа. Keycloak не видит пароль вообще, получает assertion/токен и на его основе заводит или связывает локального пользователя.

Разница принципиальная: в первом случае Keycloak знает секрет (или проверяет его через bind), во втором — доверяет подписи и заявлению. Все дальнейшие вопросы «почему нет атрибута» и «почему не обновилось» решаются в разных местах в зависимости от того, какой из двух механизмов у нас применяется.

Что происходит в момент логина (User Federation)

Пошагово:

  1. Пользователь вводит логин. Keycloak ищет его в кэше провайдера.
  2. Промах кэша → lookup в AD по настроенному атрибуту (username, sAMAccountName, UPN, mail — что выбрано при создании провайдера).
  3. Найден → проверка пароля: bind сервисной учёткой, затем bind от имени пользователя. Пароль в Keycloak не сохраняется, он уходит в источник.
  4. Успех → атрибуты прогоняются через mappers и складываются в локальную модель пользователя (в зависимости от Edit Mode).
  5. Только теперь в игру вступают client scopes и protocol mappers из второго моего поста про Keycloak: они берут уже готовую модель и формируют токен.

Стадии 1–4 — это федерация, стадия 5 — выдача. Пустой claim почти всегда означает, что сломалась одна из первых четырёх, а не пятая.

Три режима, определяющие актуальность данных

  • Imported — данные копируются в БД Keycloak при первом входе и живут там. Быстро, но между синхронизациями — устаревшие.
  • Always read from source — атрибуты читаются при каждом обращении. Всегда свежие, но есть задержка при опросе самой AD, зависимость от доступности AD в момент логина — жёсткая.
  • Write-back — изменения из Keycloak уезжают в AD. Требует прав на запись и аккуратности.

Выбор режима — это не техническая мелочь, а решение о том, где истина. Если отдел меняют в AD, а Keycloak держит копию — кто-то обязательно увидит старую должность в токене и придёт с вопросом.

Синхронизация: что и когда подтягивается

  • Полная — обходит всех пользователей источника. Долго, нагружает каталог, нужна для первичного наполнения и после больших изменений.
  • Инкрементальная — по метке изменения в источнике. Быстрее, но членство в группах и некоторые атрибуты подхватываются не так охотно, как хотелось бы.
  • On-demand — при первом входе конкретного пользователя.
  • Событийная — источник сам сообщает об изменениях. Самое свежее и самое хрупкое: ломается тихо.

Синхронизация обновляет модель пользователя. Она НЕ отзывает выданные токены. Старый access token живёт до истечения, refresh — до своего срока.

Маппинг: где чаще всего рассыпается цепочка

Данные идут в два прыжка:

  1. Mapper федерации: атрибут AD → атрибут модели Keycloak
  2. Protocol mapper в client scope: атрибут модели Keycloak → claim в токене

Правило, снимающее половину инцидентов: нет значения в модели — бесполезно крутить protocol mapper; значение в модели есть, но mapper не привязан к нужному scope — в токене ничего не появится.

Имя атрибута на обоих прыжках должно совпадать посимвольно.

Проблемы и как с ними бороться

1. Пользователь не находится при логине

→ Проверить атрибут поиска и его уникальность: искать по mail — плохая идея, у людей бывает несколько адресов и дубли. Логин должен быть однозначным.

→ Проверить фильтр поиска: слишком узкий — часть пользователей не видна.

→ Проверить, что сервисная учётка реально видит нужную OU.

2. Логин работает, атрибуты пустые

→ Смотреть модель пользователя, а не токен. Если там пусто — виноват mapper федерации, режим чтения или права учётки. Если там есть — идти в client scope.

3. Атрибут изменился в AD, а в Keycloak старый

→ Проверить режим: копия или чтение из источника.

→ Прогнать синхронизацию и убедиться, что она вообще отработала, а не завершилась с ошибкой в логах.

→ Пользователю всё равно нужен перелогин, старый токен не обновится сам.

4. Вложенность групп не видна

→ Источник отдаёт только прямые членства. Либо рекурсивный запрос в фильтре группы, либо разворачивать иерархию, либо не строить авторизацию на глубокой вложенности.

5. Дубли пользователей

→ Внешний идентификатор должен быть стабильным и неизменным. Пересоздание провайдера или смена атрибута-идентификатора — и вы получаете дубликат юзера с другим внутренним ID. Лечится только разбором и склейкой вручную.

6. Лимит выдачи при полной синхронизации

→ Источник по умолчанию отдаёт ограниченное число записей за раз. Включить пажинацию — для крупных каталогов это обязательный пункт.

7. Федерация падает целиком

→ Истёк пароль сервисной учётки, отвалился TLS, сеть до источника — и логина нет ни у кого, включая админов. Единая точка отказа.

→ Отдельная read-only учётка с ротацией пароля, шифрованный канал, таймауты, пул соединений, алерт на сам факт коннекта — не на количество ошибок, а на отсутствие успешных проверок.

→ Держать локального аварийного администратора, который не зависит от федерации.

8. Несколько источников, одинаковые логины

→ Два провайдера с пересекающимися username дают неоднозначность. Либо различать логины суффиксом, либо явно разделять пространства имён, либо не заводить второй провайдер без реальной необходимости.

9. Медленный логин

→ Частая причина — чтение из источника на каждый запрос плюс кэш, выставленный в ноль. Ищем баланс: короткий TTL кэша обычно приемлем, а вот полный отказ от кэша кладёт каталог под нагрузкой.

10. Синхронизация есть, а поведение не меняется

→ Кэш. Пользовательский кэш, кэш провайдера, кэш сессий — три разных слоя, и после правок групп/ролей чистить надо все три. Плюс реальный токен: декодировать и посмотреть, а не верить настройкам.

По теме можно еще очень много писать, есть куча дополнительных подводных камней, но пока на этом закончу, так как всю базу, в основном, расписал.