angus
(Angus McLeod)
2024 年6 月 20 日 16:01
1
我正在考虑是否允许 用户 API 密钥 客户端注册有效的 auth_redirect 以用于密钥创建。
当前功能
目前,用户 API 密钥重定向必须由托管站点在站点设置 allowed_user_api_auth_redirects 中注册。任何随密钥创建请求发送的 auth_redirect 都会与该站点设置列表进行检查(参见此处 )。这是一个合理的保护措施,可以避免开放重定向(这会带来各种安全风险)。
根本原因
考虑此问题的根本原因是 ActivityPub 插件的用户授权功能。这允许用户证明他们对 ActivityPub 参与者的所有权,以便该参与者的活动可以与他们在给定实例上的帐户相关联。这就是它的样子:
目前这适用于 Mastodon,因为每个 Mastodon 服务器都是一个 OAuth 提供商,允许以编程方式创建 OAuth 客户端。流程如下:
用户确定其帐户所在的 Mastodon 域。
如果是首次在该域上授权,插件会在该 Mastodon 服务器上创建一个 OAuth 应用,注册其重定向并获取 OAuth 流程的客户端凭据。
插件使用在 2 中创建(或之前创建)的 OAuth 应用与用户执行 OAuth 流程。
目标是使用 Discourse 的用户 API 密钥实现类似的功能。这已在此 PR 中实现:
main ← angusmcleod:add_discourse_to_discourse_verification
opened 08:09AM - 01 May 24 UTC
@pmusaraj This is ready to go once https://github.com/discourse/discourse-activi… ty-pub/pull/84 is merged.
- Authorizations now have a dedicated model and table (existing mastodon authorizations will be migrated)
- Discourse actor authorizations are now supported.
- The interface in user preferences has been improved.
### Notes
To authorize a remote Discourse user, the ActivityPub auth redirect for the user's domain has to be in the site setting `allowed user api auth redirects`:
```
[url]/ap/auth/redirect/discourse
```
For example:
```
https://meta.discourse.org/ap/auth/redirect/discourse
```
此流程要求托管站点已将客户端的域或重定向添加到 allowed_user_api_auth_redirects。
可能的更改
我目前正在考虑向 discourse/discourse 提交一个 PR,该 PR 将执行以下操作:
创建 user_api_key_client 表
列:
client_id 和 application_name 从 user_api_key 迁移
redirect_uri(可选)
public_key(可选)
所有使用 client_id 和 application_name 的现有功能将像以前一样通过 user_api_key_client 工作。
添加注册客户端路由
post "/user-api-key/register" => "user_api_keys#register"
必需参数:
application_name
client_id
public_key
auth_redirect
操作:
验证并保存参数到 user_api_key_client
如果成功,则返回成功代码
允许在创建操作中使用已注册的客户端
将 UserApiKeyController 的 create 操作更改如下:
如果 client_id 存在于 user_api_key_client 中并且同时具有 auth_redirect 和 public_key:
使用存储的 auth_redirect 验证 auth_redirect 的使用
使用存储的 public_key 加密返回的负载
否则,遵循现有功能。
抄送 @pmusaraj
2 个赞
pmusaraj
(Penar Musaraj)
2024 年6 月 21 日 18:54
2
总的来说,我赞成这样做,因为它可以在不给管理员带来太多麻烦的情况下,在 ActivityPub 插件及其他插件中实现用户授权工作流。
不过,有一些问题:
我不太喜欢这里的迁移,我宁愿保持现有的用户 API 密钥不变,因为单个用户密钥的 ID 和名称独立于注册客户端的 ID 和名称。也许我们可以为 user_api_key 添加一个 user_api_key_client_id 列。然后,带有关联客户端的密钥可以使用客户端配置的重定向(当然,现有密钥也保留当前行为)。
此外,管理员是否应该能在某个地方查看注册客户端列表?
1 个赞
angus
(Angus McLeod)
2024 年6 月 24 日 07:34
4
这就是为什么我认为应该迁移 client_id
当前 user_api_keys 表混合了可能应该是两个独立数据模型的内容:用户 API 密钥和用户 API 密钥客户端。您可以在密钥创建方法中看到当前方法的局限性(此处 ):
# destroy any old keys we had
UserApiKey.where(user_id: current_user.id, client_id: params[:client_id]).destroy_all
key =
UserApiKey.create!(
application_name: @application_name,
client_id: params[:client_id],
user_id: current_user.id,
push_url: params[:push_url],
scopes: scopes.map { |name| UserApiKeyScope.new(name: name) },
)
为了创建新密钥,您必须销毁所有具有相同 client_id 的密钥,以保持 client_id 的唯一性。换句话说,当前数据模型要求客户端和密钥之间存在 1:1 的关系。这种 1:1 的关系对于一部分用例很有用,但限制了其他用例。
事实上,这种 1:1 的限制正是您建议的方法可能不起作用的原因。
为了让客户端为一个密钥注册重定向,client_id 的唯一性必须独立于密钥本身。否则,注册将无法用于多个密钥,因为注册操作中的 client_id 用于标识重定向。
如果您将 client_id 和 application_name 移至专用的 user_api_key_clients 表,您将保留 1:1 的情况,同时也允许 1:多 的情况,以及由此带来的功能,例如用于 ActivityPub 的 redirect_uri 注册。
1 个赞
pmusaraj
(Penar Musaraj)
2024 年7 月 26 日 17:21
6
抱歉,Angus,耽搁了。
我明白你的意思了,但通过迁移现有的 client_id,我们会在新表中保留这种混合状态,因为迁移过来的 ID/名称将是 1 对 1 客户端的密钥。尤其从管理员的角度来看,将来有一个已注册的多对一客户端列表会更好。
但也许现在不适合解决这个问题。
我们就按你提出的计划进行吧,期待你的 PR。谢谢!
1 个赞
angus
(Angus McLeod)
2024 年10 月 22 日 18:43
8
我已重新整理此 PR,因为我将重新专注于 ActivityPub,并且这是其一项功能的潜在框架,正如 OP 中所讨论的。
main ← angusmcleod:add_user_api_key_client
opened 01:34PM - 29 Jul 24 UTC
See further https://meta.discourse.org/t/feasibility-of-allowing-a-user-api-key-… client-to-register-a-valid-auth-redirect/312901
在重新整理时,我注意到将密钥与客户端分开(正如此 PR 所做的那样)也可以解决 @nat 最近解决的问题。
committed 04:39AM - 14 Oct 24 UTC
Allow user to log in another account using the same device (client_id)
即,需要进行此更改,以销毁与客户端关联的所有旧密钥,无论用户如何,是因为密钥和客户端在同一个表中。将它们分开意味着您可以为客户端的备用用户注册一个新密钥。
1 个赞
pmusaraj
(Penar Musaraj)
2024 年11 月 11 日 20:29
9
这终于合并了,非常感谢 @angus ,希望这能解除你的障碍。
1 个赞
angus
(Angus McLeod)
2024 年11 月 11 日 20:42
10
非常感谢!这(解决了我的问题) 很快就会有一个在 ActivityPub Discourse-to-Discourse 身份验证 PR 中实现的方案。
1 个赞