【问题标题】:What are User Claims in IdentityServer4 API Resources vs. API ScopesIdentityServer4 API 资源与 API 范围中的用户声明是什么
【发布时间】:2020-02-28 10:29:10
【问题描述】:

我已配置 IdentityServer4 的一个实例,并已成功将其配置为 OIDC 提供程序的客户端。我现在正尝试将其设置为我的应用程序的 OIDC 提供程序。我已经阅读了快速入门并阅读了文档,但我很难找到我的具体问题的答案。

用户声明可以在几个不同的地方指定:API 资源和 API 范围。在 API 资源上指定用户声明与在该资源的 API 范围上指定用户声明有什么区别?

我对术语的理解是:

  • API 资源表示客户端将访问的 API,例如一个“GitHub API”,我的“数据导入 API”
  • API 范围表示该 API 中的资源子集,客户端可以请求访问这些资源,例如repo => 公共和私有存储库,import_job:control => 开始/停止/删除导入作业
  • 用户声明是关于用户的一条信息,例如email => 电子邮件地址

将用户声明与 API 资源和/或范围相关联必须是有意义的,但我无法做出精神上的飞跃来确定原因和方式。请提供这些声明的说明性示例以及它们在上面给出的上下文中所代表的内容:GitHub API(假设,如果没有实际定义)和通用批量导入 API。

【问题讨论】:

    标签: oauth-2.0 identityserver4 openid-connect


    【解决方案1】:

    资源是一个概念,可以划分为可以以各种方式实现的逻辑部分(范围)。无论哪种方式,尽管这在文档中可能不是很明显,但对于 IdentityServer,一个资源至少有一个范围。

    为了允许客户端访问资源,必须配置客户端允许该客户端的范围。在示例中,范围的名称等于资源的名称,但实际上一个资源可能具有多个范围。请注意,仅允许使用一个范围的客户端可以访问整个资源(受众),除非资源 (api) 根据允许的范围过滤访问(范围是作为范围声明的访问令牌的一部分)。

    IdentityServer 的一个特点是它是一个令牌提供者,例如用于访问令牌和身份令牌。

    从最后一个开始,有两种类型的身份令牌。有一个“最小”身份令牌(仅包含“子”声明)仅在请求时与访问令牌一起发布。并且客户端可以在 UserInfo 端点请求一个“完整”身份令牌。

    对于 IdentityServer,用户声明是(身份信息的)资源。附带说明一下,在使用此信息之前应征得用户同意,因为用户拥有此信息。

    并非所有用户声明都应发送到在 UserInfo 端点请求的身份令牌。为了确定应该使用哪些声明,IdentityServer 查看 Identity~ 表。基于这些表,RequestedClaims 集合可用于 UserInfo 上下文,用于过滤用户声明资源。

    换句话说,当客户端配置为请求“openid”范围时,则仅包含“sub”声明,添加“profile”范围将包含基础配置文件声明(如果在 UserClaims 表中可用) ,并且配置“电子邮件”范围会将电子邮件也添加到身份令牌中。

    对于访问令牌也有类似的机制。基于 ApiClaims 和 ApiScopeClaims 表,RequestedClaims 集合可用于授权上下文。请查看my answer here 了解更多信息。

    假设您想将“名称”声明添加到访问令牌,然后将其添加到其中一个表中。查看my answer here 或者实际上是整个线程,了解更多信息。

    虽然 IdentityServer 可以向访问令牌添加各种声明,但您应该想知道这是否是正确的方法,如 this post 中所述。

    访问令牌声明的问题在于这些声明用于用户授权。但是用户声明通常并不意味着用户授权。而且您不希望最终得到一个包含所有声明的超级访问令牌。

    退一步,IdentityServer 是用来配置资源保护和客户端授权的。客户端可以连接到资源(范围),但有权访问信息的是用户:来自客户端的请求始终“代表用户”。这就是为什么“子”声明总是(在交互式流程中)访问令牌的一部分。此外,可以扩展 IdentityServer 以处理用户身份验证。但是,尽管在当前设计中是可能的,但用户授权不是(或至少不再是)IdentityServer 的关注点。

    IdentityServer 的创建者过去一直在考虑用户授权,并为此提出了一个单独的服务:PolicyServer。将授权声明从 IdentityServer 和访问令牌中取出。

    因此,为了回答您的问题,我们使用不同的表来配置用于构建令牌的资源、范围、客户端和过滤器。用户声明讲述了有关用户(身份)的一些信息,并且不在访问令牌中。

    对于用户授权,我可以推荐一个类似 PolicyServer 服务器的实现,结合基于资源的授权。


    表格的简短摘要:

    • AspNetUserClaims - 用户信息资源

    • ApiResources - 资源的名称

    • ApiScopes - 作为资源一部分的一对多范围

    • IdentityResources - 实际上是身份的范围(例如 openid 配置文件)

    • IdentityClaims - 为身份令牌过滤 AspNetUserClaims

    • ApiClaims - 为访问令牌过滤 AspNetUserClaims,无论请求哪个范围

    • ApiScopeClaims - 过滤访问令牌的 AspNetUserClaims,取决于请求的范围

    • ClientClaims - 为特定客户包含的声明

    • ClientScopes - 客户端允许的范围


    客户端请求范围。如果省略范围,则(根据规范)所有允许的范围都被视为请求。

    API 是资源(受众)的一部分。当资源具有多个范围时,需要更细粒度的客户端授权(基于范围)。

    用户授权用于确定允许用户做什么:客户端可以连接到 api,按范围(例如日历)过滤,并且用户有权读取但不能写入事件。

    虽然 calendar.writecalendar.read 可以是作用域,但与用户授权无关。用户可以被授权读取和写入,但由于客户端可能受到限制(例如 calendar.read),用户可能必须使用单独的客户端才能连接到资源,例如一个日历应用程序两者都有,一个电子邮件应用程序只有 calendar.read

    【讨论】:

    • 感谢您非常彻底的回答!表格的描述帮助很大。
    • 这是我遇到过的关于这个主题的最完整的解释之一。首先第一件事:非常感谢您的努力。我想指出,我现在正在设置一个 IdentityServer4 依赖方,它支持 EntityFramework 以支持持久性,但我找不到任何名为 ApiClaimsIdentityClaims 的表.另一方面,我浏览了 IS4.EF 代码的代码,发现了一个名为 UserClaim 的类,它由 ApiResourceClaimApiScopeClaimIdentityResourceClaim 类,它们一直映射到数据库。
    【解决方案2】:

    ApiResource 可以包含许多范围(订单、折扣、会计...)。例如,您需要一个令牌来访问 GitHub 的配置文件信息,而不是存储库等。在这种情况下,GitHub 是一个 ApiResource 并包含配置文件范围。

    当用户发送令牌请求时,只需指定一些范围(不是 ApiResource),IdentityServer 就会检测用户想要访问的 ApiResources(从请求的范围)。

    ApiResource 中的用户声明: 当您在 ApiResource 中指定 UserClaims 时,当用户请求令牌以访问该 ApiResource 时,这些 UserClaims 将在令牌中。

    范围没有任何用户声明。

    【讨论】:

    • 根据问题中的要求为基于 GitHub 的示例投票 ?
    【解决方案3】:

    添加到 Mehrdad 的答案:

    我喜欢将声明视为 API 中的一个对象,其中包含用于识别和授权的字段。

    一些声明将派生自 OAuth 访问令牌中的内容,但声明信息也可能来自其他地方。

    我的write up 可以帮助您直观地理解这一点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-18
      • 1970-01-01
      • 2018-02-02
      • 2018-06-14
      • 2010-09-18
      • 2018-04-28
      • 2019-08-01
      相关资源
      最近更新 更多