Discourse 包含一个系统,如果遵循非常具体的协议,可以为每个用户生成 API 密钥。此功能有助于应用程序访问 Discourse 实例,而无需涉及版主。
总体描述
从高层次来看:
-
客户端(桌面应用、浏览器插件、移动应用)生成私钥/公钥对和返回 URL
-
客户端重定向到 Discourse 上的一个路由,向 Discourse 提供其公钥
-
Discourse 获得用户使用该应用的批准
-
Discourse 生成一个用户 API 密钥
-
Discourse 使用公钥(包含用户 API 密钥)进行加密的有效载荷重定向回返回 URL
详细信息
用例:
-
代表最终用户轮询 Discourse 站点的桌面应用程序,以获取跨多个站点的通知计数。
-
代表最终用户轮询 Discourse 站点并处理推送通知的移动应用程序
-
为最终用户提供有关各种 Discourse 站点仪表板的 Web 应用程序。
-
与第三方应用程序的自定义集成,这些应用程序将 Discourse 作为通用公司应用的一部分来使用。例如:将 Discourse 社区通知集成到 hopscotch 应用中。
设计:
站点设置
-
allow_user_api_key_scopes:允许用户 API 密钥的访问范围。范围在此处定义。可用的内置范围包括:
read(读取)、write(写入)、message_bus(消息总线)、push(推送)、one_time_password(一次性密码)、notifications(通知)、session_info(会话信息)、bookmarks_calendar(书签日历)、user_status(用户状态)(插件可能会注册其他范围)。 -
user_api_key_allowed_groups:控制哪些组被允许生成用户 API 密钥(默认为管理员、版主和 trust_level_0)
-
allowed_user_api_push_urls:可以是推送通知目标的站点列表
-
allowed_user_api_auth_redirects:用户 API 密钥生成后允许重定向的目标
全局设置
- max_user_api_reqs_per_minute:20
- max_user_api_reqs_per_day:2880
用户体验元素
如果已授予任何用户 API 密钥,Discourse 会在用户页面中显示一个 apps(应用)选项卡。
apps 选项卡将列出:
- 应用程序的名称,例如(“Discourse Notifier”)
- 最后使用日期
- 批准日期
- 已授予的访问范围列表
- 一个 revoke access(撤销访问权限)按钮,以便您可以轻松撤销任何密钥
API 密钥授权 UI
每个密钥都必须由最终用户在一个清楚说明情况的页面中明确授权,例如:
“Discourse Notifier” 正在请求对您的帐户执行以下访问:
- 读取和清除通知
- 读取用户会话信息
- 创建一次性登录令牌
[授权]
API 密钥生成流程
API 只要求用户端进行一次 GET 请求。
https://sitename.com/user-api-key/new
从 Discourse 2.1 开始,如果用户 API 密钥长时间未被使用,它们现在会自动过期。默认情况下,站点设置:
revoke user api keys unused days设置为 180
参数:
- auth_redirect:重定向回生成的令牌的 URL
- application_name:发起请求的应用程序的名称(将显示在用户帐户的“Apps”选项卡中)
- client_id:客户端的唯一标识符
- nonce:客户端生成的唯一随机数。它将在加密的有效载荷中被回显,以便客户端可以验证响应的真实性
- scopes:允许密钥的访问范围的逗号分隔列表,请参阅
allow user api key scopes查看可用范围的完整列表 - push_url:推送通知的目标 URL(如果作用域中包含
push或notifications,则为必需且有效) - public_key:客户端生成的密钥对的公有部分
- padding(可选):用于加密有效载荷的 RSA 填充模式。可接受的值为
pkcs1(默认)或oaep。推荐新应用程序使用 OAEP。
调用 /user-api-key/new 并带有正确参数后,可能会发生两件事:
- 如果用户未登录,我们将重定向到登录(登录后我们将恢复授权)
- 用户登录后,将向他们展示授权 UI
授权被允许后,系统将重定向回 auth_redirect 中定义的 URL,并包含一个加密的 payload 参数,其中包含一个 JSON 对象,其中包含生成的用户 API 密钥(key)、nonce、推送状态(push)和 API 版本(api)。如果请求了 one_time_password 作用域,还会包含一个单独的加密的 oneTimePassword 查询参数。出于额外的安全考虑,client_id 不会被回显。
检查 API 版本
Discourse 中的使用密钥 API 是版本化的。客户端可以通过向 https://sitename.com/user-api-key/new 发出 HEAD 请求来检查 Discourse 站点的 API 版本。响应将包含一个名为 Auth-Api-Version 的标头,其中包含站点 API 的版本号。
使用 API
使用客户端 API 将与当前的管理 API 略有不同。
客户端可以指定 2 个标头:
User-Api-Key(必需):生成的密钥
和
User-Api-Client-Id(可选):提供此标头以更新数据库中此 api_key 存储的“客户端 ID”。
指定这些标头后,客户端就可以像往常一样对 API 执行请求。
生成一次性登录密码
从 4 版开始,API 包含一个特殊的作用域:one_time_password 作用域,它允许客户端使用用户 API 密钥生成一次性密码。如果客户端在生成 API 密钥时包含此作用域(遵循上述步骤),则加密的 oneTimePassword 将作为单独的查询参数包含在重定向回客户端的链接中。
或者,客户端可以向 /user-api-key/otp 发出 GET 请求,并附带以下参数:
- auth_redirect
- application_name
- public_key
- padding(可选)
并带有 User-Api-Key 标头。
此请求将重定向到 Discourse 中的一个屏幕,该屏幕将要求用户允许应用程序访问该站点。如果用户批准,该站点将重定向回 auth_redirect 中定义的 URL,并包含一个加密的 oneTimePassword 参数,其中包含一个一次性密码,客户端可以使用该密码通过请求 https://sitename.com/session/otp/ONE-TIME-PASSWORD 登录到该站点。(该一次性密码仅有效 10 分钟。)
撤销 API 密钥
要撤销 API 密钥,请向 /user-api-key/revoke 发送带有 User-Api-Key 标头且不带任何参数的 POST 请求。
上次由 @SaraDev 于 2022-07-13T00:00:00Z 审阅

