从另一个 API 调用 API

作为开发人员,如何在一个 API 需要调用另一个 API 时确保零信任? 在本文中,你将了解如何在代表用户工作时安全地开发应用程序。

当用户驱动应用的 UI 时,应用可能会使用委托的权限,以使 API 知道哪个用户代表应用工作。 它将检查应用在调用 API 时提供的访问令牌中的主题(子)声明或对象 ID (oid) 和租户 ID (tid) 声明。 API 不依赖不受信任的应用,这只是来自网络上某个位置的调用。 相反,它会验证令牌,以确保 API 仅代表 Microsoft Entra ID 已验证的应用用户工作。

当一个 API(我们将称其为原始 API)调用另一个时,我们调用的 API(我们将称其为下游 API)必须遵循上述验证流程。 下游 API 不能依赖不受信任的网络来源。 它必须从经过正确验证的访问令牌获取用户标识。

如果下游 API 未遵循正确的验证流程,下游 API 必须依靠原始 API 以另一种方式提供用户的标识。 下游 API 可能会错误地使用应用程序权限执行该操作。 然后,原始 API 将成为用户对下游 API 可实现哪些结果的唯一授权。 原始 API 可以有意(或无意)地允许用户完成用户以其他方式无法完成的任务。 例如,一个用户可以更改另一个用户的详细信息,或者读取和更新用户无权访问的文档。 不正确的验证可能会导致严重的安全问题。

为了提高安全性,原始 API 获取委托的权限访问令牌,以便在原始 API 进行调用时提供给下游 API。 我们来看看如何执行。

客户端应用获取访问令牌以调用原始 API

下图左侧显示了客户端应用,右侧是原始 API。

示意图的左侧显示了具有 ID 和访问令牌的客户端应用,右侧显示了需要授权的原始 API。

客户端应用程序已将委托的权限访问令牌(由带“A”标签的五边形指示)获取到原始 API。 委托的权限访问令牌允许它代表用户调用需要授权的原始 API。

客户端应用向原始 API 提供访问令牌

下面的动画显示了向原始 API 提供访问令牌的客户端应用。 原始 API 完全验证并检查访问令牌,以确定客户端应用用户的标识。

动画图的左侧显示了客户端应用,该应用向右侧显示的需要授权的原始 API 提供访问令牌。

原始 API 执行令牌验证和强制实施

下一个动画显示,在客户端应用向原始 API 提供访问令牌后,原始 API 将执行令牌验证和强制实施。 如果一切正常,API 将继续为客户端应用的请求提供服务。

动画图的左侧显示了具有 ID 令牌的客户端应用,该应用向右侧显示的原始 API 提供访问令牌。

原始 API 无法使用访问令牌调用下游 API

下面的动画显示原始 API 现在想要调用下游 API。 但是,原始 API 无法使用访问令牌调用下游 API。

动画图显示了向原始 API 提供访问令牌的客户端应用。“需要授权”可防止原始 API 向下游 API 提供令牌。

原始 API 返回到 Microsoft Entra ID

在下面的动画中,原始 API 需要返回到 Microsoft Entra ID。 它需要访问令牌以代表用户调用下游 API。

动画图显示了向原始 API 提供访问令牌的客户端应用,该原始 API 需要 Microsoft Entra ID 进行验证才能调用下游 API。

动态图显示了两个关系图,在第一个关系图和第二个关系图之间有一个运动转换。 第一个图标题:原始 API 无法使用该令牌调用下游 API。 第一个图组件:云形状显示在包含 Microsoft Entra ID 图标的幻灯片顶部中心。 在左下角,矩形表示客户端应用。 客户端应用矩形下方是一个标记为“ID”的六边形,表示 ID 令牌。 在下部中间,立方体形图标、云形状和世界图标表示原始 API。 箭头将左侧的形状连接到中间的形状。 在箭头上方,云形状的左侧和下方,是一个标记为“A”的六边形,表示访问令牌。 在右下角,立方体形图标、云形状和世界图标表示下游 API。 在其左侧,正方形标签为“需要授权”。 箭头将中间的形状连接到右侧的形状。 第二个图标题:原始 API 返回到 Microsoft Entra ID。 第二个图副标题:需要访问令牌以代表用户调用下游 API。 第二个图组件:云形状显示在包含 Microsoft Entra ID 图标的幻灯片顶部中心。 在左下角,矩形表示客户端应用。 客户端应用矩形下方是一个标记为“ID”的六边形,表示 ID 令牌。 在下部中间,立方体形图标、云形状和世界图标表示原始 API。 箭头将左侧的形状连接到中间的形状。 在箭头上方,云形状的左侧和下方,是一个标记为“A”的六边形,表示访问令牌。 在原始 API 形状上方,箭头将它们连接到 Microsoft Entra 云形状。 在右下角,立方体形图标、云形状和世界图标表示下游 API。 在其左侧,正方形标签为“需要授权”。 箭头将中间的形状连接到右侧的形状。

下一个动画显示了原始 API,它可提供原始 API 从客户端应用接收的令牌以及原始 API 的客户端凭据。

动画图显示了向原始 API 提供访问令牌的客户端应用,该原始 API 需要接收 Microsoft Entra ID 的验证才能调用下游 API。

动态图显示了两个关系图,在第一个关系图和第二个关系图之间有一个运动转换。 第一个图标题:原始 API 返回到 Microsoft Entra ID。 第一个图副标题:需要访问令牌以代表用户调用下游 API。 第一个图组件:云形状显示在包含 Microsoft Entra ID 图标的幻灯片顶部中心。 在左下角,矩形表示客户端应用。 客户端应用矩形下方是一个标记为“ID”的六边形,表示 ID 令牌。 在下部中间,立方体形图标、云形状和世界图标表示原始 API。 箭头将左侧的形状连接到中间的形状。 在箭头上方,云形状的左侧和下方,是一个标记为“A”的六边形,表示访问令牌。 在原始 API 形状上方,箭头将它们连接到 Microsoft Entra 云形状。 在右下角,立方体形图标、云形状和世界图标表示下游 API。 在其左侧,正方形标签为“需要授权”。 箭头将中间的形状连接到右侧的形状。 第二个图标题:原始 API 返回到 Microsoft Entra ID。 第二个关系图副标题:提供来自客户端应用的令牌以及原始 API 的凭据。 第二个图组件:云形状显示在包含 Microsoft Entra ID 图标的幻灯片顶部中心。 在左下角,矩形表示客户端应用。 客户端应用矩形下方是一个标记为“ID”的六边形,表示 ID 令牌。 在下部中间,立方体形图标、云形状和世界图标表示原始 API。 箭头将左侧的形状连接到中间的形状。 在原始 API 形状上方,箭头将它们连接到 Microsoft Entra 云形状。 在该箭头左侧,云形状的左侧和下方,是一个标记为“A”的六边形,表示访问令牌。 访问令牌下方是一个钥匙形状。 在右下角,立方体形图标、云形状和世界图标表示下游 API。 在其左侧,正方形标签为“需要授权”。 箭头将中间的形状连接到右侧的形状。

Microsoft Entra ID 将检查同意或条件访问强制实施等内容。 可能需要返回到调用客户端,并提供无法获取令牌的原因。 通常使用声明质询流程返回到调用应用程序,并解释未收到同意(例如,与条件访问策略相关)。

Microsoft Entra ID 执行检查

在下面的动画中,Microsoft Entra ID 执行其检查。 如果一切正常,Microsoft Entra ID 将向原始 API 颁发访问令牌,以代表用户调用下游 API。

动画图显示了在 Microsoft Entra ID 进行验证后向下游 API 提供访问令牌的原始 API。

动态图显示了两个关系图,在第一个关系图和第二个关系图之间有一个运动转换。 第一个图标题:原始 API 返回到 Microsoft Entra ID。 第一个关系图副标题:提供来自客户端应用的令牌以及原始 API 的凭据。 第一个图组件:云形状显示在包含 Microsoft Entra ID 图标的幻灯片顶部中心。 在左下角,矩形表示客户端应用。 客户端应用矩形下方是一个标记为“ID”的六边形,表示 ID 令牌。 在下部中间,立方体形图标、云形状和世界图标表示原始 API。 箭头将左侧的形状连接到中间的形状。 在原始 API 形状上方,箭头将它们连接到 Microsoft Entra 云形状。 在该箭头左侧,云形状的左侧和下方,是一个标记为“A”的六边形,表示访问令牌。 访问令牌下方是一个钥匙形状。 在右下角,立方体形图标、云形状和世界图标表示下游 API。 在其左侧,正方形标签为“需要授权”。 箭头将中间的形状连接到右侧的形状。 第二个图标题:Microsoft Entra ID 检查条件访问、同意等。第二个图副标题:原始 API 接收自己的访问令牌,以代表登录到客户端应用的用户调用下游 API。 第二个图组件:云形状显示在包含 Microsoft Entra ID 图标的幻灯片顶部中心。 在左下角,矩形表示客户端应用。 客户端应用矩形下方是一个标记为“ID”的六边形,表示 ID 令牌。 在下部中间,立方体形图标、云形状和世界图标表示原始 API。 箭头将左侧的形状连接到中间的形状。 在原始 API 形状上方,箭头将它们连接到 Microsoft Entra 云形状。 在右下角,立方体形图标、云形状和世界图标表示下游 API。 在其左侧,正方形标签为“需要授权”。 箭头将中间的形状连接到右侧的形状。 在该箭头上方,原始 API 形状的右侧,是一个标记为“A”的六边形,表示访问令牌。

原始 API 拥有代理流的用户上下文

下面的动画演示了允许 API 在调用下游 API 时继续拥有用户上下文的代理流 (OBO) 流程。

动画图显示了向下游 API 提供访问令牌的原始 API。

原始 API 调用下游 API

在下一个动画中,我们调用下游 API。 下游 API 接收的令牌将有可指示下游 API 的正确受众 (aud) 声明。

动画图显示了验证来自原始 API 的访问令牌的下游 API。

令牌将包括所授予同意的范围和原始应用用户标识。 下游 API 可以正确实现有效权限,以确保已标识的用户有权完成请求的任务。 你需要使用代理流获取 API 的令牌来调用另一个 API,以确保用户上下文传递到所有下游 API。

最佳选项:原始 API 执行代理流

最后一个动画显示,最佳选项是让原始 API 执行代理流 (OBO)。 如果下游 API 收到正确的令牌,它将能够正确地响应。

动画图显示了从原始 API 接收访问令牌的下游 API。

当 API 代表用户操作并需要调用另一个 API 时,API 必须使用 OBO 来获取委托的权限访问令牌,以代表用户调用下游 API。 当 API 代表用户执行操作时,API 绝不应使用应用程序权限来调用下游 API。

后续步骤