使用动态范围在多租户应用程序中实现OAuth 2

时间:2018-08-02 16:04:36

标签: authentication oauth oauth-2.0 authorization standards

我目前正在尝试将多租户系统从“自定义”身份验证和授权实施迁移到OAuth2。

多租户模型与GitHub的结构非常相似,因此我将使用它作为主要示例。假设在应用程序中有用户,存储库和组织。用户可以直接访问存储库,也可以通过其所属组织访问组织。根据他们的访问权限,用户应该对存储库和子资源(例如/ repository / issues)或组织及其子资源(/ organization / members)具有不同的权限,以管理它们的用户。与GitHub的OAuth2解决方案不同,该系统应该能够在存储库或组织之间提供不同级别的权限(GitHub通过自定义实现在不同级别上提供此权限)。

目标是保持逻辑尽可能简单,将所有内容封装在授权服务中,并尽可能多地搭载在OAuth2上。

我的方法是部署通用OAuth2服务,并使用动态范围处理权限:

  • user:read
  • user:write
  • repo:read
  • org:read
  • repo:<repo_id>:issues:read
  • repo:<repo_id>:issues:write
  • org:<org_id>:members:read
  • org:<org_id>:members:write

这为客户端和用户启用了精细权限,例如,一个用户能够在他的一个存储库中read + write发行,而在另一个存储库中只能read发行。

虽然这似乎可以解决问题,但主要的限制是能够请求范围。由于用户不知道他们有权访问的存储库和组织的ID,因此在联系授权服务器时,他们无法请求正确的作用域列表。

为了克服这个问题,我考虑了两种解决方案:

解决方案1 ​​

  1. repo:readorg:read发行令牌
  2. 检索用户有权访问的存储库和组织的列表
  3. 发布具有所有必要范围的第二个令牌

更深入地思考,这似乎是不可行的,因为除非授权服务器处理资源的这种“发现”,否则它不支持implicit的{​​{1}}之类的授予。

解决方案2

前2个步骤与第一个解决方案共通,而对于第3个步骤,用户将只能发出承租人范围的令牌。通过extending the OAuth2 with a parameter识别承租人(authorization_code),使用authorization_code授予的客户端将必须为每个承租人发行令牌。在步骤1上发出的令牌将必须在授权服务器上保留用户的身份,并且当用户在租户之间切换时,无需重新进行身份验证。这种方法的缺点是,它会增加客户端集成的复杂性,并可能以某种方式违背标准。

我正在寻找对此的第二种意见,这可能会简化问题并确保解决方案符合标准。

2 个答案:

答案 0 :(得分:2)

tldr;如何使用自包含的访问令牌传递用户身份信息并保留在API端点定义的访问策略?

您当前面临的问题是由于OAuth 2.0 scope的功能不匹配造成的。 Scope value in OAuth 2.0被定义为供客户端应用程序使用。

  

授权和令牌端点允许客户端指定      使用“范围”请求参数的访问请求的范围。

但是在您的方法中,您尝试使其由最终用户(人类用户)定义。

一种解决方案是使授权服务器独立于权限详细信息。这意味着,授权服务器仅颁发对您的服务/系统有效的令牌。这些令牌可以是独立的,包含用户标识符和可选的组织详细信息(声明)。它可能包含您的服务所需的其他详细信息(由您决定)。理想的格式是使其成为JWT。

一旦您的客户端(系统的使用者,如GIT网站)获得了此令牌,它便可以调用系统后端。一旦您的系统支持接收令牌,它就可以验证令牌的完整性,所需的声明,并使用这些声明来标识为该特定用户授予了哪些资源。您为范围定义的权限级别现在与服务后端一起存储。

此功能的优势在于可以让用户身份驻留在任何地方。例如,您可以使用Google或Auzure AD,只要它们可以为您提供有效的令牌,就可以支持此类用户使用您的系统。这是理想的选择,因为权限未存储在其中。超级用户将具有定义和维护这些权限的能力。

答案 1 :(得分:2)

同意@Kavindu Dodanduwa提到的所有内容,但想在此处添加一些其他详细信息。

这个问题确实超出了OAuth 2.0标准所涵盖的范围。如果要管理每个资源(例如,每个存储库或组织)的权限,则应在您的服务或它前面的网关中进行处理。通常,您需要在后端存储某种access-control list (ACL),然后才能使用它来授权用户。

如果您想查看现有标准,请查看XACMLUMA(这是OAuth 2.0的扩展)。但是,我发现它们的实现和管理相当复杂,尤其是在分布式环境中。

相反,我建议使用sidecar的替代解决方案来对您的服务执行授权。查看相关博客文章:

Open Policy Agent对于这种架构可能是一个很好的解决方案。