Перейти к основному содержимому

ADFS: вход по почте и руководитель из каталога

Актуально для: SimpleTwo 0.9.x · Проверено: 20.09.2026

ADFS подключается как обычный провайдер OIDC — см. Вход по корпоративной учётной записи. Эта статья про два случая, которые встречаются почти в каждом внедрении и решаются на стороне ADFS, а не в SimpleTwo.

1. Вход по почтовому адресу (Alternate Login ID)

Симптом. Клиент нашёл нужный контур, пароль верный, а вход отвечает «неверные учётные данные». В журнале координатора — sso.password_reject.

Причина. SimpleTwo отправляет в ADFS ровно ту строку, которую человек ввёл, а ADFS по умолчанию сверяет её с userPrincipalName. Сотрудник с UPN ivan@corp.local и почтой ivan@example.com не будет найден.

Решение. Alternate Login ID (ALI) заставляет ADFS искать введённое значение в атрибуте каталога, а не в UPN. В SimpleTwo при этом менять нечего.

ALI действует на весь лес, а не на одно приложение

Настройка меняет разбор идентификатора для всех входов через этот ADFS. Делайте это в согласованное окно и сначала проверьте каталог.

Шаг 1. Найти дубликаты. Если одно значение встречается у двух учётных записей, ADFS не сможет выбрать — и перестанут входить оба:

Get-ADUser -Filter * -Properties mail |
Where-Object { $_.mail } |
Group-Object mail | Where-Object Count -gt 1 |
Select-Object Name, Count

Для многозначного proxyAddresses проверка обязательна отдельно: там чаще всего лежат остатки старых миграций.

Шаг 2. Выбрать атрибут.

АтрибутКогдаОговорка
mailлюди вводят основной почтовый адресоднозначный, самый простой
proxyAddressesу людей несколько адресов, и ввести могут любоймногозначный; значения хранятся с префиксом (smtp:ivan@example.com), а человек вводит адрес без префикса

Сотрудник с пустым атрибутом после включения ALI входит по-прежнему по UPN — этот путь продолжает работать.

Шаг 3. Включить. На сервере ADFS:

Set-AdfsClaimsProviderTrust -TargetIdentifier "AD AUTHORITY" `
-AlternateLoginID mail `
-LookupForests corp.local

Откат — пустые значения:

Set-AdfsClaimsProviderTrust -TargetIdentifier "AD AUTHORITY" -AlternateLoginID "" -LookupForests ""

Шаг 4 — тот, который обычно пропускают. Проверьте именно ту точку входа, которой пользуется SimpleTwo: приложение входит не через браузерную форму, а через password grant, и ALI исторически применялся к разным точкам ADFS неодинаково.

curl -s -X POST "https://adfs.example.com/adfs/oauth2/token" \
-d grant_type=password \
-d client_id="<Client ID из Settings → SSO>" \
-d username="ivan@example.com" \
-d password="<пароль>" \
-d scope="openid" | head -c 400
ОтветЧто это значит
есть access_token / id_tokenALI работает на нужной точке, в SimpleTwo менять нечего
"error":"invalid_grant" с кодом вида MSIS9659идентификатор не разрешён: проверьте значение атрибута у этой учётной записи и список лесов
с UPN работает, с почтой — нетALI не действует на эту точку входа

Прогоните дважды: с почтовым адресом и с UPN. Коллеги с основного домена продолжают вводить UPN, и он обязан работать.

Шаг 5. Внесите домен в Settings → SSO → домены организации. Именно этот список превращает «неверные учётные данные» в понятное «этот домен здесь не обслуживается» и позволяет клиенту вообще найти ваш координатор по адресу почты.

Password grant проходит мимо MFA и conditional access

Это свойство самого ROPC, а не ALI. Если у вас обязательная многофакторная проверка, знайте, что вход из приложения её не увидит. Переход клиента на authorization code flow, при котором человек вводит логин на странице ADFS (и ALI перестаёт быть нужен), запланирован.

2. Руководитель: два claim'а вместо преобразования в ADFS

В Active Directory атрибут manager хранит DN (CN=Пётр Смирнов,OU=Users,DC=corp,DC=example,DC=com), а не адрес. Раньше от ADFS требовали сходить в каталог второй раз и превратить DN в почту; сейчас этого не нужно и не поддерживается: адрес в этом поле ни с кем не сопоставляется и пишется в аудит.

SimpleTwo соединяет людей сам: DN руководителя из одной учётной записи совпадает с DN сотрудника в другой. Поэтому от ADFS нужны два обычных LDAP-атрибута.

Шаг 1. Зарегистрировать описания claim'ов. Без короткого имени claim вычислится, но в OIDC-токен не попадёт — выглядит это неотличимо от несработавшего правила:

Add-AdfsClaimDescription -Name "UserDN" `
-ClaimType "http://schemas.xmlsoap.org/claims/UserDistinguishedName" `
-ShortName "user_dn" -IsAccepted $true -IsOffered $true -IsRequired $false

Add-AdfsClaimDescription -Name "ManagerDN" `
-ClaimType "http://schemas.xmlsoap.org/claims/ManagerDistinguishedName" `
-ShortName "manager_dn" -IsAccepted $true -IsOffered $true -IsRequired $false

Шаг 2. Добавить одно правило по шаблону Send LDAP Attributes as Claims (хранилище — Active Directory) в правилах выпуска приложения SimpleTwo:

LDAP AttributeOutgoing Claim Type
distinguishedNameUserDN
managerManagerDN

Оба столбца — редактируемые списки: distinguishedName в готовом перечне нет, его нужно набрать руками. Кастомных правил не требуется, порядок правил значения не имеет.

Шаг 3. Указать SimpleTwo, что читать. Консоль → Settings → поля каталога:

  • Directory DN (internal) → из claim'а user_dn;
  • Manager → из claim'а manager_dn.

Первое поле служебное, оно нигде не показывается: DN в карточке коллеги — это шум.

Шаг 4. Проверить. Руководитель появляется в карточке после того, как оба — сотрудник и его руководитель — хотя бы раз вошли: пока одной из учётных записей нет, соединять нечего. Подтверждение — тишина в аудите: записи directory.manager_unresolved перестают появляться.

3. Если не получилось

Что видноПричина
В токене нет user_dn / manager_dnне зарегистрированы описания claim'ов (шаг 1) или короткие имена заняты
manager_dn пуст у части людейу них в AD не заполнен manager — вопрос к каталогу
Оба claim'а на месте, руководителя в профиле нетв SimpleTwo не сопоставлено поле Directory DN (internal)
В аудите directory.manager_unresolved с DNэтот руководитель ещё ни разу не входил в SimpleTwo
Руководитель «отвалился» у одного человекаего перенесли в другой OU, DN изменился; восстановится при следующем входе руководителя
Почему так подробно про «пусто»

У ADFS почти все ошибки здесь тихие: правило с опечаткой в имени атрибута не падает, а возвращает пустой набор и завершается успешно. Отличить «не нашлось» от «не сработало» можно только по тому, где именно пусто.