Skip to main content
Некоторые OIDC-клиенты отправляют запросы в форме, которая расходится с RFC. Veriqa строгая и такой запрос отвергает — это правильное поведение по умолчанию, но иногда исправить клиента вы не можете: чужой плагин, коробочная CMS, вендорская сборка. Квирк совместимости — именованное послабление формы запроса, включаемое для одного клиента. Каждый квирк точечный, выключен по умолчанию и живёт с заранее объявленным условием снятия: когда апстрим-дефект починят, ключ убирают вместе с его обработчиком.
Квирк — это ветка поведения, а не настройка. Включайте его, только если конкретный клиент действительно не может отправить корректный запрос, и снимайте, как только условие снятия выполнено. Каждый включённый квирк Veriqa сообщает предупреждением в логе при старте.

Почему по клиенту, а не глобально

Послабление, включённое глобально, ослабляет проверку для всех приложений — включая те, что шлют корректные запросы, и те, что появятся в конфигурации завтра. Строгость проверки перестаёт быть свойством развёртывания и становится свойством самого слабого его участника. Поэтому квирк адресуется по ClientId: клиент со сломанным плагином получает послабление, все остальные продолжают проверяться строго. Это же делает послабление видимым — в конфигурации написано, какому приложению и что именно разрешено сверх RFC.

Как включить

Включение двухступенчатое: мало перечислить квирк у клиента — нужно ещё открыть гейт развёртывания. Пока гейт закрыт, набор квирков клиента пересекается с пустым набором уровня ядра, и послабление не применяется.
appsettings.json
Две ступени существуют затем, чтобы конфигурация отдельного клиента не могла в одиночку ослабить проверку: за общий потолок отвечает тот, кто владеет развёртыванием, а за конкретное приложение — запись клиента.

Профиль вместо перечня ключей

Вместо того чтобы выписывать ключи по одному, можно назвать профиль — движок и плагин, которые у вас стоят. Профиль разворачивается в те же ключи, проходит ту же валидацию, тот же гейт и тот же потолок: это сокращение записи, а не отдельный механизм.
appsettings.json
Профиль и явный перечень можно сочетать — ключи объединяются. Неизвестное имя профиля роняет старт с перечнем допустимых, ровно как неизвестный ключ квирка: опечатка не может молча оставить послабление выключенным. В профиль входят только послабления формы запроса. Ничто, меняющее claims, профилем включаться не может: включая совместимость со сломанным клиентом, интегратор не должен получить в придачу другое утверждение о том, кто вошёл.

Как выключить

Уберите ключ из CompatibilityQuirks этого клиента — послабление перестаёт действовать при следующем старте. Чтобы разом снять все квирки развёртывания, не трогая записи клиентов, закройте гейт: CompatibilityQuirksAllowApplicationOverride: false. Специально выключать ничего не нужно: дефолт — выключено у всех. Свежее развёртывание не применяет ни одного квирка, пока вы не откроете гейт и не перечислите ключ явно.

Что Veriqa сообщает при старте

  • Квирк действует — предупреждение со списком «клиент → включённые квирки». Это ожидаемый шум: включённое послабление не должно быть тихим.
  • Квирк перечислен, но не действует — предупреждение с причиной. Если гейт закрыт, так и сказано, и лечится открытием гейта. Если гейт открыт, а набор всё равно пуст — дело не в гейте: запись клиента не дошла до резолвера, чаще всего из-за второй записи с тем же ClientId, перекрывающей эту.
  • Неизвестный ключ — старт не продолжается: конфигурация выбирает ключ из закрытого набора, и опечатка здесь означала бы тихо не применённое послабление. В сообщении перечислены допустимые ключи. Сравнение регистрозависимое — Drop-Scope-On-Code-Exchange будет отвергнут наравне с опечаткой.
Конфигурация выбирает ключ, а не тип и не сборку: по строке из конфигурации никогда не выполняется рефлексия. Право править конфигурацию не даёт исполнить свой код внутри identity-провайдера.

Реестр квирков

drop-scope-on-code-exchange

Что делает. Убирает параметр scope из token-запроса с grant_type=authorization_code. Зачем. RFC 6749 §4.1.3 в этом запросе scope не предусматривает, и строгая проверка отвергает его как invalid_request. При обмене кода присланный scope всё равно ни на что не влияет — выданный набор прав берётся из authorization code, — поэтому снятие параметра равносильно тому, что клиент его и не отправлял. Права не расширяются. Кого касается. Плагин openid-connect-generic для WordPress кладёт scope в запрос обмена кода. Симптом — вход доходит до обмена кода и падает с ответом:
В WordPress этот ответ виден не JSON-ом: плагин возвращает браузер на страницу входа сайта, а текст ошибки кладёт в адрес — wp-login.php?login-error=invalid_request&message=The+'scope'+parameter+is+not+valid+in+this+context. С включённым квирком этот же запрос проходит проверку формы, а в логе появляется запись о снятом параметре — с ClientId и снятым значением. Правок на стороне сайта при этом не требуется: вход проходит на штатном плагине, без установленных на сайт заплаток. Что не задето. Путь grant_type=refresh_token: там scope разрешён RFC 6749 §6 и сужает выданные права. Этот путь квирк не трогает — сужение прав законно и полезно. Условие снятия. Апстрим-фикс oidc-wp/openid-connect-generic#497 выпущен и раскатан на стороне интеграторов, использующих плагин. После этого ключ убирается вместе с обработчиком. Пока issue открыт, квирк нужен.

drop-resource-parameter

Что делает. Снимает параметр resource (RFC 8707) с запроса авторизации и с token-запроса. Зачем. Ресурсы Veriqa не регистрирует, поэтому строгая проверка отвергает любое значение этого параметра с invalid_target, и вход обрывается, не начавшись. Потребителя у параметра нет: без зарегистрированных ресурсов права берутся из scope’ов, поэтому снятие даёт ровно тот же токен, что и запрос без параметра. Квирк не выдаёт audience и не сужает его — это не поддержка индикаторов ресурса. Кому нужен. Плагин auth_oidc у Moodle сохраняет диалект Microsoft Entra ID, под который был написан, и шлёт resource в каждом запросе, в том числе в generic-режиме; настройки, которая это отключает, нет. Симптом: вход останавливается на запросе авторизации с
С включённым квирком тот же запрос проходит проверку формы, а в лог добавляется запись о снятом параметре — с ClientId и снятым значением. Что не затрагивается. Дефолт. Без включённого у конкретного client_id ключа resource отвергается с invalid_target. Условие снятия. Плагин auth_oidc у Moodle перестаёт слать resource в generic-режиме (вне Entra). Апстрим-тикета на это нет.

Дальше

Справочник конфигурации

Все ключи, включая клиентские.

Hardening к продакшну

Что проверить перед выпуском в продакшн.