我正在尝试设置 discourse-oauth2-basic 插件,以便我们的用户可以通过 NeonCRM 创建并存储的账户凭据登录 Discourse 论坛。
一位 NeonCRM 技术支持人员向我解释,我可以使用以下格式手动创建授权 URL:
https://{{组织 ID}}.z2systems.com/np/oauth/auth?response_type=code&client_id={{客户端 ID}}&redirect_uri={{重定向 URL}}
在 Discourse 中,我为该插件设置了以下参数:
oauth2 客户端 ID:MY-CLIENT-ID
oauth2 客户端密钥:MY-CLIENT-SECRET
oauth2 授权 URL:https://MY-NEON-ID.z2systems.com/np/oauth/auth
oauth2 令牌 URL:https://www.z2systems.com/np/oauth/token
因此,我手动创建了以下 URL(已做脱敏处理):
https://MY-NEON-ID.z2systems.com/np/oauth/auth?response_type=code&client_id=MY-CLIENT-ID&redirect_uri=https://MY-FORUM.COM/auth/oauth2_basic/callback
当我在浏览器中访问该 URL 时,出现了一个 Discourse 页面,显示如下消息:
我的日志显示:
(oauth2_basic) 认证失败!csrf_detected: OmniAuth::Strategies::OAuth2::CallbackError, csrf_detected | 检测到 CSRF
这是为什么?
所以,如果我改用这个 URL:
https://MY-NEON-ID.z2systems.com/np/oauth/auth?response_type=code&client_id=MY-CLIENT-ID&redirect_uri=https://MY-FORUM.COM/
(我移除了 redirect_uri 末尾的回调部分)
我确实可以到达 NeonCRM 登录页面,输入测试用户凭据并登录后,会被重定向到 MY-FORUM.COM。但一旦到达那里,我并没有被登录。如果我点击页面顶部的“登录”按钮,然后点击灰色的“使用 OAuth2 登录”按钮,会弹出一个新窗口,显示以下消息:
同时,我的日志中出现了两个错误:
ArgumentError (Invalid URI: )
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/excon-0.64.0/lib/excon.rb:126:in `new’
以及
Failed to handle exception in exception app middleware : Invalid URI:
Falco
(Falco)
8
这个 redirect_uri 是错误的。您需要正确设置它,流程才能正常工作。
在插件文档中,这是 基本设置 中的第一项。
NeonCRM 也在 其文档 中说明了如何设置它。
感谢 @Falco!
我确实尝试将 redirect_uri 设置为:
https://MY-FORUM.COM/auth/oauth2_basic/callback
但这没有生效,请查看我的原始帖子(我刚刚编辑过,使其更清晰,如果您错过了,抱歉)。
@Falco,我找到了启用 force_https 的说明,并将其设置为 true。
但依然出现相同的错误。
我已经按照 NeonCRM 的建议,将小部件集成到了论坛顶部(如果您愿意,也可以自行尝试):
https://forum.efao.ca/
当我使用该小部件时,得到了与最初帖子中相同的结果:
(oauth2_basic) 认证失败!csrf_detected: OmniAuth::Strategies::OAuth2::CallbackError, csrf_detected | CSRF 检测到
david
(David Taylor)
16
我们在 oauth2 插件中使用 Excon 的唯一位置如下:
你的 oauth2_user_json_url 设置的是什么?我怀疑它是空的。如果是这样,你还应该禁用 oauth2_fetch_user_details,这样 Discourse 就不会尝试访问一个空 URL。
@david,确实为空。
我不知道该将 oauth2_user_json_url 设置为什么。不幸的是,我尝试通过 NeonCRM 的技术支持来弄清楚这个问题,但运气不佳,未能成功。
如果我尝试禁用它,系统会提示我需要设置 oauth2 callback user id path,但如上所述,我不知道该值应该是什么。
david
(David Taylor)
18
我没有 NeonCRM 的安装环境来测试,但我觉得将其设置为 access_token 应该可以生效。你能试试吗?
来自 Falco 在上面链接的文档:
同样的错误:
(oauth2_basic) 认证失败!csrf_detected: OmniAuth::Strategies::OAuth2::CallbackError, csrf_detected | 检测到 CSRF
回溯:
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/logster-2.3.2/lib/logster/logger.rb:110:in `report_to_store'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/logster-2.3.2/lib/logster/logger.rb:101:in `add_with_opts'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/logster-2.3.2/lib/logster/logger.rb:52:in `add'
/usr/local/lib/ruby/2.6.0/logger.rb:543:in `error'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:163:in `log'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:486:in `fail!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-oauth2-1.6.0/lib/omniauth/strategies/oauth2.rb:71:in `callback_phase'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:238:in `callback_call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:189:in `call!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:169:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:192:in `call!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:169:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:192:in `call!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:169:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:192:in `call!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:169:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:192:in `call!'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/strategy.rb:169:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/omniauth-1.9.0/lib/omniauth/builder.rb:64:in `call'
/var/www/discourse/lib/middleware/omniauth_bypass_middleware.rb:30:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/tempfile_reaper.rb:15:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/conditional_get.rb:25:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/head.rb:12:in `call'
/var/www/discourse/lib/content_security_policy/middleware.rb:12:in `call'
/var/www/discourse/lib/middleware/anonymous_cache.rb:218:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/session/abstract/id.rb:232:in `context'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/session/abstract/id.rb:226:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/cookies.rb:670:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/callbacks.rb:28:in `block in call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/activesupport-5.2.3/lib/active_support/callbacks.rb:98:in `run_callbacks'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/callbacks.rb:26:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/debug_exceptions.rb:61:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/logster-2.3.2/lib/logster/middleware/reporter.rb:43:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-5.2.3/lib/rails/rack/logger.rb:38:in `call_app'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-5.2.3/lib/rails/rack/logger.rb:28:in `call'
/var/www/discourse/config/initializers/100-quiet_logger.rb:18:in `call'
/var/www/discourse/config/initializers/100-silence_logger.rb:31:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/request_id.rb:27:in `call'
/var/www/discourse/lib/middleware/enforce_hostname.rb:17:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/method_override.rb:22:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/executor.rb:14:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/sendfile.rb:111:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-mini-profiler-1.1.0/lib/mini_profiler/profiler.rb:184:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/message_bus-2.2.0/lib/message_bus/rack/middleware.rb:57:in `call'
/var/www/discourse/lib/middleware/request_tracker.rb:163:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-5.2.3/lib/rails/engine.rb:524:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-5.2.3/lib/rails/railtie.rb:190:in `public_send'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/railties-5.2.3/lib/rails/railtie.rb:190:in `method_missing'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/urlmap.rb:68:in `block in call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/urlmap.rb:53:in `each'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-2.0.7/lib/rack/urlmap.rb:53:in `call'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/unicorn-5.5.1/lib/unicorn/http_server.rb:605:in `process_client'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/unicorn-5.5.1/lib/unicorn/http_server.rb:700:in `worker_loop'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/unicorn-5.5.1/lib/unicorn/http_server.rb:548:in `spawn_missing_workers'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/unicorn-5.5.1/lib/unicorn/http_server.rb:144:in `start'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/unicorn-5.5.1/bin/unicorn:128:in `<top (required)>'
/var/www/discourse/vendor/bundle/ruby/2.6.0/bin/unicorn:23:in `load'
/var/www/discourse/vendor/bundle/ruby/2.6.0/bin/unicorn:23:in `<main>'
david
(David Taylor)
20
有意思……回溯信息显示该错误来自 OAuth2 库的 这一部分。这意味着 state 参数未能正确匹配。
为了确认,这个错误是来自 您的生产站点 吗?我尝试登录该站点,从我的角度来看,state 参数似乎传递正常。
这表明问题出在服务器端。您的站点是如何托管的?您是否遵循了我们的 标准安装流程?
另外,@david,我不确定这是否相关,但我在我们的日志中也看到了这条单独的条目:
Job 异常:SSL_connect returned=1 errno=0 state=error: 证书验证失败(自签名证书)
我们使用 Let’sEncrypt 作为我们的 SSL 证书。
是的,forum.efao.ca 是我们的生产站点。我们托管在 Digital Ocean 上,并且是使用标准流程安装的。
/usr/local/lib/ruby/2.6.0/net/protocol.rb:44:in `connect_nonblock'
/usr/local/lib/ruby/2.6.0/net/protocol.rb:44:in `ssl_socket_connect'
/usr/local/lib/ruby/2.6.0/net/pop.rb:553:in `do_start'
/usr/local/lib/ruby/2.6.0/net/pop.rb:531:in `start'
/var/www/discourse/app/jobs/scheduled/poll_mailbox.rb:43:in `poll_pop3'
/var/www/discourse/app/jobs/scheduled/poll_mailbox.rb:18:in `execute'
/var/www/discourse/app/jobs/base.rb:232:in `block (2 levels) in perform'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rails_multisite-2.0.7/lib/rails_multisite/connection_management.rb:63:in `with_connection'
/var/www/discourse/app/jobs/base.rb:221:in `block in perform'
/var/www/discourse/app/jobs/base.rb:217:in `each'
/var/www/discourse/app/jobs/base.rb:217:in `perform'
/var/www/discourse/app/jobs/base.rb:279:in `perform'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/mini_scheduler-0.11.0/lib/mini_scheduler/manager.rb:83:in `process_queue'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/mini_scheduler-0.11.0/lib/mini_scheduler/manager.rb:34:in `block in initialize'
david
(David Taylor)
25
恐怕如果没有服务器访问权限,我无法进行更多诊断来定位问题。我们有很多用户在使用 oauth2 插件时并未遇到问题,因此我认为这很可能是某处的配置问题。唯一可能有帮助的方法是升级到 Discourse 的最新版本,而不是使用稳定分支。
也许社区中的其他人会介入,但如果没有,你可以在 Marketplace 频道寻求帮助,或许会有所收获。