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

Вход по корпоративной учётной записи (OIDC)

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

Координатор выступает доверяющей стороной OpenID Connect (OIDC Relying Party): человек входит той же учётной записью, что и в остальные корпоративные системы, а SimpleTwo заводит ему аккаунт при первом входе и держит профиль в актуальном состоянии по данным провайдера.

Проверено с Entra ID (Azure AD), ADFS, Keycloak, Okta и Google. Подписи ID-токена проверяются по ключам из JWKS провайдера, алгоритм RS256 — тот, что эти провайдеры используют по умолчанию.

Провайдер, умеющий только SAML

Прямого SAML в координаторе нет. Провайдер, который говорит только на SAML, подключается через ADFS или Entra ID: для SimpleTwo они выглядят обычным OIDC, а SAML остаётся между ними и вашим провайдером. Пункт меню в консоли называется «Single sign-on (OIDC)» именно поэтому.

1. Что нужно завести у провайдера​

Одно приложение (app registration) с типом «веб» и адресом возврата:

https://<адрес координатора>/admin/api/sso/callback

Адрес возврата подставляется сам из публичного адреса координатора — менять его в настройке нужно только если перед координатором стоит свой домен или прокси.

Запрашиваемые области по умолчанию — openid email profile groups. Группы нужны для сопоставления с ролями; если провайдер отдаёт их под другим именем области (частый случай — Entra ID, где группы приходят без отдельной области), исправьте поле Scopes и имя claim'а.

2. Настройка в консоли​

Settings → Single sign-on (OIDC):

ПолеЧто этоПо умолчанию
Issuerадрес издателя; настройки берутся из <issuer>/.well-known/openid-configuration—
Client ID / Client secretучётные данные приложения у провайдера—
Redirect URLадрес возврата<публичный адрес>/admin/api/sso/callback
Scopesобласти через пробелopenid email profile groups
Email claimclaim с адресом — он же имя учётной записиemail
Name claimclaim с отображаемым именемname
Groups claimclaim со списком группgroups
Group → roleсопоставление групп провайдера с ролями SimpleTwoпусто
Default roleроль тем, кто не попал ни в одно правилопусто
Пустая «Default role» — это отказ во входе, и так задумано

Человек, чьи группы не совпали ни с одним правилом, не получит доступ: в журнале появится событие sso.no_role со списком его групп. Это удобный способ настроить сопоставление — попробуйте войти, посмотрите, какие группы пришли на самом деле, и внесите их в таблицу. Заполненная «Default role» открывает вход всей организации, поэтому ставьте её осознанно.

Поток входа — authorization code с state, nonce и PKCE; ID-токен проверяется по подписи, издателю, аудитории и сроку. Ничего из этого не настраивается — это условия, при которых токен принимается.

3. Профиль: какие поля приходят из каталога​

Кроме почты, имени и групп координатор умеет забирать произвольные атрибуты профиля — должность, подразделение, телефон, город, руководителя. Каждому полю в Groups / roles → profile задаётся источник:

  • из claim'а — значение приходит от провайдера и обновляется при каждом входе; человек его не редактирует;
  • своё — человек заполняет сам в клиенте.

Поле, чьё имя или claim означает дату рождения, распознаётся автоматически и получает особую обработку: год виден только владельцу, коллегам отдаются день и месяц. Обрезка делается на сервере, а не в интерфейсе, и нечитаемое значение отбрасывается целиком, а не отдаётся как есть.

Руководителя лучше передавать не адресом, а парой user_dn / manager_dn — как это настроить в ADFS и почему именно так, написано в статье про ADFS.

4. Домены организации​

Клиент находит контур по домену рабочей почты: человек вводит ivan@example.com, приложение само определяет, к какому координатору идти. Домены перечисляются в той же настройке, а кнопка проверки (POST /admin/api/sso/domains/check) показывает, что видит клиент.

Домен, который обслуживает другая установка, добавлять сюда не нужно: взаимодействие между установками — это федерация, отдельный механизм.

5. Как это выглядит у пользователя​

  • В браузере (админ-консоль, веб-клиент) — обычный переход к провайдеру и обратно.
  • В приложении — человек вводит рабочую почту и пароль в самом клиенте. Координатор проверяет их у провайдера (password grant) и, если провайдер подтвердил, заводит или обновляет учётную запись. Пароль в SimpleTwo не хранится и не сравнивается локально: у учётной записи из каталога здесь просто нет пароля.
Строка, которую ввёл человек, уходит провайдеру как есть

SimpleTwo не переписывает введённый адрес. ADFS по умолчанию сверяет его с userPrincipalName, поэтому сотрудник с UPN ivan@corp.local и почтой ivan@example.com получит «неверные учётные данные», хотя пароль верный. Лечится на стороне ADFS — Alternate Login ID, см. статью про ADFS.

6. Если вход не удался​

Смотреть — журнал аудита в консоли (/admin/api/audit), события с префиксом sso.:

СобытиеЧто означаетЧто делать
sso.password_rejectпровайдер не принял пару логин/парольпроверить, что человек вводит тот идентификатор, который провайдер сверяет (UPN или ALI)
sso.no_roleвход прошёл, но группы не дали ни одной роли; рядом лежит список пришедших группвнести группу в Group → role или задать Default role

Две ошибки, которые выглядят как поломка SimpleTwo, но лечатся у провайдера:

  • Группы не приходят вовсе. Проверьте, что claim с группами включён в токен: у ADFS claim попадает в OIDC-токен только с зарегистрированным коротким именем, у Entra ID группы нужно явно добавить в конфигурацию токена.
  • Другой алгоритм подписи. Принимается RS256. Провайдер, подписывающий ES256, сейчас не поддерживается — это видно по отказу проверки подписи в журнале.

Кто ведёт вход​

Актуально для: SimpleTwo 0.9.285 и новее.

В карточке SSO консоли координатора есть блок «Кто ведёт вход»:

  • Координатор — как описано выше: своя форма входа и свой брокер в корпоративный провайдер.
  • Directory — вход в браузере ведёт страница входа directory: второй фактор, собственный вход через корпоративный провайдер. Координатор становится одним из приложений directory и по-прежнему сам выдаёт токены платформы, так что другие сервисы режим не замечают.

Переключиться на identity можно, только когда у хоста directory есть публичное имя и координатор до него достучался. Строка под переключателем говорит, почему нельзя. При переключении координатор сам регистрирует себя в directory как приложение platform и хранит его секрет. Учётки в этом режиме не заводятся при входе: человек должен уже быть в directory. Вход по паролю из мобильных и настольных клиентов работает в обоих режимах, пароль проверяет directory. Запасного входа по паролю через корпоративный провайдер в режиме identity нет: directory сам проверяет пароль, в том числе через каталог LDAP.

Как хранятся секреты интеграций​

Актуально для: directory новее 0.27.1.

Секреты, которые directory держит для интеграций, — секрет клиента у корпоративного провайдера, токены целей SCIM и SIEM, ключ клиента SIEM, секреты вебхуков, пароль учётки чтения LDAP, пароль или токен подключения SimpleOne — и собственные ключи подписи directory хранятся в базе зашифрованными. Ключ directory получает от координатора так же, как чат и почта, и держит только в памяти; в базе и на диске хоста его нет. Ключ есть, как только в консоли координатора создан ключ шифрования — тот же, которым шифруются сообщения; для directory из него выводится отдельный ключ.

Что сейчас, видно на «Обзоре» консоли, в карточке «Настройка каталога», и в /healthz (secrets_sealed):

  • секреты интеграций зашифрованы — всё в порядке;
  • не зашифрованы: нет ключа — ключа шифрования в установке нет или координатор недоступен; секреты хранятся как введены, как было до этой версии;
  • зашифрованы, но ключа нет — directory не получил ключ после перезапуска. Новые секреты не принимаются, пока ключ не придёт: писать открытым текстом рядом с зашифрованным directory отказывается.

Секреты, сохранённые раньше открытым текстом, шифруются сами, как только придёт ключ.

Второй фактор и адресные книги​

Актуально для: directory новее 0.28.0.

Тем же ключом шифруются секрет второго фактора (TOTP) каждого пользователя и содержимое адресных книг — личных и общей книги организации: адрес или номер, подпись и заметка контакта. Коды восстановления и пароли приложений и раньше хранились только как хеши, ключи входа (passkey) — только открытая часть; их шифровать не нужно. Пользователь ничего не замечает: вход с кодом, книги, синхронизация, импорт и экспорт vCard и CSV работают как прежде. Ранее сохранённые секреты и контакты, включая удалённые, шифруются при первом получении ключа; телефоны пользователей из-за этого книги заново не скачивают. Что зашифровано, перечисляет /healthz в поле secrets.covers.

Восстановление по листу ключа​

Если координатора нет, а есть выгрузка базы directory и распечатанный лист ключа восстановления, проверьте, что лист её открывает:

identity recover --key "ключ с листа" --key-id kek-1 --dsn "строка подключения к базе identity"

Это пробный прогон: база не меняется. Команда выводит отчёт по видам данных — сколько значений зашифровано, сколько открылось, сколько хранится открытым текстом — и завершается с кодом 0, только если открылось всё. Если координатор восстановлен с новым мастер-ключом и напечатан новый лист, перешифруйте базу под него:

identity recover --key "старый лист" --key-id kek-1 --dsn "…" \
--reseal-key "новый лист" --reseal-key-id kek-1

Поколение указывается то, что напечатано на новом листе, даже если оно называется так же, как на старом. Перешифрование записывается в журнал событий безопасности; после него базу открывает только новый лист, и directory получает от нового координатора ключ, который её открывает. Если перешифрование прервалось, запустите ту же команду ещё раз — она доделает остальное.

Дальше​