PowerBI 和 Azure AD 无头登录
PowerBI and Azure AD Headless Login
我正在尝试将 PowerBI 仪表板嵌入到我的客户 MVC 门户中。我的客户没有AAD账号,所以他们来网站的时候不能登录Live,他们是用个人权限登录我的MVC网站。
我已经在 PowerBI/AAD 上注册了我的应用程序并拥有 ClientID 和 Secret。我调用 AAD 并获得一个授权码,然后我用它来获得一个成功返回的认证令牌。
每当我使用访问令牌获取仪表板时,它都会被 403 Forbidden 不断拒绝。
我已经查看了 Microsoft 的所有示例,但它们需要用户登录提示。我查看了引用 AcquireToken 方法的 ADAL2.0 代码,但这在 ADAL3 中已弃用并替换为具有不同参数的 AcquireTokenAsync,我在下面的示例中使用了它。
获取令牌的函数如下:
protected AuthenticationResult GetAccessToken()
{
string pBiUser = Properties.Settings.Default.PowerBIUser;
string pBiPwd = Properties.Settings.Default.PowerBIPwd;
string pBiClientId = Properties.Settings.Default.PowerBIClientId;
string pBiSecret = Properties.Settings.Default.PowerBIClientSecret;
TokenCache TC = new TokenCache();
ClientCredential CC = new ClientCredential(pBiClientId,pBiSecret);
string AU = Properties.Settings.Default.PowerBIAuthority;
Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext authenticationContext
= new Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext(AU, TC);
AuthenticationResult result = authenticationContext.AcquireTokenAsync("https://analysis.windows.net/powerbi/api"
,CC).Result;
if (result == null)
{
throw new InvalidOperationException("Failed to obtain the PowerBI token");
}
return result;
}
然后我拿到结果令牌并调用。 响应 收到 403:
protected PBIDashboards GetDashboards(AuthenticationResult authResult)
{
PBIDashboards pbiDashboards = new PBIDashboards();
var baseAddress = new Uri("https://api.powerbi.com");
using (var httpClient = new System.Net.Http.HttpClient {BaseAddress = baseAddress})
{
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("authorization",
"Bearer " + authResult.AccessToken);
using (**var response** = httpClient.GetAsync("v1.0/myorg/dashboards").Result)
{
string responseData = response.Content.ReadAsStringAsync().Result;
//Deserialize JSON string
pbiDashboards = JsonConvert.DeserializeObject<PBIDashboards>(responseData);
if (pbiDashboards != null)
{
var gridViewDashboards = pbiDashboards.value.Select(dashboard => new
{
Id = dashboard.id,
DisplayName = dashboard.displayName,
EmbedUrl = dashboard.embedUrl
});
}
}
}
return pbiDashboards;
}
根据错误信息(403
),问题与权限有关。
据我所知,当我们使用 Power BI REST 的 客户端凭据流 获取访问令牌时,我们无法使用此类权限。可以参考下图的权限:
要在无需用户交互的情况下获取 Power BI REST 的令牌,我们可以使用资源所有者密码凭据流程。您可以使用已经实现此功能的第 3 方库 PowerBI.Api.Client。
经过大量研究,您可以直接AJAX调用获取令牌:
private async Task<string> GetAccessToken()
{
string pBiUser = Properties.Settings.Default.PowerBIUser;
string pBiPwd = Properties.Settings.Default.PowerBIPwd;
string pBiClientId = Properties.Settings.Default.PowerBIClientId;
string pBiSecret = Properties.Settings.Default.PowerBIClientSecret;
string pBITenant = Properties.Settings.Default.PowerBITenantId;
string tokenEndpointUri = "https://login.microsoftonline.com/"+pBITenant+"/oauth2/token";
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("grant_type", "password"),
new KeyValuePair<string, string>("username", pBiUser),
new KeyValuePair<string, string>("password", pBiPwd),
new KeyValuePair<string, string>("client_id", pBiClientId),
new KeyValuePair<string, string>("client_secret", pBiSecret),
new KeyValuePair<string, string>("resource", "https://analysis.windows.net/powerbi/api")
});
using (var client = new HttpClient())
{
HttpResponseMessage res = client.PostAsync(tokenEndpointUri, content).Result;
string json = await res.Content.ReadAsStringAsync();
AzureAdTokenResponse tokenRes = JsonConvert.DeserializeObject<AzureAdTokenResponse>(json);
return tokenRes.AccessToken;
}
}
获得字符串 AccessToken 后,即可调用 Dashboards 请求。
protected PBIDashboards GetDashboards(string token)
{
PBIDashboards pbiDashboards = new PBIDashboards();
var baseAddress = new Uri("https://api.powerbi.com");
using (var httpClient = new System.Net.Http.HttpClient {BaseAddress = baseAddress})
{
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("authorization",
"Bearer " + token);
using (var response = httpClient.GetAsync("v1.0/myorg/dashboards").Result)
{
string responseData = response.Content.ReadAsStringAsync().Result;
//Deserialize JSON string
pbiDashboards = JsonConvert.DeserializeObject<PBIDashboards>(responseData);
if (pbiDashboards != null)
{
var gridViewDashboards = pbiDashboards.value.Select(dashboard => new
{
Id = dashboard.id,
DisplayName = dashboard.displayName,
EmbedUrl = dashboard.embedUrl
});
}
}
}
return pbiDashboards;
}
这将为您提供仪表板列表和仪表板 ID,以调用 PowerBI API 在 Javascript 中构建嵌入页面。我使用隐藏的输入字段来存储访问令牌并嵌入 URL 以传递给 Javascript 调用。
// check if the embed url was selected
var embedUrl = document.getElementById('embed').value;
if (embedUrl === "")
return;
// get the access token.
accessToken = document.getElementById('token').value;
// Embed configuration used to describe the what and how to embed.
// This object is used when calling powerbi.embed.
// You can find more information at https://github.com/Microsoft/PowerBI-JavaScript/wiki/Embed-Configuration-Details.
var config = {
type: 'dashboard',
accessToken: accessToken,
embedUrl: embedUrl
};
// Grab the reference to the div HTML element that will host the dashboard.
var dashboardContainer = document.getElementById('dashboard');
// Embed the dashboard and display it within the div container.
var dashboard = powerbi.embed(dashboardContainer, config);
我正在尝试将 PowerBI 仪表板嵌入到我的客户 MVC 门户中。我的客户没有AAD账号,所以他们来网站的时候不能登录Live,他们是用个人权限登录我的MVC网站。
我已经在 PowerBI/AAD 上注册了我的应用程序并拥有 ClientID 和 Secret。我调用 AAD 并获得一个授权码,然后我用它来获得一个成功返回的认证令牌。
每当我使用访问令牌获取仪表板时,它都会被 403 Forbidden 不断拒绝。
我已经查看了 Microsoft 的所有示例,但它们需要用户登录提示。我查看了引用 AcquireToken 方法的 ADAL2.0 代码,但这在 ADAL3 中已弃用并替换为具有不同参数的 AcquireTokenAsync,我在下面的示例中使用了它。
获取令牌的函数如下:
protected AuthenticationResult GetAccessToken()
{
string pBiUser = Properties.Settings.Default.PowerBIUser;
string pBiPwd = Properties.Settings.Default.PowerBIPwd;
string pBiClientId = Properties.Settings.Default.PowerBIClientId;
string pBiSecret = Properties.Settings.Default.PowerBIClientSecret;
TokenCache TC = new TokenCache();
ClientCredential CC = new ClientCredential(pBiClientId,pBiSecret);
string AU = Properties.Settings.Default.PowerBIAuthority;
Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext authenticationContext
= new Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext(AU, TC);
AuthenticationResult result = authenticationContext.AcquireTokenAsync("https://analysis.windows.net/powerbi/api"
,CC).Result;
if (result == null)
{
throw new InvalidOperationException("Failed to obtain the PowerBI token");
}
return result;
}
然后我拿到结果令牌并调用。 响应 收到 403:
protected PBIDashboards GetDashboards(AuthenticationResult authResult)
{
PBIDashboards pbiDashboards = new PBIDashboards();
var baseAddress = new Uri("https://api.powerbi.com");
using (var httpClient = new System.Net.Http.HttpClient {BaseAddress = baseAddress})
{
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("authorization",
"Bearer " + authResult.AccessToken);
using (**var response** = httpClient.GetAsync("v1.0/myorg/dashboards").Result)
{
string responseData = response.Content.ReadAsStringAsync().Result;
//Deserialize JSON string
pbiDashboards = JsonConvert.DeserializeObject<PBIDashboards>(responseData);
if (pbiDashboards != null)
{
var gridViewDashboards = pbiDashboards.value.Select(dashboard => new
{
Id = dashboard.id,
DisplayName = dashboard.displayName,
EmbedUrl = dashboard.embedUrl
});
}
}
}
return pbiDashboards;
}
根据错误信息(403
),问题与权限有关。
据我所知,当我们使用 Power BI REST 的 客户端凭据流 获取访问令牌时,我们无法使用此类权限。可以参考下图的权限:
要在无需用户交互的情况下获取 Power BI REST 的令牌,我们可以使用资源所有者密码凭据流程。您可以使用已经实现此功能的第 3 方库 PowerBI.Api.Client。
经过大量研究,您可以直接AJAX调用获取令牌:
private async Task<string> GetAccessToken()
{
string pBiUser = Properties.Settings.Default.PowerBIUser;
string pBiPwd = Properties.Settings.Default.PowerBIPwd;
string pBiClientId = Properties.Settings.Default.PowerBIClientId;
string pBiSecret = Properties.Settings.Default.PowerBIClientSecret;
string pBITenant = Properties.Settings.Default.PowerBITenantId;
string tokenEndpointUri = "https://login.microsoftonline.com/"+pBITenant+"/oauth2/token";
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("grant_type", "password"),
new KeyValuePair<string, string>("username", pBiUser),
new KeyValuePair<string, string>("password", pBiPwd),
new KeyValuePair<string, string>("client_id", pBiClientId),
new KeyValuePair<string, string>("client_secret", pBiSecret),
new KeyValuePair<string, string>("resource", "https://analysis.windows.net/powerbi/api")
});
using (var client = new HttpClient())
{
HttpResponseMessage res = client.PostAsync(tokenEndpointUri, content).Result;
string json = await res.Content.ReadAsStringAsync();
AzureAdTokenResponse tokenRes = JsonConvert.DeserializeObject<AzureAdTokenResponse>(json);
return tokenRes.AccessToken;
}
}
获得字符串 AccessToken 后,即可调用 Dashboards 请求。
protected PBIDashboards GetDashboards(string token)
{
PBIDashboards pbiDashboards = new PBIDashboards();
var baseAddress = new Uri("https://api.powerbi.com");
using (var httpClient = new System.Net.Http.HttpClient {BaseAddress = baseAddress})
{
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("authorization",
"Bearer " + token);
using (var response = httpClient.GetAsync("v1.0/myorg/dashboards").Result)
{
string responseData = response.Content.ReadAsStringAsync().Result;
//Deserialize JSON string
pbiDashboards = JsonConvert.DeserializeObject<PBIDashboards>(responseData);
if (pbiDashboards != null)
{
var gridViewDashboards = pbiDashboards.value.Select(dashboard => new
{
Id = dashboard.id,
DisplayName = dashboard.displayName,
EmbedUrl = dashboard.embedUrl
});
}
}
}
return pbiDashboards;
}
这将为您提供仪表板列表和仪表板 ID,以调用 PowerBI API 在 Javascript 中构建嵌入页面。我使用隐藏的输入字段来存储访问令牌并嵌入 URL 以传递给 Javascript 调用。
// check if the embed url was selected
var embedUrl = document.getElementById('embed').value;
if (embedUrl === "")
return;
// get the access token.
accessToken = document.getElementById('token').value;
// Embed configuration used to describe the what and how to embed.
// This object is used when calling powerbi.embed.
// You can find more information at https://github.com/Microsoft/PowerBI-JavaScript/wiki/Embed-Configuration-Details.
var config = {
type: 'dashboard',
accessToken: accessToken,
embedUrl: embedUrl
};
// Grab the reference to the div HTML element that will host the dashboard.
var dashboardContainer = document.getElementById('dashboard');
// Embed the dashboard and display it within the div container.
var dashboard = powerbi.embed(dashboardContainer, config);