偶尔的 OAuth 错误

我们正在使用外部 OAuth 进行用户身份验证。用户偶尔会在访问平台时收到 500 错误:错误日志摘要:

Started GET "/auth/oauth2_basic/callback?code=[coderemoved]&state=[stateremoved]" for [IP] at [timestamp]
(oauth2_basic) Setup endpoint detected, running now.
(oauth2_basic) Callback phase initiated.
Faraday::TimeoutError (Timeout::Error)
lib/final_destination/resolver.rb:31:in `block in lookup'
lib/final_destination/resolver.rb:8:in `synchronize'
lib/final_destination/resolver.rb:8:in `lookup'
lib/final_destination/ssrf_detector.rb:127:in `lookup_ips'
lib/final_destination/ssrf_detector.rb:95:in `lookup_and_filter_ips'
lib/final_destination/http.rb:13:in `connect'
lib/middleware/omniauth_bypass_middleware.rb:43:in `call'
lib/middleware/content_security_policy.rb:12:in `call'
lib/middleware/anonymous_cache.rb:387:in `call'
lib/middleware/gtm_script_nonce_injector.rb:10:in `call'
config/initializers/100-quiet_logger.rb:20:in `call'
config/initializers/100-silence_logger.rb:29:in `call'
lib/middleware/enforce_hostname.rb:24:in `call'
lib/middleware/request_tracker.rb:233:in `call'

如果用户只是刷新页面,一切都会正常工作,日志信息如下:

Started GET "/auth/oauth2_basic/callback?code=[coderemoved]&state=[stateremoved]" for [IP] at [timestamp]
(oauth2_basic) Setup endpoint detected, running now.
(oauth2_basic) Callback phase initiated.
Processing by Users::OmniauthCallbacksController#complete as HTML
  Parameters: {"code"=>"[coderemoved]", "state"=>"[stateremoved]", "provider"=>"oauth2_basic"}
Deprecation notice: `SiteSetting.anonymous_posting_min_trust_level` has been deprecated. Please use `SiteSetting.anonymous_posting_allowed_groups` instead. (removal in Discourse 3.3) 
At /var/www/discourse/lib/site_setting_extension.rb:160:in `public_send`
start
Redirected to https://[pageremoved]
Completed 302 Found in 83ms (ActiveRecord: 0.0ms | Allocations: 11138)

很遗憾,没有重现步骤。这种情况似乎发生在用户离开一段时间后再次访问时,但我无法确切证实。有可能自他们上次访问以来平台已升级。
有什么建议或我可以提供其他信息吗?

顶一下。我遇到了完全相同的问题。

超时错误表明存在网络问题。可能只是网络故障。

我曾想过这个问题,但错误出现得太快了,不像是正常行为。我想知道是不是有什么地方的 DNS 查询超时过于激进:

  1. 错误在“resolver.rb”中。
  2. 通过刷新可以暂时修复——这时 DNS 查询会被缓存。
  3. 出于某种完全无法解释的原因,我无法从任何涉及我们自托管 DNS 的 URL 读取 OIDC 发现文档。尽管如此,我仍然可以在 Docker 实例内部手动 curl 到该文件。我已经排除了许多不同的变量,DNS 似乎是唯一共同点。

重要的是,Discourse 服务器能够与 OIDC 服务器通信,即使在出现这种情况时也会失败。从访问日志来看,当失败时有一个请求:

21/Jan/2024:23:10:21 +0000] "POST /application/o/token/ HTTP/1.1" 200 7998 "-" "Faraday v2.9.0"

当成功时有两个请求:

[21/Jan/2024:23:21:03 +0000] "POST /application/o/token/ HTTP/1.1" 200 7998 "-" "Faraday v2.9.0"
[21/Jan/2024:23:21:05 +0000] "GET /application/o/userinfo/ HTTP/1.1" 200 5254 "-" "Faraday v2.9.0"

无论如何,它从不超过 5 秒。我还没有尝试设置一个使用 Cloudflare DNS 的 OIDC 服务器代理,但这将是我的下一步。

普遍的看法是,这总是 DNS。

好吧,这肯定是 DNS 问题。我没有设置代理,而是将我的 OIDC 服务器添加到 Docker 容器的 hosts 文件中,现在似乎可以正常工作了。不过,这是一个脆弱且不理想的解决方案;我认为开发人员需要修复超时问题,使其变得合理。这种情况让我想起了“500 英里邮件”的故事。

你可以在 app.yml 中添加内容,以便在重建时更新 /etc/hosts。你可以参考其他模板中的示例。

有可能,但很少有人遇到麻烦。你的自托管 DNS 服务器有时会过载吗?

我不知道去哪里更改超时设置。我不记得曾经做过。

在我的例子中,IdP 和 Discourse 虚拟机紧挨着,虽然不能完全排除网络问题的可能性,但其他服务都没有遇到问题。