Я хочу повысить уровень нашей безопасности, и для этого необходимо по возможности избегать использования секретных учётных данных.
К сожалению, плагин OIDC требовал клиентский секрет для обращения к эндпоинту /userinfo, и я не мог настроить свой форум с включённым плагином.
К счастью, спецификация OIDC определена таким образом, что не требует использования каких-либо секретных токенов.
Если мы будем придерживаться потока id_token, то IdP предоставит нам всю необходимую информацию для аутентификации пользователя, без необходимости обращаться к IdP повторно.
Это безопасно, поскольку редирект настроен в IdP, и нам не нужно беспокоиться о том, что bearer-токен будет перенаправлен не по назначению.
Я создал патч для плагина OIDC, добавляющий поддержку потока id_token, и отправил pull-запрос здесь:
PR пока не совсем готов, так как ему не хватает модульных тестов, но в целом всё почти готово, и я подтвердил, что это корректно работает с Azure AD (Entra ID).
По-видимому, вы описываете здесь OpenID Connect “Implicit Flow”, который работает без какого-либо сервер-серверного взаимодействия и поэтому не требует общего секрета. Вместо этого вся информация передаётся через HTTP-перенаправления, а ID-токен криптографически проверяется с использованием открытых ключей из Discovery-документа.
Это допустимо, и я считаю, что это валидная просьба о новой функции. Однако это совершенно другая система по сравнению с нашим текущим плагином, который использует authorization code flow. Этот поток использует сервер-серверное взаимодействие с общим секретом, поэтому криптографическая проверка id_token не требуется. В некоторых аспектах это проще, но в других — сложнее.
Важно: мы не можем просто изменить реализацию по умолчанию в плагине. Сайты, использующие authorization-code flow, должны продолжать использовать его. Насколько я помню, многие провайдеры идентификации вообще не поддерживают Implicit Flow.
Поэтому я вижу два возможных пути развития:
Мы добавляем поддержку “implicit flow” в плагин OIDC, но делаем это опциональным. Я считаю маловероятным, что мы примем PR, который добавляет gem openid-connect как зависимость ядра Discourse, поэтому реализация должна быть выполнена в рамках нашей текущей стратегии.
Плагин discourse-lti (интеграция инструментов обучения) может послужить полезным источником вдохновения, поскольку протокол LTI основан на implicit flow OIDC. Логика декодирования id_token находится здесь.
Или, альтернативно,
Вы создаёте implicit flow как совершенно новый плагин. В этом случае вы будете свободны в выборе реализации (но вам также придётся поддерживать его самостоятельно).
Я считаю, что в некоторых ситуациях он всё ещё может иметь смысл. Однако, похоже, что поток кода авторизации (по умолчанию в Discourse) с PKCE (опционально в Discourse) является наиболее рекомендуемым способом использования OIDC.
Поэтому, возможно, стоит пересмотреть следующее утверждение:
Действительно ли переход на неявный поток OIDC и, следовательно, передача всей пользовательской информации через клиент представляет собой улучшение безопасности?
Я считаю, что в некоторых ситуациях это всё ещё может иметь смысл. Однако, похоже, что поток авторизационного кода (по умолчанию в Discourse) с PKCE (опционально в Discourse) является наиболее рекомендуемым способом использования OIDC.
Это очень интересно — до сих пор я не до конца понимал, что такое PKCE. Исходя из прочтения документации Auth0, кажется, что (при определённых конфигурациях) этот поток сочетает преимущества потока неявного кода (отсутствие секретного ключа клиента) без его недостатков.
Возможно, это можно реализовать вместо текущей схемы? Выглядит так, будто достаточно просто убрать параметр секретного ключа клиента из конечной точки /token.
В конечном счёте, моя главная цель — просто устранить необходимость в секретном ключе клиента