Power Bi Embedded with PHP CURL- App Owns Data

Power BI Embedded will enable you to embed powerful Dashboards, Reports, and Tiles into your application. An ISV can leverage the continuous development efforts from the Microsoft Power Bi team and embed several types of reports for their users and customers, while branding the application with their Logo and color scheme.
Before you get started, you will need to double check the business requirements. Are you embedding for organization users? External users such as customers, vendors, or suppliers? Embedding in SharePoint or Microsoft Teams? Embedding a public dashboard that’s using a public dataset?
This discovery stage is very important, as you might not need to program anything, if you are embedding a Power bi Dashboard into a SharePoint site, or if you are publishing an iframe of a “Publish to Web” URL with a public dataset or unsecure content.
PBI embedded requires you to buy one of the three SKUs below:


There are three areas where you must do some work to create this solution:
1- Power BI: You need a Power BI pro account to be able to create an app workspace, which will be the container of your reports and dashboards that you will embed. In Addition, you will need either an Azure power bi embedded subscription, or a Power bi premium subscription to allow your users to consume the reports.


Then you will need to link your app workspace to your provisioned capacity.

2- Microsoft Azure: This is where you need to register an Azure AD application that will give you the credentials to allow you to embed Power BI content. This is discussed in more details below. If you are going to use the Azure PBI embedded resource, then you would need to add the resource capacity here as well.

3- Your Application: You can host it anywhere, use any programming language to communicate with Azure AD and Power BI REST API. You will also need to download or link to the power bi JavaScript library.
Once you ascertain that you will need power bi embedded into your own application, you would need to decide between the two types of embedding:
User owns Data: This is for a scenario where an organization wants users to login to their website and see their PBI reports. Users need to have a Power BI account either free or Pro, and the organization needs to provision Premium Capacity
App owns Data: This is a scenario for organizations that will be serving reports to customers that don’t have a power bi license, and usually unaware that the reports are provided by power bi. At least one Power bi Pro user will be required to create the app workspace and reports, as well as either Azure power bi embedded capacity (A SKU) or Office premium capacity (P SKU).
This article will discuss embedding for the “APP owns Data” Scenario, so lets’ get started.
First, study the image below, as you will programmatically need to go through this Authorization Grant Flow to access the power bi resource:


Step 1: Get an OATH2 token through a CURL POST request to the Azure AD API.
To get started with step 1, we must register an application in Azure AD. You can do that through the Azure management portal > Azure Active Directory > App registrations. Make sure you register a native application not a web app.

You can also use the Power BI App Registration tool. After you register the app, you need to assign it the required permissions as illustrated in this updated article.
You are ready to get started with coding: (The code below is mixed with comments and image illustrations. You can download the complete source from GitHub.)

<?php $curl1 = curl_init(); curl_setopt_array($curl1, array( CURLOPT_URL => "https://login.windows.net/common/oauth2/token",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => array(
grant_type => 'password',
scope => 'openid',
resource => 'https://analysis.windows.net/powerbi/api',
client_id => ' ', // Registered App Application ID

username => ' ', // Your Power BI Pro account. For example john.doe@yourdomain.com
password => ''  // Password for above user
)
));
$tokenResponse = curl_exec($curl1);
$tokenError = curl_error($curl1);
curl_close($curl1);
// decode result, and store the access_token in $embeddedToken variable:
$tokenResult = json_decode($tokenResponse, true);
$token = $tokenResult["access_token"];
$embeddedToken = "Bearer "  . ' ' .  $token;

The above code has accomplished the following:
Application identity with OAuth 2.0 client credentials grant
1. First, the server application needs to authenticate with Azure AD as itself, without any human interaction such as an interactive sign-on dialog. It makes a request to Azure AD’s token endpoint, providing the credential, Application ID, and application ID URI.
2. Azure AD authenticates the application and returns a JWT access token that is used to call the web API.
The code below will accomplish the third step in the authentication/authorization process:
3- Over HTTPS, the web application uses the returned JWT access token to add the JWT string with a “Bearer” designation in the Authorization header of the request to the web API. The web API then validates the JWT token, and if validation is successful, returns the desired resource.
Let’s define what a group is before introducing a group id in the code, because it’s a very important concept, and understanding it will save you time going forward.
Groups are a collection of unified Azure Active Directory groups that the user is a member of and is available in the Power BI service. These are referred to as app workspaces within the Power BI service. To learn how to create a group, see Create an app workspace.
/* Use the token to get an embedded URL using a GET request */
$group_Id = 'f6xzs20-850b-04az-9hga-3d00087191'; // Your power bi app workspace group id.

Easiest way to get your group id is by browsing to your app workspace in Power BI, and getting the alphanumerical string after groups in the URL. You can also get it programmability through a REST call.

/*Use the token to get an embedded URL using a GET request */
$group_Id = ' ';
$curl2 = curl_init();
curl_setopt($curl2, CURLOPT_URL, 'https://api.powerbi.com/v1.0/myorg/groups/'.$group_Id.'/reports/');
curl_setopt($curl2, CURLOPT_RETURNTRANSFER, trUE);
curl_setopt($curl2, CURLOPT_ENCODING, "");
curl_setopt($curl2, CURLOPT_MAXREDIRS, 10);
curl_setopt($curl2, CURLOPT_TIMEOUT, 30);
curl_setopt($curl2, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($curl2, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt ($curl2, CURLOPT_HTTPHEADER,array(

        'Authorization:'.$embeddedToken,
        'Cache-Control: no-cache'
    ));

$embedResponse  = curl_exec($curl2);
$embedError = curl_error($curl2);
curl_close($curl2);

if ($embedError) {

echo "cURL Error #:" . $embedError;

} else {

$embedResponse = json_decode($embedResponse, true);

$embedUrl = $embedResponse['value'][1]['embedUrl'];

}
?>

Now that our application has retrieved the bearer Token from Azure AD, and it presented it to Power BI REST API along with a group id where the reports reside. The REST service will return an array with the report names, their ID, embed URL, and some other data.
Next, we will use jQuery and Power BI JavaScript file to render the report:

<?php
include 'pbi-logic.php';
include 'header.php'; ?>
<div id="reportContainer"></div>
<script>
// 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 embedConfiguration= {
type: 'report',
id: ' ', // the report ID
embedUrl: "<?php echo $embedUrl ?>",
accessToken: "<?php echo $token; ?>" ,
};
var $reportContainer = $('#reportContainer');
var report = powerbi.embed($reportContainer.get(0), embedConfiguration);
</script>
</body>
</html>

You should be done now. Make the required changes to the embed configuration as needed to turn on and off different aspects of your report, dashboard, or tile. To create a report from your application, for instance, you need to supply a dataset:

var embedCreateConfiguration= {
type: 'report',
datasetId: ' ', // dataset ID
embedUrl: "<?php echo $embedUrl ?>",
accessToken: "<?php echo $token; ?>" ,
};
var $embedContainer = $('#reportContainer');
// Create report
var report = powerbi.createReport($embedContainer.get(0), embedCreateConfiguration);

// Report.off removes a given event handler if it exists.
report.off("loaded");

// Report.on will add an event handler which prints to Log window.
report.on("loaded", function() {
    Log.logText("Loaded");
});
report.off("error");
report.on("error", function(event) {
    Log.log(event.detail);
});
// report.off removes a given event handler if it exists.
report.off("saved");
report.on("saved", function(event) {
    Log.log(event.detail);
    Log.logText('In order to interact with the new report, create a new token and load the new report');
});
</script>
</body>
</html>

Power bi embedded for ISV will save you a lot of time, provide you with a lot of flexibility, and will offer you continuous development and enhancements. I have written this article to help fellow developers, especially if you don’t know .net to be able to follow the samples available from Microsoft.
Find a link to my GitHub repo, where you can download the working code tested on Apache/PHP7.
Links to websites that helped me along the way:

https://docs.microsoft.com/en-us/power-bi/developer/embedded-faq

https://github.com/Microsoft/PowerBI-JavaScript

https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-authentication-scenarios#web-application-to-web-api

http://www.msbiblog.com/2018/01/12/power-bi-embedded-example-using-curl-and-php/