大家好,
我希望改进我们的安全状况,其中一部分意味着我们需要尽可能避免使用敏感凭据。
不幸的是,OIDC 插件需要一个客户端密钥凭据才能访问 /userinfo 端点,并且在我启用它之后,我无法设置我的论坛。
幸运的是,OIDC 规范实际上定义了一种不需要使用任何秘密令牌的方式。
如果我们坚持使用 id_token 流 ,IdP 将向我们发送我们需要的所有信息来验证用户,而无需回溯到 IdP。
这是安全的,因为重定向在 IdP 中配置,我们不必担心承载令牌被转发到错误的目的地。
我已经为 OIDC 插件创建了一个补丁来支持 id_token 流,并在此处提交了一个拉取请求:
main ← DrChat:oidc2
opened 11:06PM - 25 Oct 25 UTC
This significantly refactors this plugin and builds on the new [`omniauth_openid… _connect`](https://github.com/omniauth/omniauth_openid_connect/tree/5ebcad6fb77a96e6b67d9a4f8e7dd04bbf6a35d6) package.
The primary motivation was to eliminate the requirement for a client secret to improve our security posture.
The primary flow for OpenID Connect (`id_token`) will actually transfer all of the information needed by Discourse to verify a user's identity and create an account without the requirement that Discourse reach back out to the IdP (which is what previously required a secret credential).
I have tested this pull request against Azure Active Directory (Entra ID), and it is working properly without a client secret.
Also, just a warning: This is my first foray into Ruby programming. Reviewers beware :)
PR 还不算完全完成,因为它仍然需要单元测试,但它几乎完成了,并且我已经确认它与 Azure AD (Entra ID) 正常工作。
供参考,这是 OIDC 插件的文档:
Summary
Discourse OpenID Connect allows an OpenID Connect provider to be used as an authentication provider for Discourse.
Install Guide
This plugin is bundled with Discourse core. There is no need to install the plugin separately.
Features
The plugin aims to provide a minimal implementation of the specification . Specifically, it supports the “Authorization Code Flow”. To get started, follow the plugin installation instructions , or contact your hosti…
1 个赞
david
(David Taylor)
2025 年10 月 29 日 13:00
2
我认为您所描述的是 OpenID Connect 的"隐式流程" ,它不需要服务器到服务器的通信,因此不需要共享密钥。相反,所有信息都通过 HTTP 重定向传输,并且 ID 令牌使用发现文档中的公钥进行加密验证。
这很好,我认为这是一个有效的特性请求。但它与我们当前的插件非常不同,后者使用"授权码流程" 。此流程使用带有共享密钥的服务器到服务器通信,因此不需要对 id_token 进行加密验证。这在某些方面更简单,但在其他方面更复杂。
重要的是:我们不能仅仅更改插件中的默认实现。使用授权码流程的站点需要继续使用该流程。据我所知,许多身份提供商甚至不支持隐式流程。
因此,我认为这里有两个前进的方向:
我们在 OIDC 插件中添加对“隐式流程”的支持,但将其设置为可选 。我认为我们不太可能接受一个将 openid-connect gem 作为 Discourse 核心依赖项引入的 PR,因此它需要实现在我们当前的策略中。
discourse-lti(学习工具集成)插件可能是一个有用的灵感来源,因为 LTI 协议基于 OIDC 隐式流程。id_token 解码逻辑位于此处
或者
您将隐式流程构建为一个全新的插件。在这种情况下,您可以自由地在实现方面做任何您想做的事情(但您也必须自己维护它)。
david
(David Taylor)
2025 年10 月 29 日 13:19
3
值得注意的是,OIDC“隐式流”会增加 CSRF 攻击和令牌暴露的攻击面:
我认为在某些情况下它仍然是有意义的。但似乎授权码流(Discourse 的默认设置)加上 PKCE(Discourse 中可选)是使用 OIDC 最推荐的方式。
感谢您详细的回复!
我认为在某些情况下仍然有意义。但似乎 PKCE(Discourse 中可选)的授权码流(Discourse 的默认设置)是使用 OIDC 最推荐的方式。
这非常有趣——直到现在我才完全理解 PKCE。根据我对 auth0 文档 的阅读,似乎(在某些配置中)这种流具有隐式流(无客户端密钥)的优点,而没有其任何缺点。
这也许是可行的吗?看起来就像从 /token 端点删除客户端密钥参数一样简单。
最终,我最关心的是消除对客户端密钥的要求
好的 - 使用以下配置可以实现此功能:
"DISCOURSE_OPENID_CONNECT_ENABLED": "true",
"DISCOURSE_OPENID_CONNECT_DISCOVERY_DOCUMENT": "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration",
"DISCOURSE_OPENID_CONNECT_CLIENT_ID": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"DISCOURSE_OPENID_CONNECT_CLIENT_SECRET": "",
"DISCOURSE_OPENID_CONNECT_VERBOSE_LOGGING": "true",
"DISCOURSE_OPENID_CONNECT_USE_PKCE": "true"
以及对代码的以下更改:
diff --git a/plugins/discourse-openid-connect/lib/omniauth_open_id_connect.rb b/plugins/discourse-openid-connect/lib/omniauth_open_id_connect.rb
index 410a88f46dc..e74ee360aae 100644
--- a/plugins/discourse-openid-connect/lib/omniauth_open_id_connect.rb
+++ b/plugins/discourse-openid-connect/lib/omniauth_open_id_connect.rb
@@ -73,6 +73,11 @@ module OmniAuth
)
options[:client_options][:auth_scheme] = :request_body
end
+
+ # If we're using PKCE _and_ there is no client_secret, use the request_body auth_scheme.
+ if options[:pkce] && options[:client_secret].empty?
+ options[:client_options][:auth_scheme] = :request_body
+ end
end
def request_phase
重定向 URI 在 Azure 控制面板中的配置如下: