通过验证声明保护应用程序和 API

与令牌交互是构建应用程序来为用户授权的核心部分。 根据最低特权访问零信任原则,应用程序在执行授权时必须验证访问令牌中的某些声明的值。

基于声明的授权允许应用程序确保令牌包含令牌中存在的租户、使用者和参与者等内容的正确值。 也就是说,考虑到要使用的各种方法和要跟踪的方案,基于声明的授权看起来可能很复杂。 本文旨在简化基于声明的授权过程,以便确保应用程序遵循最安全的做法。

若要确保授权逻辑安全,必须验证声明中的以下信息:

  • 为令牌指定适当的受众。
  • 令牌的租户 ID 与存储数据的租户的 ID 匹配。
  • 令牌的使用者适合。
  • 参与者(客户端应用)已获得授权。

注意

访问令牌仅在客户端为其获取访问令牌的 Web API 中进行验证。 客户端不应验证访问令牌。

有关本文提及的声明的详细信息,请参阅 Microsoft 标识平台访问令牌

验证受众

aud 声明标识令牌的目标受众。 在验证声明之前,必须始终验证访问令牌中包含的 aud 声明的值是否与 Web API 匹配。 该值可取决于客户端请求令牌的方式。 访问令牌中的受众取决于终结点:

  • 对于 v2.0 令牌,受众是 Web API 的客户端 ID。 即一个 GUID。
  • 对于 v1.0 令牌,受众是在验证令牌的 Web API 中声明的 appID URI 之一。 例如,api://{ApplicationID} 或以域名开头的唯一名称(如果域名与租户相关联)。

有关应用程序的 appID URI 的详细信息,请参阅应用程序 ID URI

验证租户

始终检查令牌中的 tid 是否匹配用于通过应用程序存储数据的租户 ID。 在租户上下文中为应用程序存储信息时,以后只能在同一租户中再次访问它。 请勿允许从一个租户访问另一个租户的数据。

租户的验证只是第一步,仍然需要如本文所述对使用者和执行组件进行检查。 如果打算授权租户中的所有用户,强烈建议明确将这些用户添加到组中并根据组进行授权。 例如,如果只检查租户 ID 和 oid 声明的状态,则 API 可能会无意间为用户之外的该租户中的所有服务主体进行授权。

验证使用者

确定令牌使用者(如用户或仅应用令牌的应用程序本身)是否已获得授权。

可以检查特定的 suboid 声明。

或者,

可以检查使用者是否属于具有 rolesscpgroupswids 声明的相应角色或组。 例如,使用不可变声明值 tidoid 作为应用程序数据的组合键,并确定是否应向用户授予访问权限。

rolesgroupswids 声明也可用来确定使用者是否有权执行操作,但它们不是可用来为使用者授权的所有方式的详尽列表。 例如,管理员可能有权写入 API,而不是普通用户,或者用户可能位于允许执行某些操作的组中。 wid 声明表示分配给用户的租户级角色,该角色来自 Microsoft Entra 内置角色中显示的角色。 有关详细信息,请参阅 Microsoft Entra 内置角色

警告

请勿使用 emailpreferred_usernameunique_name 等声明来存储或确定访问令牌中的用户是否应有权访问数据。 这些声明不是唯一的,可以由租户管理员或用户(某些情况下)控制,因此它们不适合用于授权决策。 仅用于显示目的。 此外,请勿使用 upn 声明进行授权。 虽然 UPN 是唯一的,但它通常会在用户主体的生存期内发生变化,因此对于授权不可靠。

验证参与者

代表用户的客户端应用程序(称为参与者)也必须获得授权。 使用 scp 声明(范围)来验证应用程序是否有权执行操作。 scp 中的权限应限制为用户实际需要的权限,并遵循最低特权原则。

但是,会出现令牌中不存在 scp 的情况。 以下情况下,应该检查是否缺少 scp 声明:

  • 守护程序应用/仅限应用权限
  • ID 令牌

有关范围和权限的详细信息,请参阅 Microsoft 标识平台中的范围和权限

注意

应用程序可以处理仅限应用的令牌(来自例如守护程序应用等没有用户的应用程序的请求),并希望跨多个租户而不是单个服务主体 ID 授权特定应用程序。 在在这种情况下,appid 声明(对于 v1.0 令牌)或 azp 声明(对于 v2.0 令牌)可用于使用者授权。 但是,使用这些声明时,应用程序必须确保通过验证 idtyp 可选声明直接为应用程序颁发令牌。 只有 app 类型的令牌才能以这种方式进行授权,因为委托的用户令牌可能被应用程序以外的实体获取。

后续步骤

  • 有关令牌和声明的详细信息,请参阅安全令牌