Raz*_*van 6 authentication standards authorization oauth oauth-2.0
我目前正在尝试将多租户系统从“自定义”身份验证和授权实施迁移到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,因此在联系授权服务器时,他们无法请求正确的作用域列表。
为了克服这个问题,我考虑了两种解决方案:
解决方案1
repo:read和发行令牌org:read从更深的角度来看,这似乎是不可行的,因为除非授权服务器将处理这种“发现”资源implicit,authorization_code否则它将不支持像这样的授予。
解决方案2
前两个步骤与第一个解决方案相同,而对于第三个步骤,用户只能发出租户范围的令牌。通过使用标识租户(/authorize?...&repo=<repo_id>)的参数扩展OAuth2,使用authorization_code授予的客户端将必须为每个租户发行令牌。在步骤1上发出的令牌将必须在授权服务器上保留用户的身份,并且当用户在租户之间切换时,无需重新进行身份验证。这种方法的缺点是,它增加了客户端集成的复杂性,并且可能以某种方式违背标准。
我正在寻找对此的第二种意见,这可能会简化问题并确保解决方案符合标准。
同意@Kavindu Dodanduwa 提到的所有内容,但想在这里添加一些额外的细节。
这个问题确实超出了标准 OAuth 2.0 的范围。如果您想管理每个资源(例如每个存储库或组织)的权限,这应该在您的服务或其前面的网关中处理。通常,您需要在后端存储某种访问控制列表 (ACL) ,然后可以使用它来授权用户。
如果您想查看现有标准,请查看XACML和UMA(这是 OAuth 2.0 的扩展)。然而,我发现它们的实施和管理相当复杂,尤其是在分布式环境中。
相反,我建议使用 sidecar 对您的服务执行授权的替代解决方案。查看相关博客文章:
开放策略代理可能是此类架构的一个很好的解决方案。
tldr; 如何使用自包含的访问令牌来传达用户身份信息并保存在 API 端点定义的访问策略?
您现在面临的问题是由于 OAuth 2.0scope的功能不匹配。OAuth 2.0 中的范围值被定义为由客户端应用程序使用。
授权和令牌端点允许客户端使用“scope”请求参数指定访问请求的范围。
但是在您的方法中,您尝试使其由最终用户(人类用户)定义。
一种解决方案是使授权服务器独立于权限细节。这意味着,授权服务器只发布对您的服务/系统有效的令牌。这些令牌可以是独立的,包含用户标识符和可选的组织详细信息(声明)。它可能包含您的服务所需的其他详细信息(由您决定)。理想的格式是使其成为 JWT。
一旦您的客户端(系统的消费者,如 GIT 网站)获得此令牌,它就可以调用系统后端。一旦您的系统支持收到令牌,它就可以验证令牌的完整性、所需声明并使用这些声明来确定为该特定用户授予的资源。您为范围定义的权限级别现在存储在您的服务后端中。
这样做的好处是能够让用户身份驻留在任何地方。例如,您可以使用 Google 或 Auzure AD,只要他们能够为您提供有效的令牌,您就可以支持此类用户使用您的系统。这是理想的,因为权限不存储在其中。超级用户将有能力定义和维护这些权限。
| 归档时间: |
|
| 查看次数: |
1775 次 |
| 最近记录: |