跳过“授权应用程序访问”

我们使用 Discourse 作为协作工具,并拥有另一个用于搜索文档的应用 Datashare。我们希望将关于文档的评论集成到 Discourse 中。两者都在我们的基础设施内使用外部 SSO/OAuth 提供商。

我们使用用户 API 密钥来连接这两个应用,以便它们能够通信。这可以正常工作,但我们不得不点击“授权应用访问”表单,而我们希望避免这一操作,因为我们的环境是基于 OAuth 的可信环境。

是否有办法跳过或绕过这个“授权”访问步骤,直接进入用户 API 密钥的创建流程,从而不显示该页面,让用户无需执行这一额外步骤?我们是否可以在请求中提供某个参数来绕过此步骤?

我们尝试先调用 UserApiKeysController.create(而不是 UserApiKeysController.new),但遇到了 CSRF 错误。因此,我们尝试跳过令牌验证,如下所示:

class UserApiKeysController < ApplicationController
  skip_before_action :verify_authenticity_token
end

但这也不起作用。

您是否有其他实现方式?

提前感谢。

欢迎加入,Bruno,很高兴你来到这里 :slight_smile: 也许 @david@blake 对此有一些想法。

我可以肯定地说,这并不是正确的做法。你已经在用插件了吗,还是仅通过 HTTP 进行交互?

如果你正在使用插件,在大多数情况下,你不应该与 app/controllers/ 中的实例进行交互。

如果你通过 HTTP 进行交互,并且使用的是服务器到服务器的通信,那么使用由管理员创建的 API 密钥会是更好的选择。

用户 API 旨在用于客户端到服务器的通信,在这种场景下,无法在客户端层面提供代码完整性保障。

是的,我们计划开发一个 Discourse 插件,我们的 JS 应用将仅通过 HTTP 请求进行交互。
我们希望避免开发服务器对服务器的通信(例如使用管理员 API 密钥),以尽量减少组件之间的耦合。

我理解理想情况下我们不应直接修改 Discourse 的控制器,但同时,确实有很多方法似乎被设计为可被重写(模板方法模式及其他扩展点),而且据我们目前所见,许多插件确实是这样做的。

那么,正确的做法是什么呢?

如果你正在编写一个插件,应该在插件挂载的控制器中开发新的路由,直接执行你需要的任务。这些路由可以共享一个 before_action,用于设置 Access-Control-Allow-{Origin, Headers, Credentials} 响应头(如果 Origin 请求头中的域名在你的应用允许运行的域名列表中,则将其回显)。

这样,你的 JavaScript 代码只需调用 fetch(..., { credentials: "include", ...}),完全不需要 API 密钥。

感谢 @riking,当我们在导航器中拥有 Discourse 的开放会话时,这确实有效。

由于我们设置了 SiteSetting.enable_local_logins = false 且仅使用 OAuth 一种认证机制,我们可以通过手动访问 http://discourse_site/login 来发起新会话。浏览器会跟随重定向跳转到我们的 OAuth 提供商,然后再重定向回 Discourse。这正是调用 /user-api-key/new 时在后台发生的情况。

那么,如果当前没有会话,我们如何从应用程序中编程方式发起新的 Discourse 会话呢?