在 Discourse 中使用 API 实现 Apple 登录

您好,我正在使用 Apple 构建 Discourse 登录 API。我已经安装了插件并遵循了 Discourse Apple Authentication 的说明。在使用 Apple 帐户登录 Discourse 网站时,它工作正常。

在检查了 Apple 登录的 Web 流程后,我注意到它会重定向到 Apple 的登录页面,在成功登录后获取 Apple 生成的代码,然后重定向到:

POST {{discourse_host}}/auth/apple/callback,参数为 state:{state}, code:{code from Apple}

之后,它会重定向到 GET {{discourse_host}}/auth/apple/callback?code={{code from Apple}}&state={state},生成一个将在 Discourse API 中使用的新 cookie。

根据此流程,我期望在调用 /auth/apple/callback 后会生成一个新的 cookie。

但是,当我尝试调用 API 时,会显示错误 Authorization timed out, or you have switched browsers. Please try again.

因此,我再次尝试使用 Apple 生成的新代码,但仍然收到相同的错误。

当我检查日志时,它显示:

Started GET "/auth/apple/callback?code=c32f105b5084d42b8bd3e7051873ddb55.0.rrzxz.pChPU9zGlXIHHhgEXLiA5g&state=fbi3bbboud" for
(apple) Setup endpoint detected, running now.
(apple) Callback phase initiated.
(apple) Authentication failure! csrf_detected: OmniAuth::Strategies::OAuth2::CallbackError, csrf_detected | CSRF detected
Started GET "/auth/failure?message=csrf_detected&strategy=apple" for 123.253.233.16 at 2023-11-27 06:10:28 +0000
Processing by Users::OmniauthCallbacksController#failure as HTML
  Parameters: {"message"=>"csrf_detected", "strategy"=>"apple"}
  Rendered users/omniauth_callbacks/failure.html.erb within layouts/no_ember (Duration: 4.1ms | Allocations: 17)
  Rendered layout layouts/no_ember.html.erb (Duration: 57.5ms | Allocations: 2882)

Message (47 copies reported)

(apple) Authentication failure! csrf_detected: OmniAuth::Strategies::OAuth2::CallbackError, csrf_detected | CSRF detected

Backtrace

/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/omniauth-1.9.2/lib/omniauth/strategy.rb:163:in `log'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/omniauth-1.9.2/lib/omniauth/strategy.rb:486:in `fail!'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/omniauth-oauth2-1.7.3/lib/omniauth/strategies/oauth2.rb:87:in `callback_phase'
/var/www/discourse/plugins/discourse-apple-auth/lib/omniauth_apple.rb:60:in `callback_phase'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/omniauth-1.9.2/lib/omniauth/strategy.rb:238:in `callback_call'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/omniauth-1.9.2/lib/omniauth/strategy.rb:189:in `call!'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/omniauth-1.9.2/lib/omniauth/strategy.rb:169:in `call'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/omniauth-1.9.2/lib/omniauth/strategy.rb:192:in `call!'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/omniauth-1.9.2/lib/omniauth/strategy.rb:169:in `call'
/var/www/discourse/vendor/bundle/ruby/3.2.0/gems/omniauth-1.9.2/lib/omniauth/strategy.rb:192:in `call!'

所以我想问一下,使用 Discourse Apple 登录的 API 方向是否正确,以及如何解决 csrf_detected 错误。

Apple 身份验证(实际上,Discourse 中的所有其他身份验证方法)并非设计为通过 API 使用。它们应由最终用户在受支持的浏览器中直接使用。

您在这里试图解决什么问题?也许我们可以找到一个替代解决方案?

1 个赞

你好 @david,感谢你的回复。我想在这里实现的是创建一个用于 Apple 登录的 API,供移动应用程序访问 Discourse API。

对于使用 Discourse API 使用电子邮件和密码登录,使用以下两个 Discourse API 可以正常工作:

  1. {{discourse_host}}/session/csrf.json:此 API 返回一个 cookie 和 CSRF 代码,将用于使用下一个 API 进行登录。
  2. {{discourse_host}}/session:此 API 返回一个新 cookie,可用于访问其他 Discourse API。
Csrf API

Session

我希望它类似于 Discourse 中的 Apple 登录,即我向 Discourse API 发出请求以生成 _t cookie。

你好@david,我的问题有解决方案吗?

恐怕没有简单的答案。身份验证 API(例如此类)专门设计用于避免在没有用户在网络上进行实际交互的情况下触发它们。

对于您的用例,更常见的解决方案是使用用户 API 密钥系统。这将允许 Discourse 处理 100% 的身份验证逻辑,并为您的应用程序提供一些每个用户的 API 密钥。该策略应该比尝试“伪造”用户会话更加健壮。

1 个赞