如果遵循非常特定的协议,Discourse 包含一个为每个用户生成 API 密钥的系统。此功能促进了“应用程序”对 Discourse 实例的访问,而无需管理员介入。
高层描述
从高层来看:
-
客户端(桌面应用程序、浏览器插件、移动应用程序)生成私钥/公钥对和返回 URL
-
客户端重定向到 Discourse 上的路由,向 Discourse 提供其公钥
-
Discourse 获得用户使用应用程序的批准
-
Discourse 生成用户 API 密钥
-
Discourse 重定向回返回 URL,并使用包含用户 API 密钥的公钥加密有效负载
详细信息
用例:
-
代表最终用户轮询 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:50
- max_user_api_reqs_per_day:4000
UX 元素
如果已授予任何用户 API 密钥,Discourse 会在用户页面中显示应用程序选项卡。
应用程序选项卡将列出:
- 应用程序名称,例如:(“Discourse Notifier”)
- 上次使用日期
- 批准日期
- 已授予的访问范围列表
- 撤销访问按钮,以便您可以轻松撤销任何密钥
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:发出请求的应用程序名称(将显示在用户账户的应用程序选项卡中)
- client_id:客户端的唯一标识符
- nonce:由客户端生成的唯一 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 将 somewhat 不同于当前的管理员 API。
客户端可以指定 2 个标头:
User-Api-Key(必需):生成的密钥
和
User-Api-Client-Id(可选):提供此以更新数据库中为此 api_key 存储的 ‘client 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 审核
