【发布时间】:2019-01-10 11:33:14
【问题描述】:
我目前正在尝试将多租户系统从“自定义”身份验证和授权实施迁移到 OAuth2。
多租户模型与 GitHub 的结构非常相似,因此我将使用它作为主要示例。假设在应用程序中我们有用户、存储库和组织。用户可以直接访问存储库,也可以通过他们所属的组织访问存储库。根据他们的访问权限,用户应该对管理它们的用户拥有对存储库和子资源(如 /repository/issues)或组织及其子资源(/organization/members)的不同权限。与 GitHub 的 OAuth2 解决方案不同,该系统应该能够跨存储库或组织提供不同级别的权限(GitHub 通过自定义实现在不同级别上提供)。
目标是保持逻辑尽可能简单,将所有内容封装在授权服务中,并尽可能多地搭载 OAuth2。
我的方法是部署通用 OAuth2 服务,并使用动态范围处理权限:
user:readuser:writerepo:readorg:readrepo:<repo_id>:issues:readrepo:<repo_id>:issues:writeorg:<org_id>:members:readorg:<org_id>:members:write
这为客户端和用户启用了细粒度的权限,例如用户可以在他的一个存储库中read + write 问题,但在另一个存储库中只能read。
虽然这似乎解决了问题,但主要限制是能够请求范围。由于用户不知道他们有权访问的存储库和组织的 ID,因此他们在联系授权服务器时无法请求正确的范围列表。
为了克服这个问题,我考虑了 2 个解决方案:
解决方案 1
- 为
repo:read和org:read颁发令牌 - 检索用户有权访问的存储库和组织列表
- 使用所有必需的范围发出第二个令牌
深思熟虑后,事实证明这是不可行的,因为它不支持像 implicit 对 authorization_code 的授权,除非授权服务器会处理这种资源“发现”。
解决方案 2
前 2 个步骤与第一个解决方案相同,而对于第 3 个步骤,用户将只能发布租户范围内的令牌。通过extending the OAuth2 with a parameter 识别租户(/authorize?...&repo=<repo_id>),使用授权码授权的客户端必须为每个租户颁发令牌。在步骤 1 中发布的令牌必须在授权服务器上保留用户的身份,并且当用户在租户之间切换时无需重新验证。这种方法的缺点是它增加了客户端集成的复杂性,并且可能会以某种方式违反标准。
我正在寻找对此的第二意见,这可能会简化问题并确保解决方案符合标准。
【问题讨论】:
标签: authentication oauth oauth-2.0 authorization standards