Почему по клиенту, а не глобально
Послабление, включённое глобально, ослабляет проверку для всех приложений — включая те, что шлют корректные запросы, и те, что появятся в конфигурации завтра. Строгость проверки перестаёт быть свойством развёртывания и становится свойством самого слабого его участника. Поэтому квирк адресуется по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 в запрос обмена
кода. Симптом — вход доходит до обмена кода и падает с ответом:
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 к продакшну
Что проверить перед выпуском в продакшн.