通过验证声明保护应用程序和 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 可能会无意间为用户之外的该租户中的所有服务主体进行授权。
验证使用者
确定令牌使用者(如用户或仅应用令牌的应用程序本身)是否已获得授权。
可以检查特定的 sub
或 oid
声明。
或者,
可以检查使用者是否属于具有 roles
、scp
、groups
、wids
声明的相应角色或组。 例如,使用不可变声明值 tid
和 oid
作为应用程序数据的组合键,并确定是否应向用户授予访问权限。
roles
、groups
或 wids
声明也可用来确定使用者是否有权执行操作,但它们不是可用来为使用者授权的所有方式的详尽列表。 例如,管理员可能有权写入 API,而不是普通用户,或者用户可能位于允许执行某些操作的组中。 wid
声明表示分配给用户的租户级角色,该角色来自 Microsoft Entra 内置角色中显示的角色。 有关详细信息,请参阅 Microsoft Entra 内置角色。
警告
请勿使用 email
、preferred_username
或 unique_name
等声明来存储或确定访问令牌中的用户是否应有权访问数据。 这些声明不是唯一的,可以由租户管理员或用户(某些情况下)控制,因此它们不适合用于授权决策。 仅用于显示目的。 此外,请勿使用 upn
声明进行授权。 虽然 UPN 是唯一的,但它通常会在用户主体的生存期内发生变化,因此对于授权不可靠。
验证参与者
代表用户的客户端应用程序(称为参与者)也必须获得授权。 使用 scp
声明(范围)来验证应用程序是否有权执行操作。 scp
中的权限应限制为用户实际需要的权限,并遵循最低特权原则。
但是,会出现令牌中不存在 scp
的情况。 以下情况下,应该检查是否缺少 scp
声明:
- 守护程序应用/仅限应用权限
- ID 令牌
有关范围和权限的详细信息,请参阅 Microsoft 标识平台中的范围和权限。
注意
应用程序可以处理仅限应用的令牌(来自例如守护程序应用等没有用户的应用程序的请求),并希望跨多个租户而不是单个服务主体 ID 授权特定应用程序。 在在这种情况下,appid
声明(对于 v1.0 令牌)或 azp
声明(对于 v2.0 令牌)可用于使用者授权。 但是,使用这些声明时,应用程序必须确保通过验证 idtyp
可选声明直接为应用程序颁发令牌。 只有 app
类型的令牌才能以这种方式进行授权,因为委托的用户令牌可能被应用程序以外的实体获取。
后续步骤
- 有关令牌和声明的详细信息,请参阅安全令牌