Power BI Embedded for mere mortals | by Yousry Mohamed | Towards Data Science

Power BI has become one of the most powerful and commonly used data visualization and analytical tools in the market. It has many amazing features but one of the cool ones I like most is the embedding feature. In a nutshell, Power BI Embedded allows rendering any published report as a part of an independent web application. I feel some nostalgia with SharePoint webparts now 😂. This means users are not limited or required to have Power BI licenses. This use case is very useful for ISVs developing web apps empowered by Power BI.
Power BI Embedded has been introduced around 2018 if my memory helps me. It was bound initially to something called workspace collections which has been retired now. The API changed somehow since the initial release and also new services like Power BI Premium has been released to serve more enterprise-y scenarios. I have done Power BI Embedded using the old workspace collections and wanted to try the latest API and see how it works. Being a pragmatic person, my motive was to embed a visualization of an optimization problem solution in a web app. The optimization is done using Google OR-Tools and I found lots of cool visuals to show the solution which are more appealing than rendering stuff like HTML tables.
But as we know life is not always rainbows and flying unicorns. Microsoft documentation is generally pretty good but for Power BI Embedded it leaves a few items here and there a bit vague. So I wanted to prepare a simple instructions manual on how to use Power BI Embedded using one of the common cases which is sometimes called “App Owns Data”. The concept is easy, the application has full access to the report and underlying data and the report is rendered in one of the application pages. Users are not required to authenticate with Power BI. They can see and interact with the report in a seamless fashion.
So if you like Power BI, let’s see how to embed it!
Because not everyone has an active Power BI license, it’s would be better to start with a free Office 365 E3 trial subscription and register for a one month Trial Power BI Pro license within that tenant. No credit card info is even required for Office 365 nor Power BI Pro. The Office 365 tenant comes with a bundled Azure Active Directory which is needed in this process.
The following tools will be used throughout this tutorial:
Power BI Desktop
.NET Core 3.1 SDK
Visual Studio Code
NodeJs
We can pick any Power BI report to use here but I wanted to use a report with Direct Query data source. The reason is that Direct Query might be very useful for embedding scenarios as we don’t need to worry about data refresh and so on. So I started by creating an Azure SQL database initialized with AdeventureWorksLT database. I have an Azure subscription other than the Office 365 trial thing mentioned before so don’t get confused. A report using Import mode would just work fine as well. So if you don’t have access to an Azure SQL database, create any report in Power BI desktop and skip a few paragraphs till creating the workspace and publishing the report steps.
Once the database is created, we have to configure firewall rules (of the underlying SQL server) to allow access from other Azure services plus my local machine.
After that, we can create a new Power BI report (using Power BI desktop of course) to visualize anything related to our sample data like sales per each customer. As I mentioned, the report is designed with a Direct Query data source to allow real time reflection of database state.
There is nothing special about the report to be used and in my case it resembles a simple SELECT SUM(Amount) FROM Sales GROUP BY Customer statement.
This report has to be published to be accessible later by Power BI Embedded. But to publish it, we have to have a workspace first. Log in to Power BI using the admin account of the Office 365 tenant and create a workspace as below to host the report.
Then publish the report from Power BI desktop into the above workspace. For reports with direct query mode, you will be asked to re-enter the credentials of the datasets in your report but other than that, the report should work fine from the browser.
To make embedding as much seamless as possible in our case, we will use a service principal. Think about it as a service account granted just enough permissions on a certain resource(s) such that an application can call APIs against this resource using the credentials assigned to this service principal.
To create a service principal, open Azure AD linked with our Office 365 tenant. Just open portal.azure.com and use the same admin credentials to log in. From the side menu or search box, locate Azure Active Directory and click the link named App Registrations. From this page click New Registration. Just provide a name and click Create.
Once created, we need to take a note of application and tenant Ids because we will need them later. Some two identifiers are sometimes called client Id and tenant Id.
I have mentioned that a service principal has some sort of a credential. Within the same page of the current application, click Certificates & secrets and create a client secret and copy the value as it will not be accessible after that. The description of the client secret is arbitrary though.
One final step to do in Azure AD, is to create a group and add the newly created service principal as a group member. We will see why this is required later but for now, click the Groups link in Azure AD home page and create a new group (of type security) named Power BI Embedding Users and within the creation page include the service principal created before as a member of this group.
Now we are done with Azure AD having created a service principal, we need to switch over to our Power BI website (https://app.powerbi.com) to grant access to the service principal on the workspace created before. But to allow Power BI to use service principals it has to be configured first to allow that. From Power BI cog button, select admin portal.
Click Tenant Settings menu item, and then make sure to enable the toggle Embed content in apps and select Specify security groups and add the security group we created before.
Do the same for Allow service principals to use Power BI APIs.
Next, open workspace page in Power BI and select Workspace access.
Then search for the service principal and add it as an admin.
Phew, that was a lot of house keeping to prepare for the embedding but we are nearly there. The general pattern of the remaining task would be as follows:
Develop a web app with a backend web API
The backend web API is responsible for generating an embed token using the service principle info/credentials stored at the backend
The frontend will use the embed token to render the report
Sounds easy, let’s do it.
First, create (actually scaffold) a react web app with a dotnet core backend web API.
dotnet new react -o EmbedWebcd .\EmbedWeb\cd .\ClientApp\npm installnpm install caniuse-lite@latest --save
The caniuse-lite line is required because the current template at the time of writing has an outdated dependency which prevents running the app so it’s required to upgrade this npm dependency.
Now open EmbedWeb folder using Visual Studio Code and fire up a terminal window using Ctrl + ` . In the terminal window, execute dotnet watch run .
Let’s hit the HTTPS URL and see if the application is alive.
Cool, all good for now. In a second terminal window add a couple backend nuget packages responsible for interacting with Azure AD & Power BI REST API. That will trigger another build in the first terminal window and in a few seconds the web site should be responsive if you want to make sure nothing is broken.
dotnet add package Microsoft.Identity.Clientdotnet add package Microsoft.PowerBI.Api
In the root of EmbedWeb folder, add a new file named Embedder.cs and copy the following content into it.
You will need to update the values for client Id, client secret and tenant Id. Those values are found in the home page of the service principal created in Azure AD. Save the file with your own values and make sure it builds fine in the terminal window of dotnet watch .
Here is a brief explanation of this file:
GetAppOnlyAccessToken is responsible for generating an access token to call Power BI REST API. This method uses the new Microsoft Authentication Library for .NET (MSAL.NET) found in nuget package Microsoft.Identity.Client.GetPowerBiClient uses this access token to instantiate a class that abstracts REST calls against Power BI API so that we can simply call methods and get typed responses and so on. That’s the whole point of Power BI SDK found in nuget package Micorsoft.PowerBI.Api .GetEmbedInfo method uses Power BI SDK client object to get report metadata and generate an embed token. The call to generate embed token is configured to get a token allowing editing by the way. There is lots to say about RBAC and security but for now, let’s say we can have tokens for View Only mode or Edit mode if we want.
GetAppOnlyAccessToken is responsible for generating an access token to call Power BI REST API. This method uses the new Microsoft Authentication Library for .NET (MSAL.NET) found in nuget package Microsoft.Identity.Client.
GetPowerBiClient uses this access token to instantiate a class that abstracts REST calls against Power BI API so that we can simply call methods and get typed responses and so on. That’s the whole point of Power BI SDK found in nuget package Micorsoft.PowerBI.Api .
GetEmbedInfo method uses Power BI SDK client object to get report metadata and generate an embed token. The call to generate embed token is configured to get a token allowing editing by the way. There is lots to say about RBAC and security but for now, let’s say we can have tokens for View Only mode or Edit mode if we want.
This Embedder class is a helper class to be called from a web API controller so that creating the embed token is done at the backend side. Also it’s simplified to have the service principal details hardcoded directly into it.
Side note: Resources section at the end of this post has a couple of YouTube videos by Ted Pattison explaining lots of other useful details around authentication modes for Power BI Embedding.
We are done with the helper class, so it’s time to have a web API controller. Add a new file called EmbeddingController.cs but this time it has to go into the controllers folder and paste the following snippet inside it.
You will have to provide the Ids of your workspace and report. If you wonder how to get those things, there is an easy trick. Just open the report published on Power BI and inspect the URL in the browser address bar.
https://app.powerbi.com/groups/<GUID1>/reports/<GUID2>/ReportSection
GUID1 is the workspace Id and GUID2 is the report Id. Now save the file and make sure build is successful. To make sure that our backend part is functional, open a new PowerShell window and curl the web API endpoint which is supposed to be https://localhost:5001/embedding.
Backend part is done and dusted so the next step which is the ultimate goal is to have an HTML page in our web app to render the report same as Power BI service does.
Likewise the Power BI SDK nuget package, there is also an npm one for the JavaScript world. This npm package can be used to do many things but we will tap into the embedding part only.
In a terminal window other than the build/watch one, add Power BI npm package.
cd .\ClientApp\npm install --save powerbi-client
Now replace the contents of ClientApp\src\Components\Home.js react file with the following content.
The above snippet simply does two things:
Call web API endpoint to get embedding token
Use Power BI JavaScript library to embed the report using the obtained embed token.
Also, add the following CSS snippet to custom.css file to give some realestate to the rendered report.
.full-width{    width: 100%;    height: 800px;}
Now head off to the browser and refresh the page.
Sweet, embedding works and because we enabled editing at both frontend and backend sides, we can even edit the report and save changes.
One final bit to test is Direct Query mode. It’s not a core thing related to embedding but something to try as well. So, let’s randomize the total due amount per each customer order (which is a computed column involving sub total column).
UPDATE [SalesLT].[SalesOrderHeader]SET SubTotal = ABS(CHECKSUM(NewId())) % 120000
Now refresh the page and you will get a totally different pattern reflecting the current state of database. Direct Query is pretty cool specially of the source data is nearly pre-aggregated or easy to pull.
I hope you understand now the core moving parts involved in Power BI embedding workflow. There are other items to think about and resources section below has a few pointers here and there. Another thing to highlight, is the need to have Power BI dedicated capacity for a production environment.
Quoting a bit of the documentation:
Using embed tokens with Pro licenses are intended for development testing, so the number of embed tokens a Power BI master account or service principal can generate is limited. A dedicated capacity requires embedding in a production environment. There’s no limit on how many embed tokens you can generate with a dedicated capacity.
In a nutshell, easiest way to have a dedicated capacity is to create an Azure Power BI Embedded resource. It’s billed by hour and can be paused/restarted to save costs.
Then link it with the workspace containing the reports to be embedded.
Happy embedding 😀