Discourse OpenID Connect (OIDC)

:discourse2: 摘要 Discourse OpenID Connect 允许将 OpenID Connect 提供商用作 Discourse 的身份验证提供商。
:open_book: 安装指南 该插件已随 Discourse 核心捆绑。无需单独安装该插件。

功能

该插件旨在提供 规范 的最小化实现。具体来说,它支持“授权码流程”。要开始使用,请遵循 插件安装说明,或联系您的托管服务提供商。

我们的 oauth2-basic 插件可用于连接某些 OpenID Connect 提供商(OpenID Connect 基于 OAuth2)。但是,此插件所需的配置更少,并且如果无法使用 JSON API,还可以利用 JWT“ID Token”。

配置将通过 OpenID Connect 发现文档 自动完成。根据规范,该文档应位于 <issuer domain>/.well-known/openid-configuration,但 Discourse 支持任何路径以允许非合规的实现(例如 Azure B2C)。发现文档会被缓存 10 分钟,以提高高流量站点的性能。

如果发现文档包含 userinfo_endpoint 参数,则插件将使用该端点收集用户元数据。如果没有,插件将从令牌端点提供的 id_token(一个 JWT)中提取元数据。插件 不会 验证 JWT 签名的真实性,因为这会显著增加复杂性。这一决定得到了 规范 的支持:

如果 ID Token 是通过客户端与令牌端点之间的直接通信接收的(在本流程中正是如此),则可以使用 TLS 服务器验证来验证颁发者,而无需检查令牌签名。

对于支持使用 “带代码交换证明密钥的授权码流程” 进行无密钥授权的身份提供商,应启用 PKCE,并且可以省略 client_secret 配置。

配置

基本配置选项

  • openid_connect_enabled: 启用 OpenID Connect 身份验证

  • openid_connect_discovery_document: OpenID Connect 发现文档 URL。通常位于 https://your.domain/.well-known/openid-configuration

  • openid_connect_client_id: OpenID Connect 客户端 ID

  • 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: 发送到授权端点的作用域。必须包含 ‘openid’

  • openid_connect_use_pkce: 为 OpenID Connect 身份验证启用代码交换证明密钥 (PKCE)。

  • openid_connect_verbose_logging: 将详细的 openid-connect 身份验证信息记录到 /logs。在正常使用期间请保持禁用状态。

高级配置选项

  • openid_connect_token_scope: 请求令牌端点时发送的作用域。官方规范不要求此项。

  • openid_connect_error_redirects: 如果回调 error_reason 包含第一个参数,用户将被重定向到第二个参数中的 URL。用于发送用户输入响应错误的特殊实现(例如 Azure B2C)。

  • openid_connect_allow_association_change: 允许用户断开并重新连接其 Discourse 账户与 OpenID Connect 提供商的连接。

  • openid_connect_groups_claim: OIDC 响应[1] 中包含用户组(字符串数组)的声明名称。留空以禁用组同步。请参阅下面的 组同步

  • openid_connect_user_field_mappings: OIDC 声明[2] 的映射,这些声明将存储在 Discourse 用户字段中。用户字段通过其数字 ID 标识,该 ID 可通过管理面板编辑时 URL 中找到。

组同步

该插件可以自动将 OpenID Connect 提供商的组成员关系同步到 Discourse 组。每次登录时,插件都会读取 OIDC 令牌中配置的声明,并相应地更新用户的组成员关系。要启用组同步:

  1. 配置您的身份提供商,使其在其中一个声明中返回组数组。这必须是一个字符串数组。

  2. openid_connect_groups_claim 设置为 OIDC 令牌中包含用户组的声明名称(例如 cognito:groups)。设置后,这将开始将信息同步到 Discourse 的“关联组”系统。

  3. 找到您想要链接的 Discourse 组。前往“设置” → “成员资格” → “自动”,然后选择要关联的关联组。此下拉列表由身份提供商的信息填充,因此至少需要一名组成员登录才能出现选项。

示例设置

在此,我们将设置 openid-connect 插件以连接到 Google 的 OpenID Connect 提供商。这复制了 Discourse 核心中已存在的功能,但作为一个易于理解的示例。

  1. 访问 OpenID Connect  |  Sign in with Google  |  Google for Developers 并按照说明获取 OAuth 凭证。

  2. 在同一页面上,按照说明添加重定向 URI。这应该是 https://<your_forum>/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: <client-id>

    • openid connect client secret: <client-secret>

    • openid connect authorize scope: openid email(中间用空格分隔)

  4. 完成。现在“使用 OpenID Connect 登录”按钮将使用 Google 登录 :tada:。这些相同的步骤可以应用于其他提供商,只需进行极小的更改。

调试

除了上述 verbose_logging 设置外,您还可以使用 data-explorer 插件访问有关 OIDC 关联的数据:

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. 在 Discourse OIDC 设置中,将发现文档设置为

    https://login.yahoo.com/.well-known/openid-configuration
    
  6. 输入来自 Yahoo 的客户端 ID 和密钥

  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. 使用您的 Okta 应用客户端 ID 和密钥配置 Discourse

  2. 将发现文档 URL 设置为

    https://{your-app}.okta.com/.well-known/openid-configuration
    
  3. 在 Discourse 中,将 openid connect authorize scope 设置为 openid email

:discourse2: 由我们托管?此插件可在我们的商业版和企业版计划中使用。OAuth 2.0 & OpenID Connect Support | Discourse - Civilized Discussion


  1. 令牌或用户信息负载 ↩︎

  2. 来自令牌或用户信息负载 ↩︎

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

您好,

我们正在 AWS 上的 Discourse 安装中使用 OpenID Connect Authentication Plugin。
我们已经部署了 Discourse、Discourse Sidekiq 和 Redis 容器(基于 Bitnami,但请不要赶我走 ;))。数据库运行在 AWS RDS 上。我们使用 KeyCloak。

一切都在运行。

但有时在重启 Discourse AWS 任务后,会出现这种情况:它认为它在缓存中有发现文档,但实际上那里没有文档。而且它不会尝试从 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 的类似:我想从用户配置文件的自定义条目中获取值,并在 [custom] 用户字段中使用它。

就我个人而言,我有一个包含 userinfo_endpoint 的发现文档。

插件路线图中是否有类似的功能?

谢谢

1 个赞

您好,我设法让插件与我的SSO openID协同工作,但它没有在其他系统的用户名字段或电子邮件等字段中填入信息……

我想我应该在“openid connect claims”字段中进行一些配置,但我不知道如何直接配置该字段。有人能给我举个例子吗?这是我项目的一些截图:
https://imgur.com/gallery/LWvkJUV

1 个赞

登录私人帖子时,是否有办法避免“丢失”原始路线?

如果我们访问一个私人页面并点击该页面上的任一登录按钮,当重定向回网站时,我们会最终停留在分类页面。

您好 @david

您能否查看帖子中提到的问题?我想在 OAuth 的基础上使用 OIDC 插件。但我遇到了同样的问题——无法将参数传递给 /authorize 请求。我以 foo=bar 的格式将值放入插件中。

我无法在 LinkedIn 上让它正常工作。有人遇到过这种情况吗?当我点击“使用…登录”按钮并“允许”我的应用程序使用我的 LinkedIn 电子邮件后,我会被重定向到 LinkedIn 并成功登录,然后出现“抱歉,授权您的帐户时出错。请重试。”的提示。

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

我仍然对此有问题。我收到以下错误:

(oidc) 身份验证失败!invalid_credentials: OAuth2::Error, invalid_request: 缺少必需的参数“client_secret” {“error”:“invalid_request”,“error_description”:“必需的参数

这是 omniauth 错误,似乎与此有关 [可能]: No longer works with oauth2 gem v2.0+ · Issue #68 · decioferreira/omniauth-linkedin-oauth2 · GitHub

非常感谢您的帮助!

我收到以下错误:

(oidc) 身份验证失败!openid_connect_discovery_error: OmniAuth::OpenIDConnect::DiscoveryError, Discovery document is missing

OIDC 日志:获取发现文档时引发错误 Faraday::ConnectionFailed FinalDestination: lookup failed

我在管理员设置中将插件设置“openid connect discovery document”设置为:https://<auth_provider>/.well-known/openid-configuration,并且我可以在运行的应用程序 Docker 容器中使用 Curl 命令甚至在 Rails 控制台中成功访问它。

有什么想法为什么我会收到这些错误吗?因为这个无法正确集成。另外,我位于内网,并使用公司代理,如果这对您有帮助的话。就像我说的,在容器的环境变量中启用代理后,我可以正确访问“openid connect discovery document”网址。

1 个赞

2 篇帖子已拆分到一个新主题:允许多个 OIDC 源

帖子已拆分为新主题:使用 OIDC 覆盖头像

您好!

新问题:此插件是否处理会话管理?(https://openid.net/specs/openid-connect-session-1_0.html)。
我认为不是,因为即使 OP 发送了 session_state 数据,我在代码中也看不到任何将其存储为 cookie 或类似内容的地方。

所以这是一个问题/功能请求 :slight_smile: 这将是极好的!

2 个赞

当使用此插件和 AWS Cognito 时,要注销,Cognito 要求将 client_id 参数传递到注销 URL。据我所知,没有办法向注销 URL 添加其他查询参数——是这样吗?如果不是,是否可以添加此功能?

嘿,各位 :wave:t3:

我为这个插件写了一个小扩展(技术上是以主题/组件的形式),用于隐藏登录弹出窗口中的“通过 OIDC 登录”按钮,但可以通过访问特殊 URL 来启动通过 OIDC 的登录流程。

discourse-autooidc.zip (1.0 KB)

此功能用例是为我们公司的成员提供安全便捷(自动)的 OAuth 登录,而无需公开指向 OAuth 提供商(在我们的例子中是 Authentik,但也应该适用于 Authelia、Keycloak、Auth0、Okta 等)的链接,并且不会打扰所有其他永远无法或不应使用通过 OIDC 登录按钮的用户。

要通过 OIDC 登录,只需调用 https://<your-discourse-base-url>/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 感兴趣,它的功能与之类似

3 个赞

Keycloak 支持 Backchannel logout URL

当注销请求发送到此领域(通过 end_session_endpoint)时,将导致客户端自行注销的 URL。如果省略,在这种情况下将不会向客户端发送注销请求。

如果此插件公开某个端点,接受来自 Keycloak 的有效负载并立即将会话中的某个用户注销,那就太好了。否则,当我们在 Keycloak 中禁用用户时,我们必须等待 maximum session age(默认值相当大)。

您也可以通过用户的管理页面(例如 /admin/-1/system)将他们从所有会话中注销,然后点击页面顶部的 Log Out 按钮。

您好,

当发现文档获取失败时(例如,发生超时),插件会缓存错误,这意味着身份验证在 10 分钟内不可用。是否可以不缓存错误,以便更早地重试获取?

此致

抱歉打扰,但有一个针对此的开放 PR,合并它以添加 PKCE 支持应该很容易。

@nbianca 我看到您是该存储库的最新提交者,您能看一下吗?:folded_hands:

1 个赞