CorBlogкейсы · ops

Статья

Тихий SSO через Keycloak и Kerberos

SAML с формой уже работал — довёл до входа без пароля: keytab в AD, маппинг по UPN и allowlist браузера на FQDN Keycloak.

Нужен был бесшовный вход в приложение с SAML 2.0: человек жмёт Войти через SSO и не видит форму Keycloak. Базовый SAML между SP и Keycloak и LDAP User Federation уже работали. Осталось научить браузер отдать Negotiate, а Keycloak — принять ticket.

Кто что делает

Участник Роль
Приложение SP с SAML 2.0
Keycloak IdP
Active Directory KDC + каталог
Браузер Negotiate/Kerberos

Порядок, который у меня работает: AD (SPN + keytab) → Kerberos в federation и browser flow → GPO allowlist → при необходимости UPN в AD.

Пример имён:

Роль Значение
SP sp.example.com
Keycloak keycloak.example.com
AD / KDC ad.example.com
Kerberos realm EXAMPLE.COM
Service account keycloak-int
Principal HTTP/keycloak.example.com@EXAMPLE.COM

Что должно работать до Kerberos

  • SAML между SP и Keycloak уже настроен: вход через SSO с формой Keycloak работает
  • AD подключён как User Federation, пользователи находятся
  • Клиентские машины в домене, DNS и TLS Keycloak доверенны
  • Keycloak доступен по FQDN, что пойдёт в SPN

AD: учётка, SPN, keytab

Браузер просит TGS на HTTP/<FQDN-Keycloak>. Keycloak расшифровывает SPNEGO ключом из keytab. Без корректного SPN и keytab бесшовного входа нет.

Учётка службы, например keycloak-int: длинный пароль без истечения по политике, в Account включено This account supports Kerberos AES 256 bit encryption:

Учётка keycloak-int: AES 256 bit encryption
setspn -S HTTP/keycloak.example.com keycloak-int
setspn -Q HTTP/keycloak.example.com

setspn -Q должен вернуть ровно одну учётку. Дубликаты SPN — частая причина отката на NTLM и окна Windows Security. Синтаксис — HTTP/fqdn, регистр HTTP каноничный для браузерного SPNEGO.

ktpass `
  -out C:\keycloak.keytab `
  -princ HTTP/keycloak.example.com@EXAMPLE.COM `
  -mapUser keycloak-int@example.com `
  -pass "user_password" `
  -crypto AES256-SHA1 `
  -ptype KRB5_NT_PRINCIPAL

Realm в princ — UPPERCASE. ktpass фиксирует ключ учётки и часто ставит UPN service account в вид HTTP/keycloak.example.com@EXAMPLE.COM — этот UPN у keycloak-int потом не трогать, иначе keytab умрёт.

Keytab на хост Keycloak, например /opt/keycloak/keycloak.keytab, права только процессу Keycloak (chmod 440, нужный owner).

На ОС Keycloak

Установить krb5-user пакет:

apt update
apt install krb5-user

Создать и заполнить конфигурационный файл — /etc/krb5.conf:

[libdefaults]
    default_realm = EXAMPLE.COM
    dns_lookup_realm = false
    dns_lookup_kdc = true
    rdns = false
    default_tkt_enctypes = aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96
    default_tgs_enctypes = aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96
    permitted_enctypes = aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96

[realms]
    EXAMPLE.COM = {
        kdc = ad.example.com
        admin_server = ad.example.com
    }

[domain_realm]
    .example.com = EXAMPLE.COM
    example.com = EXAMPLE.COM

Проверить работу keytab до настройки UI в Keycloak:

kinit -k -t /opt/keycloak/keycloak.keytab HTTP/keycloak.example.com@EXAMPLE.COM
klist

Пример успешного ответа:

Ticket cache: FILE:/tmp/krb5cc_0
Default principal: HTTP/keycloak.example.com@EXAMPLE.COM

Valid starting       Expires              Service principal
10/13/2026 04:07:36  10/13/2026 14:07:36  krbtgt/EXAMPLE.COM@EXAMPLE.COM
        renew until 10/14/2026 04:07:35

Нужен TGT для HTTP/keycloak.example.com@EXAMPLE.COM. Если kinit падает — UI тоже не заработает: чинить SPN, AES, keytab или пароль.

Keycloak: federation и browser flow

В существующем LDAP/AD provider:

Параметр Значение
Allow Kerberos authentication On
Kerberos realm EXAMPLE.COM
Server principal HTTP/keycloak.example.com@EXAMPLE.COM
Key tab /opt/keycloak/keycloak.keytab
Kerberos principal attribute userPrincipalName

LDAP User Federation: Kerberos integration

В ticket principal вида user@EXAMPLE.COM. Keycloak ищет в LDAP значение из Kerberos principal attribute:

  • userPrincipalName = user@example.com — находит
  • sAMAccountName = user без @realm — часто не находит → форма логина при живом ticket
  • пустой UPN в AD — маппинг тоже не сработает

Authentication → Flows → browser:

Execution Requirement
Cookie Alternative
Kerberos Alternative
Identity Provider Redirector Alternative
forms → Username Password Form Alternative / Required внутри forms

Authentication → browser: Kerberos как Alternative

Порядок сверху вниз: Cookie → Kerberos → … → forms. Kerberos только Alternative: нет ticket — fallback на форму. Required вне домена сломает вход.

Клиент: GPO / реестр Chromium

Даже при живом keytab браузер по умолчанию не отдаёт доменные credentials любому сайту. Нужно в allowlist браузеров указать — FQDN Keycloak. Value data будет без https://. Это лучше раздавать через GPO → Computer Configuration → Preferences → Windows Settings → Registry → New → Registry Item.

После применения на клиенте выполнить — gpupdate /force, перезапустить браузеры и проверить:

  • Edge — edge://policy
  • Chrome — chrome://policy
  • Yandex — browser://policy

Google Chrome

Создать два Registry Item:

Computer Configuration
  Preferences
    Windows Settings
      Registry
        New → Registry Item

Первый item:

Action: Update
Hive: HKEY_LOCAL_MACHINE
Key Path: SOFTWARE\Policies\Google\Chrome
Value name: AuthNegotiateDelegateAllowlist
Value type: REG_SZ
Value data: keycloak.example.com

Второй item:

Action: Update
Hive: HKEY_LOCAL_MACHINE
Key Path: SOFTWARE\Policies\Google\Chrome
Value name: AuthServerAllowlist
Value type: REG_SZ
Value data: keycloak.example.com

Microsoft Edge

Создать два Registry Item:

Computer Configuration
  Preferences
    Windows Settings
      Registry
        New → Registry Item

Первый item:

Action: Update
Hive: HKEY_LOCAL_MACHINE
Key Path: SOFTWARE\Policies\Microsoft\Edge
Value name: AuthNegotiateDelegateAllowlist
Value type: REG_SZ
Value data: keycloak.example.com

Второй item:

Action: Update
Hive: HKEY_LOCAL_MACHINE
Key Path: SOFTWARE\Policies\Microsoft\Edge
Value name: AuthServerAllowlist
Value type: REG_SZ
Value data: keycloak.example.com

Yandex Browser

Создать два Registry Item:

Computer Configuration
  Preferences
    Windows Settings
      Registry
        New → Registry Item

Первый item:

Action: Update
Hive: HKEY_LOCAL_MACHINE
Key Path: SOFTWARE\Policies\YandexBrowser
Value name: AuthNegotiateDelegateAllowlist
Value type: REG_SZ
Value data: keycloak.example.com

Второй item:

Action: Update
Hive: HKEY_LOCAL_MACHINE
Key Path: SOFTWARE\Policies\YandexBrowser
Value name: AuthServerAllowlist
Value type: REG_SZ
Value data: keycloak.example.com

Итог

Бесшовный вход — это цепочка на стороне IdP и клиентов: один SPN и живой keytab, маппинг по userPrincipalName, Kerberos в browser flow как Alternative и allowlist браузера на FQDN Keycloak. Когда kinit -k с keytab проходит, а SSO всё ещё с формой — я сначала смотрю UPN и GPO, а не ACS.

Метод подходит любому SP с SAML 2.0. После базовой интеграции на стороне приложения обычно больше ничего не нужно: Kerberos/SPNEGO крутится на Keycloak, AD и браузере.