如何在 oauth2 身份验证之上实现用户权限

Posted

技术标签:

【中文标题】如何在 oauth2 身份验证之上实现用户权限【英文标题】:How to implement user permissions on top of oauth2 authentication 【发布时间】:2020-04-09 11:33:48 【问题描述】:

在使用 oauth2 通过 IdP 对其用户进行身份验证的 Web 应用程序中,实现用户权限(客户端和服务器端)的更标准/推荐的选项是什么?

“用户权限”是指用户在应用程序中允许或不允许执行的操作。 例如,假设应用程序有一个“管理”页面,用于管理应用程序的一些设置,只允许特定用户进入。其中一些用户只被允许查看当前设置,而其他用户也被允许更改设置(可能只有其中一些)。

据我所知,oauth2 中的“范围”概念可能用于实现这样的要求,例如,仅允许查看“管理员”页面的用户将具有 app:admin:view 范围,而还可以编辑设置的用户将具有app:admin:some-setting:edit 范围。 但是,在大多数大型身份提供者服务中,管理这些范围以及将它们分配给用户的任务似乎相当繁琐。

这会是一个好的解决方案吗?如果是这样,是否有任何产品/服务与 oauth2 IdP 集成并有助于更轻松地管理权限及其对用户的分配(例如,使用直观的 UI)?如果没有,是否有任何既定的方法来处理这种情况?

【问题讨论】:

【参考方案1】:

OAuth2 实现中的授权服务器返回 JWT(作为访问令牌)。您可以让授权服务器在一些自定义“声明”中返回用户访问信息。 Spring Security OAuth2 支持这一点。教程是here。

但是,如果用户有很长的访问信息列表,使得 JWT 大小超过 4KB,您将无法将令牌存储在 cookie 中(这通常被认为是存储正如我在其他答案here 和here 中解释的那样,客户端上的令牌。在这种情况下,您可以拥有一个单独的微服务,该微服务将返回给定用户名的用户访问信息,您可以将该信息本地缓存在其他服务中。

【讨论】:

【参考方案2】:

范围

我不会为此目的使用OAuth2 scopes。原因是 OAuth2 范围是为了限制 application 可以对用户的 resource 做什么,而不是限制 user应用程序

例如,如果我编写了一个 Web 应用程序来向用户展示他们在 Google 文档中使用的语言,那么它需要从 Google 委派的权限才能读取用户的 Google 文档,而不是读取他们的日历等。因此,应用程序将从 Google 获得一个 OAuth2 令牌,该令牌作用域具有 read-Docs 权限,但没有 read-calendar 权限或任何其他不必要的权限。

使用范围来携带有关用户权限(与应用程序权限相反)的信息的具体缺点是,如果您想要实现类似上述的内容,应用程序可以在您的应用程序中获得对用户资源的不同级别的访问权限,尝试同时以多种方式使用 OAuth2 范围可能会令人困惑。如果您想通过 API 向客户公开应用程序中的功能以集成到他们自己的应用程序中,这可能会成为一个问题。

OAuth2 委托与 OpenID Connect 身份验证

您提到您正在使用 OAuth2 进行身份验证。 OAuth2 用于委派授权,not for authentication。 OAuth2 访问令牌do not represent authenticated users。 OpenId Connect ID 令牌可以。

AWS Cognito 用户组

我喜欢使用AWS Cognito 进行身份验证。它为您跟踪您的用户,因此您不需要用户数据库并处理对他们的身份验证。它与 Google 和 Facebook 等外部身份提供商集成。对于跟踪不同类型用户的用例,您可以使用 Cognito Groups。 Here 是带有示例的博客文章。

基本上,您将从 Cognito 获得一个 ID 令牌,您的客户端或您的服务器可以读取该 ID 令牌以找出用户的组(管理员、普通用户等),并采取相应的行动。 Here 是从令牌中读取组的示例。

【讨论】:

以上是关于如何在 oauth2 身份验证之上实现用户权限的主要内容,如果未能解决你的问题,请参考以下文章

用户接受权限后重定向回应用程序 Oauth2

如何使用 oAuth2 对 SPA 用户进行身份验证?

使用Spring启动进行Oauth2身份验证

如何使用 OAuth2 身份验证保护私有数据?

Spring Security Oauth2 组

具有自定义身份验证提供程序的 OAUTH2 用户服务