Discourse OpenID Connect (OIDC)

:discourse2: Краткое содержание Discourse OpenID Connect позволяет использовать провайдера OpenID Connect в качестве провайдера аутентификации для Discourse.
:open_book: Руководство по установке Этот плагин включен в ядро Discourse. Отдельная установка плагина не требуется.

Возможности

Плагин стремится обеспечить минимальную реализацию спецификации. В частности, он поддерживает «поток авторизационного кода» (Authorization Code Flow). Для начала работы следуйте инструкциям по установке плагина или обратитесь к вашему хостинг-провайдеру.

Наш плагин oauth2-basic можно использовать для подключения к некоторым провайдерам OpenID Connect (OpenID Connect основан на OAuth2). Однако этот плагин требует значительно меньше ручной настройки и может использовать JWT «ID Token», если JSON API недоступен.

Настройка автоматически выполняется с использованием документа обнаружения OpenID Connect. Согласно спецификации, он должен находиться по адресу <domain_издателя>/.well-known/openid-configuration, но Discourse поддерживает любой путь для совместимости с не соответствующими спецификации реализациями (например, Azure B2C). Документ обнаружения кэшируется на 10 минут для повышения производительности на сайтах с высоким трафиком.

Если документ обнаружения включает параметр userinfo_endpoint, плагин использует его для сбора метаданных пользователя. В противном случае плагин извлекает метаданные из id_token (JWT), предоставленного конечной точкой токена. Плагин НЕ проверяет подлинность подписи JWT, так как это значительно усложнило бы систему. Это решение поддерживается спецификацией:

Если ID Token получен через прямую коммуникацию между клиентом и конечной точкой токена (что имеет место в данном потоке), для проверки издателя может использоваться валидация TLS-сервера вместо проверки подписи токена.

Для провайдеров идентификации, поддерживающих авторизацию без секрета с использованием «Потока авторизационного кода с доказательством ключа для обмена кодом» (PKCE), следует включить PKCE, а параметр конфигурации client_secret можно опустить.

Конфигурация

Базовые параметры конфигурации

  • openid_connect_enabled: Включить аутентификацию OpenID Connect

  • openid_connect_discovery_document: URL документа обнаружения OpenID Connect. Обычно находится по адресу https://your.domain/.well-known/openid-configuration

  • openid_connect_client_id: ID клиента OpenID Connect

  • openid_connect_client_secret: Секрет клиента OpenID Connect

  • openid connect rp initiated logout: Перенаправлять пользователя на end_session_endpoint после выхода. Должно поддерживаться вашим провайдером идентификации и быть указано в документе обнаружения.

  • openid connect rp initiated logout redirect: (опционально) post_logout_redirect_uri, который будет передан конечной точке выхода. Если указан, он должен быть зарегистрирован у провайдера идентификации.

  • openid_connect_authorize_scope: Сферы доступа (scopes), отправляемые на конечную точку авторизации. Должна включать ‘openid’

  • openid_connect_use_pkce: Включить Proof Key for Code Exchange (PKCE) для аутентификации OpenID Connect.

  • openid_connect_verbose_logging: Вести подробное логирование информации об аутентификации openid-connect в /logs. Оставьте это отключенным при обычном использовании.

Расширенные параметры конфигурации

  • openid_connect_token_scope: Сферы доступа (scopes), отправляемые при запросе к конечной точке токена. Официальная спецификация не требует этого.

  • openid_connect_error_redirects: Если error_reason обратного вызова содержит первый параметр, пользователь будет перенаправлен на URL во втором параметре. Используется для необычных реализаций, отправляющих ошибки в ответ на действия пользователя (например, Azure B2C).

  • openid_connect_allow_association_change: Разрешить пользователям отключать и повторно подключать свои учетные записи Discourse от провайдера OpenID Connect.

  • openid_connect_groups_claim: Имя утверждения (claim) в ответе OIDC[1], содержащего группы пользователя в виде массива строк. Оставьте пустым, чтобы отключить синхронизацию групп. См. раздел Синхронизация групп ниже.

  • openid_connect_user_field_mappings: Отображение утверждений OIDC[2], которые будут сохранены в пользовательских полях Discourse. Пользовательские поля идентифицируются их числовым ID, который можно найти в URL при их редактировании через панель администратора.

Синхронизация групп

Плагин может автоматически синхронизировать членство в группах от вашего провайдера OpenID Connect с группами Discourse. При каждом входе плагин считывает настроенное утверждение из токена OIDC и обновляет членство пользователя в группах соответствующим образом. Чтобы включить синхронизацию групп:

  1. Настройте вашего провайдера идентификации на возвращение массива групп в одном из утверждений. Это должен быть массив строк.

  2. Установите openid_connect_groups_claim в имя утверждения в токене OIDC, содержащего группы пользователя (например, cognito:groups). После установки информация начнет синхронизироваться с системой «Связанные группы» (Associated Groups) в Discourse.

  3. Найдите группу Discourse, которую хотите связать. Перейдите в «Настройки» → «Членство» → «Автоматически», а затем выберите «Связанные группы» для связи. Этот выпадающий список заполняется информацией от провайдера идентификации, поэтому для появления опции хотя бы один член группы должен войти в систему.

Пример настройки

Здесь мы настроим плагин openid-connect для подключения к провайдеру OpenID Connect Google. Это повторяет функциональность, уже существующую в ядре Discourse, но служит доступным примером.

  1. Перейдите на OpenID Connect  |  Sign in with Google  |  Google for Developers и следуйте инструкциям для получения учетных данных OAuth.

  2. На той же странице следуйте инструкциям для добавления URI перенаправления. Он должен быть https://<ваш_форум>/auth/oidc/callback (без завершающего слеша).

  3. Перейдите в настройки вашего сайта Discourse и найдите «openid_connect»

    • openid connect enabled: [x]

    • openid connect discovery document: https://accounts.google.com/.well-known/openid-configuration

    • openid connect client id: <id_клиента>

    • openid connect client secret: <секрет_клиента>

    • openid connect authorize scope: openid email (с пробелом между ними)

  4. Готово. Кнопка «Войти с помощью OpenID Connect» теперь будет входить через Google :tada:. Эти же шаги можно применить к другим провайдерам с минимальными изменениями.

Отладка

В дополнение к параметру verbose_logging, описанному выше, вы можете получить данные о связях OIDC с помощью плагина data-explorer:

SELECT user_id, provider_name, provider_uid
FROM user_associated_accounts
WHERE provider_name = 'oidc'

Или в консоли Rails:

User.find_by_username("david").user_associated_accounts.where(provider_name: 'oidc')

Примечания для конкретных провайдеров

Пожалуйста, не стесняйтесь обновлять этот раздел, если вы обнаружите какие-либо особенности, специфичные для провайдера, связанные с этой интеграцией:

Entra ID (ранее Azure AD)

Добавьте область email и убедитесь, что вы используете документ конфигурации конечной точки версии 2. Например:

https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration
Azure B2C

Подробности URL документа обнаружения можно найти здесь: Web sign in with OpenID Connect - Azure AD B2C | Microsoft Learn

Чтобы заработала отправка писем:

Yahoo
  1. Перейдите на https://developer.yahoo.com/apps и создайте новое приложение.

  2. Введите имя приложения и установите домен обратного вызова в домен вашего форума (например, meta.discourse.org).

  3. В разделе «Разрешения API» выберите Profiles: Read/Write Public and Private. Это единственный известный мне способ получения адреса электронной почты пользователя.

  4. Сохраните приложение.

  5. В настройках OIDC Discourse установите документ обнаружения в:

    https://login.yahoo.com/.well-known/openid-configuration
    
  6. Введите ID клиента и секрет от Yahoo.

  7. Включите плагин OIDC.

AWS Cognito
  1. Перейдите в Cognito и выберите или создайте новый пул пользователей.
  2. Определите приложение в разделе «Клиенты приложений».
  3. Оставьте всё по умолчанию, но измените конфигурацию потоков аутентификации, выбрав только ALLOW_REFRESH_TOKEN_AUTH.
  4. Перейдите в настройки клиента приложения и выберите новое приложение.
  5. Измените URL обратного вызова на https://yoursite.example.com/auth/oidc/callback.
  6. Отметьте только поток предоставления авторизационного кода среди «Разрешенных потоков OAuth».
  7. Отметьте все необходимые области (я отметил все).
Okta
  1. Настройте Discourse с ID клиента и секретом вашего приложения Okta.

  2. Установите URL документа обнаружения в:

    https://{ваше_приложение}.okta.com/.well-known/openid-configuration
    
  3. В Discourse установите openid connect authorize scope в openid email.

:discourse2: Размещено нами? Этот плагин доступен в наших тарифных планах Business и Enterprise. OAuth 2.0 & OpenID Connect Support | Discourse - Civilized Discussion

:spiral_notepad: Нужно автоматизировать регистрацию пользователей? См. Auto-provisioning user accounts when SSO is enabled


  1. токен или полезная нагрузка userinfo ↩︎

  2. из токена или полезной нагрузки userinfo ↩︎

52 лайка
Native SSO with Azure AD
How to setup okta authentication with discourse
Discourse Login using external API
OpenIdAuthenticator plugin fails
Sign in to Discourse using ORCID
Discourse, Keycloak, SAML vs OAuth
OpenID Connect support in selfhosted Discourse instance
How can you connect firebase to discourse?
Keycloak SSO and logout issue
Tutorial for OpenID Connect / Azure AD
OpenID connect plugin
Azure OpenID Connect Authentication Plugin
Installing own gem in plugin
SSO Login page not showing up
Enabling Okta for employees only through OpenID Connect Authentication Plugin
Is "partial" SSO possible?
Auto-sign-in with the OpenId Connect Plugin and AWS Cognito
Official support for Microsoft Azure AD?
CodeBerg support
Availability of OpenID Connect in hosted plans
Can we use the default atlassian id to login to discourse
OpenIdAuthenticator plugin fails
Intergrate Discourse with keycloak
IndieAuth login
Intergrate Discourse with keycloak
Map oidc fields to custom user fields
CSRF problem in development with 'Discourse OpenID Connect' plug-in
Azure B2C SSO to Discourse?
User (patron) getting authorization error message
Memberstack + Webflow + Discourse OpenID Connect
How can add 2 or more discovery documents?
Memberstack + Webflow + Discourse OpenID Connect
Azure AD Authentication and Creation of User Account
Possible to create a Sign in with Ghost plugin for Discourse?
Custom Login Flow: AWS Cognito SSO (via Passwordless Signin) - Is this possible?
Account already in discourse
AAD integration with Discourse
Having trouble setting up AWS Cognito passwordless login
Discourse ID fails to activate on my instance
Restrict Office 365 Login to certain Group
OpenID Connect Plugin not creating new users with AWS Cognito
OIDC users not associating with existing Discourse users
Bundling more popular plugins with Discourse core
OpenID Connect Plugin Refactor (OIDC Implicit Flow)
Availability of OpenID Connect in hosted plans
How to configure the OIDC to set the Username as the email account name or a username like value returned from my auth providers?
Managing group membership via authentication
Failed to bootstrap due to out of memory killer
OAuth connection of discourse
Auto-provisioning user accounts when SSO is enabled
Anyone have a working AWS Cognito configuration w/ ouath2, openid or sso?
SAML Plugin on Self Hosted Discourse
Can I include website analytics in trust data?
Using OpenID Connect with User Flows in Azure B2C
ADFS Authentication
How to set-up Discourse with Atricore Josso CE
Error of Discourse OpenID Connect
How can add 2 or more discovery documents?
./launcher rebuild app fails hard 'bundle exec rake db:migrate' possible issue with github/master repo removal of auth/oath2_authenticator
Removing Yahoo login from Core, and deprecating OpenID 2.0
SSO with TownNews CMS
OpenID Connect Plugin Refactor (OIDC Implicit Flow)
OpenID with line.biz - email in JWT , missing in userinfo

Привет!

Мы используем плагин аутентификации OpenID Connect с установкой Discourse на AWS.
Мы развернули контейнеры Discourse, Discourse Sidekiq и Redis (на базе Bitnami, но, пожалуйста, не выгоняйте меня из сообщества ;)). База данных работает на AWS RDS. Мы используем KeyCloak.

Всё работает.

Однако иногда после перезапуска задачи Discourse на AWS возникает ситуация, когда система считает, что документ обнаружения (Discovery document) находится в кэше, но на самом деле его там нет. При этом она не пытается повторно получить его из KeyCloak:

OIDC Log: Discovery document loaded from cache
OIDC Log: Discovery document is
---
(oidc) Request phase initiated.
(oidc) Authentication failure! openid_connect_discovery_error: OmniAuth::OpenIDConnect::DiscoveryError, Discovery document is missing

В веб-приложении я вижу сообщение: «Не удалось получить конфигурацию от провайдера идентификации. Пожалуйста, попробуйте снова».

Что вы можете посоветовать?

2 лайка

Здравствуйте,

Есть ли способ установить источник аватара пользователя Discourse на поле, указанное в сервисе OpenID?

Редактирование: мы используем Keycloak

1 лайк

Здравствуйте,

У меня есть задача, аналогичная задаче @Tomáš_Guba: я хочу получать значение из пользовательского профиля и использовать его в [пользовательском] поле.

В моём случае у меня есть документ обнаружения с userinfo_endpoint.

Есть ли что-то подобное в плане разработки плагина?

Спасибо

1 лайк

Привет! Мне удалось настроить работу плагина с моим SSO OpenID, но данные (например, имя пользователя, email и другие поля) не передаются в соответствующие поля другой системы…

Думаю, что нужно что-то настроить в поле “openid connect claims”, но я не знаю, как это сделать напрямую. Не могли бы вы привести пример? Вот несколько скриншотов моей конфигурации:
https://imgur.com/gallery/LWvkJUV

1 лайк

Есть ли способ избежать «потери» исходного маршрута при входе в закрытую тему?

Если мы заходим на закрытую страницу и нажимаем одну из кнопок входа на этой странице, то после перенаправления обратно на сайт мы оказываемся на странице категорий.

Привет, @david,

Не могли бы вы посмотреть на проблему, упомянутую в следующем посте? Я хочу использовать плагин OIDC вместо базового OAuth, но сталкиваюсь с той же проблемой — не могу передать параметры в запрос к /authorize. Я указал значение в плагине в формате foo=bar.

Мне не удалось заставить это работать в LinkedIn. Интересно, сталкивался ли кто-нибудь ещё с этим? Я дохожу до входа в LinkedIn после перенаправления туда при нажатии на кнопку «Войти с помощью…» и затем «разрешения» моему приложению использовать мой email из LinkedIn, после чего получаю сообщение: «К сожалению, произошла ошибка при авторизации вашей учётной записи. Пожалуйста, попробуйте снова».

https:/discourse.mysite.com/auth/failure?message=invalid_credentials&origin=https%3A%2F%2Fdiscourse.mysite.com%2F&strategy=oidc

У меня всё ещё возникают проблемы с этим. Я получаю следующую ошибку:

(oidc) Authentication failure! invalid_credentials: OAuth2::Error, invalid_request: A required parameter "client_secret" is missing {"error":"invalid_request","error_description":"A required parameter

Это ошибка omniauth, и, похоже, она связана [возможно] с этим: No longer works with oauth2 gem v2.0+ · Issue #68 · decioferreira/omniauth-linkedin-oauth2 · GitHub

Буду признателен за помощь!

Я получаю следующие ошибки:


(oidc) Ошибка аутентификации! openid_connect_discovery_error: OmniAuth::OpenIDConnect::DiscoveryError, документ обнаружения отсутствует

Лог OIDC: Получение документа обнаружения завершилось ошибкой Faraday::ConnectionFailed FinalDestination: поиск не удался

В настройках плагина «Документ обнаружения OpenID Connect» в Административных настройках указано: https://<auth_provider>/.well-known/openid-configuration. Я могу успешно обратиться к этому URL из контейнера Docker приложения, запущенного с помощью команды Curl, и даже из консоли Rails.

Подскажите, пожалуйста, почему возникают эти ошибки? Из-за этого не получается корректно выполнить интеграцию. Также я нахожусь в интранете и использую корпоративный прокси, если это имеет значение. Как я уже говорил, при включенном прокси в переменных окружения (ENV) контейнера обращение к URL «документа обнаружения OpenID Connect» работает корректно.

1 лайк

2 поста были перенесены в новую тему: Разрешение нескольких источников OIDC

Сообщение было перенесено в новую тему: Переопределение аватаров через OIDC

Привет!

Новый вопрос: обрабатывает ли этот плагин управление сеансами? (Final: OpenID Connect Session Management 1.0).
Я не думаю, что это так, потому что даже если OP отправляет данные session_state, я нигде в коде не вижу, чтобы они сохранялись в виде cookie или подобным образом.

Так что это вопрос/запрос на новую функцию :slight_smile: Это было бы замечательно!

2 лайка

При использовании этого плагина с AWS Cognito для выхода из системы требуется передать параметр client_id в URL выхода. Насколько мне известно, нет возможности добавить дополнительные параметры запроса в URL выхода — верно ли это? Если нет, возможно ли добавить такую функциональность?

Всем привет :wave:t3:

Я написал небольшое расширение для этого плагина (технически в виде темы/компонента), чтобы скрыть кнопку «Войти через OIDC» во всплывающем окне входа, но инициировать процесс входа через OIDC при обращении к специальному URL.

discourse-autooidc.zip (1,0 КБ)

Сценарий использования этой функции — обеспечить безопасный и удобный (автоматический) вход через OAuth для сотрудников нашей компании, не раскрывая публичную ссылку провайдеру OAuth (Authentik в нашем случае, но должно работать и с Authelia, Keycloak, Auth0, Okta и др.) и не надоедая другим пользователям кнопкой входа через OIDC, которую они никогда не смогут или не должны использовать.

Чтобы войти через OIDC, просто обратитесь к адресу https://<ваш-базовый-URL-discourse>/login#autooidc

3 лайка

Возможно, вас заинтересует GitHub - discourse/discourse-hide-auth-method: A theme component which allows hiding a specific login method from the UI, without fully disabling it · GitHub, который выполняет схожую функцию

3 лайка

Keycloak поддерживает Backchannel logout URL:

URL, который инициирует выход клиента при отправке запроса на выход в этот realm (через end_session_endpoint). Если этот параметр опущен, запрос на выход не будет отправлен клиенту в данном случае.

Будет здорово, если этот плагин предоставит какой-либо endpoint, принимающий полезную нагрузку от Keycloak и немедленно выводящий конкретного пользователя из всех сессий. В противном случае, когда мы отключаем пользователя в Keycloak, нам приходится ждать истечения maximum session age (который по умолчанию довольно большой).

Вы также можете завершить все сессии пользователя через административную страницу (например, /admin/-1/system) и нажать кнопку Выйти в верхней части страницы.

Здравствуйте,

Когда загрузка документа обнаружения не удаётся (например, из-за тайм-аута), плагин кэширует ошибку, из-за чего аутентификация становится недоступной на 10 минут. Возможно ли отключить кэширование ошибки, чтобы повторная попытка загрузки произошла раньше?

С уважением

Извините за пинг, но для этого уже есть открытый PR, который можно легко слить, чтобы добавить поддержку PKCE.

@nbianca, я видел, что вы последний коммитер в репозитории, не могли бы вы взглянуть? :folded_hands:

1 лайк