Как развернуть единый вход (SSO)
Инструкция для того, кто разворачивает Zentro у заказчика, и администратора Zentro: как сделать, чтобы приложения организации входили через Zentro — один вход на все приложения, общий экран входа, согласие и выход.
Установка фронта — Установка панели и кабинета, подключение приложений — Подключение сервиса (сервис целиком) и Подключение приложения (отдельное приложение).
Как это устроено
Заголовок раздела «Как это устроено»Zentro Identity — провайдер входа (OpenID Connect). Своего экрана у него нет: вход, второй фактор и «Разрешить» пользователь видит в личном кабинете Zentro.
Приложение ──(1) «Войти»──▶ Identity /oidc/authorize │ (2) нет входа или нужно согласие ▼ Личный кабинет /oidc/consent вход · второй фактор · «Разрешить» │ (3) код ▼Приложение ◀────────────── redirect_uri?code=… │ (4) сервер приложения меняет код на токены в Identity- Один вход на все приложения: вошли в кабинет один раз — остальные приложения пускают без пароля, пока жива сессия кабинета.
- Кабинет публикуется наружу, панель — нет. В кабинете нет админского кода вообще, его BFF не пропускает запросы к админскому API. Панель остаётся во внутренней сети.
- У панели своя сессия. Панель — не SSO-приложение, в неё входят отдельно.
Что нужно заранее
Заголовок раздела «Что нужно заранее»-
Домены с TLS (пример по тексту):
Адрес Что там Снаружи https://id.example.comIdentity да — к нему ходят браузеры и приложения https://account.example.comличный кабинет да — здесь входят пользователи https://admin.example.comпанель нет, только внутренняя сеть или VPN -
Identity установлен (Установка сервера), первый администратор заведён, у него есть второй фактор.
-
Фронт установлен (Установка панели и кабинета).
-
Почта (SMTP) у Identity — без неё не уйдут ссылки на сброс пароля, подтверждение почты и привязки.
Шаг 1. Настроить Identity
Заголовок раздела «Шаг 1. Настроить Identity»Это переменные окружения Identity — их задаёт тот, кто его разворачивает (identity.env, .env
compose). После правки Identity перезапускают. Что выбрать и почему (адреса, подпись токенов,
секреты) — Выбор настроек.
| Переменная | Значение | Зачем |
|---|---|---|
PUBLIC_BASE_URL |
https://id.example.com |
Адрес Identity — он же issuer в токенах. Приложения проверяют его в каждом токене; менять после запуска нельзя без перенастройки всех приложений |
OIDC_AUTHORIZE_UI_URL |
https://account.example.com/oidc/consent |
Куда Identity отправляет пользователя войти и дать согласие. Не задан — вход в приложения обрывается на пустой странице |
PASSWORD_RESET_URL |
https://account.example.com/reset-password |
Ссылка в письме сброса пароля |
EMAIL_VERIFY_URL |
https://account.example.com/verify-email |
Ссылка подтверждения почты |
EMAIL_CHANGE_URL |
https://account.example.com/confirm-email-change |
Ссылка подтверждения новой почты |
WEBAUTHN_RP_ID |
example.com |
Домен ключей (passkey): общий родитель адресов кабинета и панели |
WEBAUTHN_RP_ORIGIN |
https://account.example.com,https://admin.example.com |
Оба адреса фронта через запятую. Адреса нет в списке — ключи на нём не работают |
TRUSTED_PROXY_CIDRS |
адрес прокси перед Identity | Иначе в сессиях, аудите и лимитах будет адрес прокси, а не пользователя |
SMTP_* |
почтовый сервер | Письма пользователям |
Проверка:
https://id.example.com/.well-known/openid-configurationоткрывается из браузера,issuerв нём — ровноPUBLIC_BASE_URL.
Шаг 2. Настройки в панели
Заголовок раздела «Шаг 2. Настройки в панели»Настройки в панели — то, что меняется без перезапуска (кроме CORS):
| Настройка | По умолчанию | Когда менять |
|---|---|---|
oidc.authorize_request_ttl |
30 минут | Сколько у пользователя времени от «Войти» в приложении до «Разрешить»: войти, завести второй фактор, восстановить пароль. Истекло — приложение начинает вход заново |
oidc.end_session_scope |
current |
current — выход из приложения завершает только его сессию; sso — выход на этом устройстве: вход в Zentro, из которого открыто приложение, и все приложения под ним; all — выход везде: все сессии пользователя и уведомление остальным приложениям |
oidc.backchannel_private_cidrs |
пусто | Внутренние сети (10.20.0.0/16), куда Identity может слать уведомления о выходе приложениям без публичного адреса |
cors.enabled, cors.allowed_origins |
выкл. | Только если есть приложения целиком в браузере (SPA без сервера): их адреса. Применяется после перезапуска Identity |
security.* |
— | Политика паролей, второго фактора и порог для особых операций — по требованиям заказчика |
Шаг 3. Подключить приложения
Заголовок раздела «Шаг 3. Подключить приложения»Каждое приложение регистрируется в Identity:
- сервис целиком (свои роли, приложения, API) — мастер Сервисы → Подключить сервис, Подключение сервиса;
- отдельное приложение — OAuth-клиенты, Подключение приложения.
Команде приложения уходит сводка с issuer и Discovery — дальше приложение берёт все адреса оттуда.
Согласие. При первом входе в приложение пользователь видит «Разрешить» с названием приложения и тем, что оно получит. Для своих приложений организации экран можно убрать — «Приложение организации — не спрашивать согласие» у приложения. Стороннему не убирайте: согласие защищает пользователя. Выданные согласия пользователь видит и отзывает в кабинете (Приложения с доступом).
Повторный вход и уровень входа — приложение может потребовать:
| Приложение передаёт | Что увидит пользователь |
|---|---|
prompt=login |
Экран входа, даже если он уже вошёл (с подсказкой, зачем) |
max_age=N |
То же, если вход был дольше N секунд назад |
acr_values=AAL2 / AAL3 |
Подтверждение вторым фактором / ключом, если текущий вход слабее |
prompt=none |
Ничего: вошёл — сразу код, нет — ошибка приложению без экрана |
Шаг 4. Корпоративный вход (по желанию)
Заголовок раздела «Шаг 4. Корпоративный вход (по желанию)»Если у заказчика свой каталог (Keycloak, корпоративный OIDC, LDAP, Active Directory), его подключают как внешний провайдер входа (Внешние IdP) — пользователи входят в кабинет и приложения корпоративным логином.
-
LDAP / AD (вход по паролю через форму Zentro) — работает и в кабинете, и в панели.
-
OIDC / Keycloak (переход на страницу провайдера) — работает в кабинете и в панели. Нужно:
-
у фронта — публичные адреса BFF:
ACCOUNT_PUBLIC_URL=https://account.example.com/bff,PORTAL_PUBLIC_URL=https://admin.example.com/bff(Установка панели и кабинета, шаг 2); -
в провайдере и в Zentro (Внешние IdP → Redirect URI) — оба адреса возврата:
https://account.example.com/bff/auth/idp/<имя провайдера>/callbackhttps://admin.example.com/bff/auth/idp/<имя провайдера>/callback
Человек вернётся в то приложение, где начал вход. Не заданы публичные адреса — Identity вернёт на первый адрес списка (поставьте первым кабинет).
Привязка аккаунта через такой провайдер, начатая в панели, пока возвращает в кабинет — привязывайте в кабинете (вопрос к бэку открыт).
-
Подробно о провайдерах — Внешние провайдеры входа.
Шаг 5. Проверить
Заголовок раздела «Шаг 5. Проверить»https://id.example.com/.well-known/openid-configuration—issuer=PUBLIC_BASE_URL.- Кабинет
https://account.example.comоткрывается, вход работает, письмо «Забыли пароль?» приходит и ссылка из него открывает кабинет. - Ключ (passkey): завести в кабинете (Безопасность) и войти им — работает и в кабинете, и в панели.
- Тестовое приложение: «Войти» → экран входа кабинета → «Разрешить» → вернулись в приложение.
- Второе приложение: «Войти» — без пароля, сразу обратно (или только «Разрешить»).
- Выход из приложения; при
oidc.end_session_scope=sso— вышли и из остальных приложений на этом устройстве, приall— везде. - Панель снаружи не открывается.
Частые ошибки
Заголовок раздела «Частые ошибки»| Что видно | Причина | Что сделать |
|---|---|---|
| «Войти» в приложении → пустая страница или ошибка Identity | Не задан OIDC_AUTHORIZE_UI_URL или указывает не на кабинет |
Шаг 1 |
Приложение отвергает токен: неверный iss |
PUBLIC_BASE_URL не совпадает с тем, что знает приложение (http/https, слэш, порт) |
Приложение берёт issuer из Discovery; PUBLIC_BASE_URL — ровно публичный адрес |
| Ключ (passkey) не работает на одном из адресов | Адреса нет в WEBAUTHN_RP_ORIGIN или WEBAUTHN_RP_ID не родитель домена |
Шаг 1 |
| Ссылки из писем ведут не туда | PASSWORD_RESET_URL / EMAIL_*_URL указывают на старый адрес |
Шаг 1 |
| Письма не приходят | Нет SMTP у Identity | SMTP_*; проверить журнал Identity |
| «Запрос на вход устарел. Вернитесь в приложение и войдите снова» | Пользователь не уложился в oidc.authorize_request_ttl |
Начать вход в приложении заново; при необходимости увеличить срок |
| Все пользователи упираются в «слишком много попыток» | Identity или фронт видят адрес прокси вместо адресов пользователей | TRUSTED_PROXY_CIDRS у Identity; для фронта — REAL_IP_FROM (Установка панели и кабинета, шаг 5) |
| SPA-приложение не может получить токен (ошибка CORS в браузере) | Адрес приложения не разрешён в CORS Identity | cors.enabled, cors.allowed_origins, перезапуск Identity |
| Корпоративный вход в панели уводит в кабинет | Не задан PORTAL_PUBLIC_URL — Identity вернул на первый адрес |
Задать публичные адреса BFF и добавить адрес панели в Redirect URI |
| «Вход через этого провайдера здесь не настроен» | Адреса возврата этого приложения нет в Redirect URI провайдера в Zentro | Добавить …/bff/auth/idp/<имя>/callback этого приложения |