Reputation: 156
I am working with an ASP.NET Core 3.1 MVC application where I am attempting to implement Power BI in embedded view using the "App Owns Data" scenario and using a Service Principal.
I can successfully connect to the Power BI service using said Service Principal. I am able to retrieve tokens without issue and pass them through to the Power BI service where I can retrieve a list of reports and view individual reports without issue (using powerbi.embed()
). However, when I call the powerbi.createReport()
JavaScript method, it always returns "This content is not available" along with a 403 response when viewing in Fiddler.
Generating an access token
private async Task<string> GetPowerBIAccessToken()
{
string pBiClientId = powerBISettings.ApplicationId.ToString();
string pBiSecret = powerBISettings.ApplicationSecret.ToString();
var clientCredentials = new ClientCredential(pBiClientId, pBiSecret);
var authContext = new AuthenticationContext($"{powerBISettings.AuthorityUrl}/{powerBISettings.TenantId}", new TokenCache());
var token = await authContext.AcquireTokenAsync(powerBISettings.ResourceUrl, clientCredentials);
return token.AccessToken;
}
Code to generate a model to view a Power BI report
public async Task<EmbedConfig> ViewReport(Guid ReportId)
{
var result = new EmbedConfig { };
var accessToken = await GetPowerBIAccessToken();
var tokenCredentials = new TokenCredentials(accessToken, "Bearer");
using (var client = new PowerBIClient(new Uri(powerBISettings.ApiUrl), tokenCredentials))
{
var workspaceId = powerBISettings.WorkspaceId.Value;
var reports = await client.Reports.GetReportsInGroupAsync(workspaceId);
var report = reports.Value.Where(a => a.Id == ReportId).FirstOrDefault();
var generateTokenRequestParameters = new GenerateTokenRequest(accessLevel: "view");
var tokenResponse = await client.Reports.GenerateTokenAsync(workspaceId, report.Id, generateTokenRequestParameters);
result.EmbedToken = tokenResponse;
result.EmbedUrl = report.EmbedUrl;
result.Id = report.Id == null ? string.Empty : report.Id.ToString();
}
return result;
}
MVC view with embedded report to view above report - this works!
<style>
#reportContainer {
height: 600px;
width: 100%;
max-width: 2000px;
}
</style>
<script src="https://npmcdn.com/[email protected]"></script>
<script src="~/js/powerbi.min.js"></script>
<div id="reportContainer"></div>
@section scripts {
<script>
// Read embed application token from Model
var accessToken = "@Model.EmbedToken.Token";
// Read embed URL from Model
var embedUrl = "@Html.Raw(Model.EmbedUrl)";
// Read report Id from Model
var embedReportId = "@Model.Id";
// Get models. models contains enums that can be used.
var models = window['powerbi-client'].models;
// Embed configuration used to describe the what and how to embed.
// This object is used when calling powerbi.embed.
// This also includes settings and options such as filters.
// You can find more information at https://github.com/Microsoft/PowerBI-JavaScript/wiki/Embed-Configuration-Details.
var config = {
type: 'report',
tokenType: models.TokenType.Embed,
accessToken: accessToken,
embedUrl: embedUrl,
id: embedReportId,
permissions: models.Permissions.All,
settings: {
filterPaneEnabled: true,
navContentPaneEnabled: true
}
};
$(document).ready(function () {
// Get a reference to the embedded report HTML element
var reportContainer = $('#reportContainer')[0];
// Embed the report and display it within the div container.
powerbi.embed(reportContainer, config);
});
</script>
}
Code to generate the Model to create a new blank report
public async Task<EmbedConfig> CreateNewReport()
{
var result = new EmbedConfig { };
var accessToken = await GetPowerBIAccessToken();
var tokenCredentials = new TokenCredentials(accessToken, "Bearer");
using (var client = new PowerBIClient(new Uri(powerBISettings.ApiUrl), tokenCredentials))
{
var workspaceId = powerBISettings.WorkspaceId.Value;
var generateTokenRequestParameters = new GenerateTokenRequest(TokenAccessLevel.Create, datasetId: "xyz", allowSaveAs: true);
var tokenResponse = await client.Reports.GenerateTokenForCreateInGroupAsync(workspaceId, generateTokenRequestParameters);
result.EmbedToken = tokenResponse;
result.DatasetId = "xyz";
}
return result;
}
MVC view to with embedded create report - doesn't work
<style>
#reportContainer {
height: 600px;
width: 100%;
max-width: 2000px;
}
</style>
<script src="https://npmcdn.com/[email protected]"></script>
<script src="~/js/powerbi.min.js"></script>
<div id="reportContainer"></div>
@section scripts {
<script>
// Read embed application token from Model
var accessToken = '@Model.EmbedToken.Token';
// Get models. models contains enums that can be used.
var models = window['powerbi-client'].models;
// Embed configuration used to describe the what and how to embed.
// This object is used when calling powerbi.embed.
// This also includes settings and options such as filters.
// You can find more information at https://github.com/Microsoft/PowerBI-JavaScript/wiki/Embed-Configuration-Details.
var config = {
accessToken: accessToken,
datasetId: '@Model.DatasetId',
embedUrl: 'https://embedded.powerbi.com/ReportEmbed'
};
$(document).ready(function () {
// Get a reference to the embedded report HTML element
var reportContainer = $('#reportContainer')[0];
// Embed the report and display it within the div container.
powerbi.createReport(reportContainer, config);
});
</script>
}
When the above view is loaded it returns this
Fiddler captures a 403 response
Does anybody know why this could be happening? The Service Principal has all API permissions assigned to the Power BI service (I followed the 'Create App' wizard within Power BI to create an App Registration in Azure AD). I just can't figure out why it keeps returning 403 - any help would be appreciated!
Upvotes: 2
Views: 271
Reputation: 369
In the documentation you linked it mentions the following:
When embedding, the minimum requirements are to have a type, embedUrl, accessToken and id.
In your example that doesnt work, you dont seem to have the tokenType specified. Just embedUrl, accessToken, and Id.
Upvotes: 0