Skip to main content
Кроме CMS Veriqa подключается к системам, куда сотрудник входит каждый день: DevOps, мониторинг, файловое хранилище, форум, ERP, LMS и чужой identity-provider. Клиент OIDC везде бесплатный, но не везде штатный: GitLab, Keycloak, Grafana, Nextcloud и Discourse несут его в поставке, а Odoo и Moodle требуют доустановки модуля со стороны.

Что проверено

Проверено на канале Email, без изменений на стороне Veriqa.

GitLab

Барьер. Из коробки вход не проходит: omniauth_openid_connect кладёт scope в запрос grant_type=authorization_code, где RFC 6749 §4.1.3 его не предусматривает. Veriqa отвечает invalid_request, GitLab показывает:
Что сделать. Добавить в args провайдера один флаг:
Учётная запись. Создаётся первым входом (JIT), связывается по sub Veriqa, адрес из claim email GitLab считает подтверждённым и своего письма-верификации не шлёт.
Если claim email не приходит, GitLab не отказывает: он заводит пользователя, выдаёт сессию и подставляет собственный служебный адрес вида temp-email-for-oauth-{login}@gitlab.localhost, показывая подсказку заполнить профиль.

Keycloak

Здесь Veriqa подключается к другому identity-provider как внешний OIDC-провайдер: Keycloak принимает вход у Veriqa и дальше сам выступает провайдером для своих приложений. Конфигурации почти нет. Keycloak импортирует discovery-документ Veriqa и заполняет все адреса сам, включая jwks_uri, и сам же включает проверку подписи. Барьер — не email, а фамилия. Схема профиля realm’а по умолчанию требует email, firstName и lastName. Claim family_name Veriqa отдаёт только тогда, когда канал дал фамилию: Telegram и MAX берут её из профиля мессенджера, где она необязательна, а Email не даёт её никогда. Поэтому первый вход упирается в форму «Update Account Information» — всегда на канале Email и выборочно на остальных. Что сделать. Realm settings → User profile: снять признак обязательности с firstName и lastName.
Отключение сверки профиля у самого провайдера (update.profile.on.first.login = off) эту задачу не решает, хотя выглядит решением: пользователь создаётся, но Keycloak тут же включает обязательное действие VERIFY_PROFILE с тем же требованием — учётная запись есть, сессии нет. Требование снимается только в схеме профиля realm’а.
Две формы добора подряд. Если входу не хватает claim, который Veriqa добирает сама, Veriqa спрашивает его у пользователя на своей форме, прежде чем вернуть вход. RP со своей формой добора профиля — Keycloak, а также Logto — показывает сразу после неё вторую. Для такого приложения выключите форму Veriqa членом ClaimCompletionFormEnabled: false в его записи Veriqa:OpenIddict:Clients (см. Clients). При выключенной форме недостающие claims не выдаются и вход не блокируют: RP спрашивает их на своей форме. Телефона и email это не касается — Veriqa получает их своими путями.

Grafana

Барьер. Без claim email Grafana не отказывает сразу — она ищет адрес по соглашению, совместимому с GitHub: запрашивает {api_url}/emails, которого в OpenID Connect нет. Получает 404 и прекращает аутентификацию:
Сообщение уводит в сторону: причина не в сетевой ошибке, а в отсутствующем claim. Что сделать. Обеспечить приход email. Канал Email даёт его сам; на канале, который адреса не даёт (Telegram), адрес добирает Veriqa внутри входа, если email требуется, либо подставляет ваш код — см. Обогащение claim’ов. Учётная запись. Создаётся автоматически, email, name и login заполняются адресом.
Grafana не шлёт nonce и не проверяет подпись id_token по JWKS — claims она разбирает из тела токена. Ещё она пытается прочитать access token Veriqa как JWT и пишет в отладочный лог token is not in JWT format: access token — не JWT (сейчас это непрозрачный reference-токен, во время прогона был JWE), на вход это не влияет.

Nextcloud

Барьеры здесь не в claims, а в транспорте, и оба снимаются настройкой Nextcloud. Только HTTPS. По HTTP user_oidc отдаёт 404 со страницей «You must access Nextcloud with HTTPS to use OpenID Connect». Проверка пропускает поток при HTTPS, в debug-режиме или при app-настройке allow_insecure_http — последняя годится для внутреннего контура. Защита от приватных адресов. Пока не выставлен allow_local_remote_servers=true, Nextcloud не ходит на issuer в приватной сети. Диагностируется плохо: возврат отдаёт 403, а единственный след — строка в nextcloud.log:
В продакшне обе настройки не нужны: issuer публичен и работает по HTTPS. Связывание — обязательно решить до первого входа. Идентификатор пользователя Nextcloud строит по-разному: Если вы планируете сопоставлять учётные записи Nextcloud со своими по sub, снимите uniqueUid до первого входа: смена настройки не переименовывает уже заведённых пользователей.
Nextcloud проверяет подпись id_token по JWKS и не обращается к /connect/userinfo вовсе: все claims он берёт из id_token. Claims, которые Veriqa отдаёт только в userinfo, до него не доедут — если они вам нужны, включите enrichLoginIdTokenWithUserinfo.

Discourse

Плагин openid_connect встроен в ядро — устанавливать нечего. Барьера два, и оба снимаются настройками форума. По умолчанию Discourse не запрашивает email. Настройка openid_connect_authorize_scope содержит только openid. Для форума это тупик: без адреса учётная запись не создаётся, а вход останавливается на форме регистрации. Задайте openid email profile. Защита от приватных адресов. Пока issuer в приватной сети, Discourse к нему не пойдёт: allowed_internal_hosts должен содержать его хост. В браузер при этом уезжает безликое openid_connect_discovery_error — причину видно только при включённом openid_connect_verbose_logging. В продакшне барьер не возникает.
Неудачное чтение discovery кешируется. После исправления настройки Discourse какое-то время продолжает отвечать той же ошибкой, и выглядит это так, будто правка не помогла. Сбросьте кеш.
Что проверено и что нет. Вход существующего пользователя проходит, связка пишется по sub Veriqa, подпись id_token Discourse проверяет по JWKS. Автосоздание учётной записи не проверено: у Discourse оно выполняется отдельным запросом из браузера и защищено анти-бот- механикой.

Odoo

Модуль из поставки не подойдёт. Штатный auth_oauth умеет только implicit flow: он просит response_type=token, не шлёт nonce и не проверяет подпись. Veriqa отвечает unsupported_response_type: implicit убран из OAuth 2.1 как небезопасный. Снаружи это выглядит как страница ошибки вместо возврата на сайт. Что ставить. Модуль auth_oidc из репозитория OCA (ветка вашей версии Odoo). В настройке провайдера выберите flow = OpenID Connect (authorization code flow) и заполните появившиеся поля: Token URL, JWKS URL и Client Secret. Именно JWKS URL даёт Odoo проверять подпись Veriqa — и он её проверяет.
Модуль требует библиотеку python-jose, и в официальном образе Odoo её нет. Импорт обёрнут в «тихую» ветку с записью в отладочный лог, поэтому без библиотеки модуль ставится, кнопка входа появляется, а сам вход отвечает безликим отказом в доступе. Ставьте python-jose вместе с модулем.
Учётная запись. Создаётся автоматически — свободная регистрация включена в чистой базе Odoo по умолчанию, ничего дополнительно включать не нужно. Связка пишется по sub Veriqa в поле oauth_uid, логином становится адрес. Если адрес не приходит, Odoo подставляет собственный синтетический логин и всё равно заводит пользователя.

Moodle

Своего OIDC-клиента у Moodle нет; используется плагин auth_oidc, который Microsoft поставляет для Entra ID. Вход проходит, пользователь создаётся, связка пишется по sub Veriqa — но три барьера придётся снять, и два из них вы встретите даже в продакшне. Плагин шлёт чужой параметр. В любом режиме, кроме «Microsoft Identity Platform», он добавляет к запросу параметр resource, а когда поле в настройке пустое — подставляет зашитый адрес Microsoft Graph. Veriqa отвечает invalid_target: Veriqa не регистрирует ресурсы RFC 8707, поэтому не проходит никакое значение. Выходов два, и тот, что на стороне Veriqa, ничего не требует от Moodle: включите для этого client_id квирк уровня клиента drop-resource-parameter — параметр снимается до валидации. Потребителя у него здесь нет, поэтому выданный токен совпадает с тем, что получил бы клиент, никогда его не присылавший: ресурс не регистрируется, audience не выдаётся.
Со стороны Moodle обойти это можно только одним способом — выбрать тип провайдера «Microsoft Identity Platform», при котором параметр не добавляется. Способ рабочий, но это заведомо неверное описание провайдера в настройке: общего режима «другой провайдер» без resource плагин не даёт. Рекомендуемый путь — квирк выше.
Защита от приватных адресов — и от портов. Moodle блокирует исходящие запросы не только по адресу (curlsecurityblockedhosts), но и по порту: curlsecurityallowedport по умолчанию разрешает лишь 443 и 80. В отличие от остальных систем, этот барьер не исчезает сам в продакшне — если ваш issuer слушает нестандартный порт, порт нужно разрешить явно. Диагностика скупая: в браузере «Error in OpenID Connect. Please check logs», настоящая причина (The URL is blocked.) видна только после включения отладочного режима плагина. Двоеточие в идентификаторе. Если Moodle нечего взять для имени пользователя, кроме sub Veriqa, вход упрётся в «The given username contains invalid characters»: sub имеет вид telegram:1234 или email:адрес, а двоеточие Moodle в логинах не принимает. Два выхода: запрашивать scope profile (тогда имя берётся из preferred_username) или включить extendedusernamechars. После создания. Moodle уводит нового пользователя на «дозаполните профиль»: имя и фамилия у него обязательны, а канал их не всегда даёт.

Требование email: четыре разных поведения

Telegram адреса не даёт, и системы относятся к его отсутствию по-разному. Разница практическая: она определяет, нужен ли вам вообще подставленный адрес. Как выглядит та же картина на CMS — в обзоре интеграций с CMS.

Локальная проверка: у каждой системы свой выключатель

Если вы поднимаете связку на своей машине, issuer оказывается в приватной сети, и почти каждая система защищается от обращений туда собственным флагом: Четыре первых барьера исчезают в продакшне вместе с публичным issuer. Moodle — исключение: он ограничивает ещё и порт, поэтому остаётся препятствием и на публичном адресе, если issuer слушает не 443 и не 80. Подробнее о локальных стендах — Локальная проверка.

Не проверено

  • Каналы, кроме Email. На Telegram ожидаемое отличие — требование адреса (см. таблицу выше).
  • Слияние с уже заведённой локальной учётной записью — кроме Discourse, все системы выше проверены на вновь создаваемом пользователе.
  • Роли, группы и права. Пользователь получает роль по умолчанию; маппинг групп из claim’ов не проверялся ни в одной системе.
  • Повторный вход и обновление данных профиля из провайдера при следующем входе.