本文提供了有关如何在构建 Microsoft Fabric 工作负载时使用身份验证的指南。 它包括有关使用令牌和同意的信息。
数据平面和控制平面 API
数据平面 API 是工作负载后端公开的 API。 工作负载前端可以直接调用它们。 对于数据平面 API,工作负载后端可以决定要公开哪些 API。
控制平面 API 是通过 Fabric 传递的 API。 此过程从工作负载前端调用 JavaScript API 开始,以 Fabric 调用工作负载后端结束。 此类 API 的示例是“创建项”。
对于控制平面 API,工作负载必须遵循工作负载后端中定义的协定并实现这些 API。
在 Microsoft Entra ID 中工作负载的应用程序上显示 API 选项卡
在 “公开 API”选项卡上,需要添加控制平面 API 的权限范围和数据平面 API 的权限范围:
为控制平面 API 添加的范围应预先授权应用程序 ID 为
d2450708-699c-41e3-8077-b0c8341509aa的 Fabric 工作负载客户端应用程序。 当 Fabric 调用时,这些作用域包括在其发送到工作负荷后端的令牌中。需要为控制平面 API 至少添加一个范围才能使流正常工作。
为数据平面 API 添加的范围应预先授权应用程序 ID 为
871c010f-5e61-4fb1-83ac-98610a7e9110的 Microsoft Power BI。 这些内容包含在acquireAccessTokenJavaScript API 返回的令牌中。对于数据平面 API,您能够使用此选项卡管理工作负荷公开的每个 API 的详细权限。 理想情况下,应为工作负载后端公开的每个 API 添加一组范围,并在从客户端调用这些 API 时验证收到的令牌是否包括这些范围。 例如:
- 工作负载向客户端公开两个 API:
ReadData和WriteData。 - 工作负荷暴露了两个数据平面范围,
data.read和data.write。 - 在
ReadDataAPI 中,任务在继续流程之前验证令牌中是否包含data.read范围。 这同样适用于WriteData。
- 工作负载向客户端公开两个 API:
Microsoft Entra ID 中工作负载应用程序上的“API 权限”选项卡
在 API 权限 选项卡上,您需要添加您的工作负荷需要使用令牌交换的所有权限范围。 必须添加的范围是 Power BI 服务下的 Fabric.Extend。 对 Fabric 的请求可能会在没有这个范围的情况下失败。
使用令牌和同意
使用数据平面 API 时,工作负载前端需要获取令牌来调用工作负载后端。
以下部分介绍了工作负载前端如何使用 JavaScript API 和 代表 (OBO) 流来获取工作负载和外部服务的令牌,以及如何处理同意。
步骤 1:获取令牌
工作负载首先使用 JavaScript API 请求令牌,而无需提供任何参数。 此调用可能会导致两种情况:
用户看到工作负载配置的所有静态依赖项(“API 权限”选项卡上配置的内容)的同意窗口。 如果用户不是应用程序所属的主租户的一部分,并且以前没有为此应用程序授予对Microsoft Graph的访问权限,则会出现这种情况。
用户看不到同意窗口。 这种情况会发生在用户已经至少同意过一次此应用程序使用Microsoft Graph,或者用户是该应用程序的主租户成员。
在这两种情况下,工作负载都不应关心用户是否对所有依赖项(此时无法知道)给予完全同意。 收到的令牌涵盖工作负载后端受众,可用于直接从工作负载前端调用工作负载后端。
步骤 2:尝试访问外部服务
工作负载可能需要访问需要身份验证的服务。 对于该访问,它需要执行 OBO 流,在该流中,它将从客户端或 Fabric 接收的令牌交换到另一个服务。 由于缺少同意或工作负载尝试交换令牌的资源上配置的一些 Microsoft Entra 条件访问策略,令牌交换可能会失败。
若要解决此问题,工作负载负责在前端和后端之间直接调用时将错误传播到客户端。 使用工作负载通信中所述的错误传播处理 Fabric 调用时,工作负载还负责将错误传播到客户端。
工作负载传播错误后,可以调用 acquireAccessToken JavaScript API 来解决同意或条件访问策略问题,然后重试操作。
有关数据平面 API 失败,请参阅处理多重身份验证、条件访问和增量同意。 有关控制平面 API 失败,请参阅工作负载通信。
示例情况
让我们来看看需要访问三个 Fabric API 的工作负载:
列出工作区:
GET https://api.fabric.microsoft.com/v1/workspaces创建仓库:
POST https://api.fabric.microsoft.com/v1/workspaces/{workspaceId}/warehouses将数据写入 lakehouse 文件:
PUT https://onelake.dfs.fabric.microsoft.com/{filePath}?resource=file
若要能够使用这些 API,工作负载后端需要交换以下范围的令牌:
- 要列出工作区:
https://analysis.windows.net/powerbi/api/Workspace.Read.All或https://analysis.windows.net/powerbi/api/Workspace.ReadWrite.All - 对于创建仓库:
https://analysis.windows.net/powerbi/api/Warehouse.ReadWrite.All或https://analysis.windows.net/powerbi/api/Item.ReadWrite.All - 对于写入湖屋文件:
https://storage.azure.com/user_impersonation
前面提到的范围需要在“API 权限”下的工作负载应用程序上配置。
让我们看看负载可能遇到的情景示例。
示例 1
假设工作负载后端有一个数据平面 API,用于获取用户的工作区并将其返回到客户端:
工作负载前端使用 JavaScript API 请求令牌。
工作负载前端调用工作负载后端 API 以获取用户的工作区,并在请求中附加令牌。
工作负载后端会验证令牌,并尝试将其交换为所需的范围(假设
https://analysis.windows.net/powerbi/api/Workspace.Read.All)。工作负载无法交换指定资源的令牌,因为用户未同意应用程序访问此资源(请参阅 AADSTS 错误代码)。
工作后端系统通过指定需要得到对该资源的同意,将错误传递到工作前端系统。 负载前端调用
acquireAccessTokenJavaScript API 并提供additionalScopesToConsent:workloadClient.auth.acquireAccessToken({additionalScopesToConsent: ["https://analysis.windows.net/powerbi/api/Workspace.Read.All"]})或者,工作负载可以决定请求同意其应用程序上配置的所有静态依赖项,因此调用 JavaScript API 并提供
promptFullConsent。workloadClient.auth.acquireAccessToken({promptFullConsent: true})。
无论用户是否同意某些依赖项,此调用都会提示同意窗口。 之后,工作负载前端可以重试该操作。
注意
如果令牌交换仍然因同意错误而失败,则意味着用户未授予同意。 工作任务需要处理此类情况,例如,通知用户此 API 需要同意,否则将无法使用。
示例 2
假设工作负荷后端需要通过创建项 API 访问 OneLake(从 Fabric 调用到工作负荷):
工作负荷前端调用“创建项目”JavaScript API。
工作负载后台接收到来自 Fabric 的调用后,提取委托令牌,并对其进行验证。
工作负荷尝试为
https://storage.azure.com/user_impersonation交换令牌,但由于 Azure 存储访问所需的用户配置多重身份验证的租户管理员设置不当而失败(请参阅 AADSTS 错误代码)。工作负荷根据 工作负荷通信中的错误传播描述,将 Microsoft Entra ID 返回的错误和相关声明一起传递给客户端。
工作负载前端调用
acquireAccessTokenJavaScript API,并以claimsForConditionalAccessPolicy形式提供声明,其中claims指从工作负载后端传播的声明:workloadClient.auth.acquireAccessToken({claimsForConditionalAccessPolicy: claims})
之后,工作负载可以重试该操作。
请求同意时处理错误
有时,由于各种错误,用户无法授予同意。 同意请求后,响应将返回重定向 URI。 在我们的示例中,此代码负责处理响应。 (你可以在 index.ts 文件中找到它。)
const redirectUriPath = '/close';
const url = new URL(window.location.href);
if (url.pathname?.startsWith(redirectUriPath)) {
// Handle errors, Please refer to https://free.blessedness.top/entra/identity-platform/reference-error-codes
if (url?.hash?.includes("error")) {
// Handle missing service principal error
if (url.hash.includes("AADSTS650052")) {
printFormattedAADErrorMessage(url?.hash);
// handle user declined the consent error
} else if (url.hash.includes("AADSTS65004")) {
printFormattedAADErrorMessage(url?.hash);
}
}
// Always close the window
window.close();
}
工作负载前端可以从 URL 中提取错误代码,并进行相应处理。
注意
在这两种情况下(错误和成功),工作任务必须始终立即关闭窗口,且不会延迟。