azurepowerbipowerbi-embeddedazure-authenticationmicrosoft.identity.web

Trying to authenticate with Azure for using Power BI Embedded


Below is the output from an error which is being generated whilst trying to authenticate credentials with Azure for allowing public access to a Power BI Embedded report:

enter image description here

It has initially displayed a pop to confirm that I want to give but after I have given permission the above error is displayed.

I have checked the credentials I have entered in the appsettings.json file and have confirmed that they are correct.

In the Startup.cs file I have added this section:

services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
            .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"), "AzureAd")
            .EnableTokenAcquisitionToCallDownstreamApi(Configuration.GetValue<string>("DownstreamApi:Scopes")?.Split(' '))
            .AddMicrosoftGraph(Configuration.GetSection("DownstreamApi"))
            .AddInMemoryTokenCaches();
        
        services.AddScoped(typeof(PowerBiServiceApi));

        services.AddRazorPages()
            .AddMicrosoftIdentityUI();

The error itself is being generated whilst acquiring the access token in the PowerBiServiceApi the code for which is provided below:

using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Identity.Web;
using Microsoft.PowerBI.Api;
using Microsoft.PowerBI.Api.Models;
using Microsoft.Rest;

namespace NDTSM2.Services.Implementations.PowerBI
{
    // A view model class to pass the data needed to embed a single report.
    public class EmbeddedReportViewModel
    {
        public string Id;
        public string Name;
        public string EmbedUrl;
        public string Token;
    }


        public class PowerBiServiceApi
        {
            private ITokenAcquisition tokenAcquisition { get; }
            private string urlPowerBiServiceApiRoot { get; }
    
            public PowerBiServiceApi(IConfiguration configuration, ITokenAcquisition tokenAcquisition)
            {
                this.urlPowerBiServiceApiRoot = configuration["PowerBi:ServiceRootUrl"];
                this.tokenAcquisition = tokenAcquisition;
            }
    
            public const string powerbiApiDefaultScope = "https://analysis.windows.net/powerbi/api/.default";
    
            // A method to get the Azure AD token (also known as 'access token')
            public string GetAccessToken()
            {
                return this.tokenAcquisition.GetAccessTokenForAppAsync(powerbiApiDefaultScope).Result;
            }
    
            public PowerBIClient GetPowerBiClient()
            {
                var tokenCredentials = new TokenCredentials(GetAccessToken(), "Bearer");
                return new PowerBIClient(new Uri(urlPowerBiServiceApiRoot), tokenCredentials);
            }
            public async Task<EmbeddedReportViewModel> GetReport(Guid WorkspaceId, Guid ReportId)
            {
    
                PowerBIClient pbiClient = GetPowerBiClient();
    
                // Call the Power BI service API to get the embedding data
                var report = await pbiClient.Reports.GetReportInGroupAsync(WorkspaceId, ReportId);
    
                // Generate a read-only embed token for the report
                var datasetId = report.DatasetId;
                var tokenRequest = new GenerateTokenRequest(TokenAccessLevel.View, datasetId);
                var embedTokenResponse = await pbiClient.Reports.GenerateTokenAsync(WorkspaceId, ReportId, tokenRequest);
                var embedToken = embedTokenResponse.Token;
    
                // Return the report embedded data to caller
                return new EmbeddedReportViewModel
                {
                    Id = report.Id.ToString(),
                    EmbedUrl = report.EmbedUrl,
                    Name = report.Name,
                    Token = embedToken
                };
    
            }
        }
    
    }

Does anyone have any ideas why the error is being generated (have looked for guidance but so far none of the advice has rectified the issue)?

Any help would be very much appreciated.

Further to original question:

Error Details:

Operation returned an invalid status code 'Unauthorized'

at Microsoft.PowerBI.Api.ReportsOperations.GetReportInGroupWithHttpMessagesAsync(Guid groupId, Guid reportId, Dictionary`2 customHeaders, CancellationToken cancellationToken) at Microsoft.PowerBI.Api.ReportsOperationsExtensions.GetReportInGroupAsync(IReportsOperations operations, Guid groupId, Guid reportId, CancellationToken cancellationToken) at Microsoft.PowerBI.Api.ReportsOperationsExtensions.GetReportInGroup(IReportsOperations operations, Guid groupId, Guid reportId) at NDTSM2.Services.Implementations.PowerBI.PbiEmbedService.GetEmbedParams(Guid workspaceId, Guid reportId, Guid additionalDatasetId) in C:\Users\cryof\Desktop\NDTMS4\Service\NDTSM2.SERVICES\Implementations\PowerBI\PbiEmbedService.cs:line 41 at NDTMS2.Web.Controllers.EmbedInfoController.GetEmbedInfo() in C:\Users\cryof\Desktop\NDTMS4\NDTMS2.WEB\Controllers\EmbedInfoController.cs:line 40

The line that is generating the error in the PbiEmbedService is this:

        var pbiReport = pbiClient.Reports.GetReportInGroup(workspaceId, reportId);

Solution

  • Follow the sample here

    // For app only authentication, we need the specific tenant id in the authority url
    var tenantSpecificUrl = azureAd.Value.AuthorityUrl.Replace("organizations", azureAd.Value.TenantId);
    
    // Create a confidential client to authorize the app with the AAD app
    IConfidentialClientApplication clientApp = ConfidentialClientApplicationBuilder
                                                                    .Create(azureAd.Value.ClientId)
                                                                    .WithClientSecret(azureAd.Value.ClientSecret)
                                                                    .WithAuthority(tenantSpecificUrl)
                                                                    .Build();
    // Make a client call if Access token is not available in cache
    authenticationResult = clientApp.AcquireTokenForClient(azureAd.Value.ScopeBase).ExecuteAsync().Result;