cancel
Showing results for 
Search instead for 
Did you mean: 
Reply
adamwallace3
Advocate II
Advocate II

How To: Get embed token using Get/Post only

 

Step 1: Authorize App

Register App

I used a native app, it was the simplest solution. You can use a server-web app, but you will need to add client_secret anywhere you see client_id in this walkthrough. You will need to at least have read permissions enabled.

 

Step 2: Get Access Token (post)

 

POST: https://login.microsoftonline.com/common/oauth2/token
data: {
    grant_type: password
    scope: openid
    resource: https://analysis.windows.net/powerbi/api
    client_id: {Client ID}
    username: {PBI Account Username}
    password: {PBI Account Username}
}

--Returns Json:
 
{
    "token_type": "Bearer",
    "scope": "Report.Read.All ...",
    "expires_in": "xxxx",
    "ext_expires_in": "0",
    "expires_on": "xxxxxxxxxx",
    "not_before": "xxxxxxxxxxx",
    "resource": "https://analysis.windows.net/powerbi/api",
    "access_token": "eyJ0eXAi...",
    "refresh_token": "AQABA...",
    "id_token": "eyJ...."
}

 

 

Step 3: Get Report details:

This can be done two different ways. The simplest way is to navigate to your report on the Power Bi website and pull the report id and group id from the url.

https://app.powerbi.com/groups/{GROUP ID}/reports/{REPORT ID}/ReportSection

I needed to pull different reports from a given group, so here is the get request to do that.

 

GET https://api.powerbi.com/v1.0/myorg/groups/{GROUP ID}/reports
headers = {
Authorization: Bearer + {access_token from first post}
}

Returns Json:
{
    "@odata.context": "http://wabi-west-us-redirect.analysis.windows.net/v1.0/myorg/groups/.../$metadata#reports",
    "value": [
        {
            "id": "...",
            "modelId": 0,
            "name": "...",
            "webUrl": "...",
            "embedUrl": "https://app.powerbi.com/reportEmbed?reportId={REPORT ID}&groupId={GROUP ID}",
            "isOwnedByMe": true,
            "isOriginalPbixReport": false,
            "datasetId": "..."
        },
... Repeated for other Reports in Group
}

 

Step 4: Get Embed token

In the old Power Bi server (through Azure) you could encode your own embed token, in the September 2017 update Microsoft started to require that you use the rest api or one of the available SDKs.  In the "data" section you can pass arguments to implement row level security (link).

 

 

 

POST https://api.powerbi.com/v1.0/myorg/groups/{GROUP ID}/reports/{REPORT ID}/GenerateToken
headers = {
Authorization: Bearer + {access_token from first post}
Content-Type:application/json; charset=utf-8
Accept:application/json
}
data= {
  "accessLevel": "View",
  "allowSaveAs": "false"
}

Returns Json:
{
    "@odata.context": "http://wabi-west-us-redirect.analysis.windows.net/v1.0/myorg/groups/{GROUP_ID}/$metadata#Microsoft.PowerBI.ServiceContracts.Api.V1.GenerateTokenResponse",
    "token": "H4sIAAAAAAA...",
    "tokenId": "...",
    "expiration": "yyyy-mm-ddTxx:xxxxx"
}

 

Step 5: Test

  Go to the Microsoft Power BI Embedded Sample site (link) and test your report. 

The input fields are as follows:

You can also test the embedded report using the following :

<html>
<script src="https://microsoft.github.io/PowerBI-JavaScript/demo/node_modules/jquery/dist/jquery.js"></script>
<script src="https://microsoft.github.io/PowerBI-JavaScript/demo/node_modules/powerbi-client/dist/powerbi.js"></script>
<script type="text/javascript">

window.onload = function () {
var embedConfiguration = {
    type: 'report',
	accessToken: '{access_token}',
	embedUrl: 'https://app.powerbi.com/reportEmbed?reportId={REPORT ID}&groupId={GROUP ID}',
	id:'{REPORT ID}',
settings: {
              {settings_ from link}
            }
	}; 
var $reportContainer = $('#dashboardContainer');
var report = powerbi.embed($reportContainer.get(0), embedConfiguration);
}

function reloadreport(){
	var element = $('#dashboardContainer');
	alert(element);
	var report = powerbi.get(element);
	report.reload().catch(error => {console.log(error)  });
};
</script> 
<div id="dashboardContainer"></div>
</html>  

Notes:

Available settings can be found here.

 

Disclaimer:

This code comes with no warranty and no guarantees.  It is HIGHLY likely that Microsoft will change something and this walkthrough will become depreciated. Please check your PowerBi agreement to make sure that the steps listed in this walkthrough adhere to the agreed upon terms.

 

Tags:

Python, embedded, token, access token, get, post, REST API, ruby, PHP

 

 EDIT 1:

Added space to prevent 😮 and 😛 in code.

 

Edit 2:

Turned down sarcasm and added links.

34 REPLIES 34
alexbjorlig
Helper IV
Helper IV

Regarding the "Step 2: Get Access Token", how would you do this as a service principal?

To use service principal, use a grant type of `client_credentials` and replace the username and password with a client secret.

 

POST: https://login.microsoftonline.com/common/oauth2/token
data: {
    grant_type: client_credentials
    scope: openid
    resource: https://analysis.windows.net/powerbi/api
    client_id: {Client ID}
client_secret: {Client Secret} }

 

I am not sure about your "service principal" thing, But if you asked "How to do get the access token with code and not Postman to use it in an application in production?" here is my function in .NET Core 3.1 that calls my powerBI app registered in Azure in the 1st step:

 

using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;

public async Task<AccessTokenResponse> GetAccessTokenAsync(string clientId)
{
HttpClient client = new HttpClient();

//Build request body
Dictionary<string, string> data = new Dictionary<string, string>();
data.Add("grant_type", "password");
data.Add("scope", "openid");
data.Add("resource", "https://analysis.windows.net/powerbi/api");
data.Add("client_id", clientId);
data.Add("username", "{your powerBI username}");
data.Add("password", "{your powerBI password}");

//The .ToKeyValue() function is taken from https://blog.bitscry.com/2018/12/14/creating-formurlencodedcontent-variables-from-objects/
FormUrlEncodedContent content = new FormUrlEncodedContent(data.ToKeyValue());

//Call request
HttpResponseMessage response = await client.PostAsync("https://login.microsoftonline.com/common/oauth2/token", content);
//request validation
response.EnsureSuccessStatusCode();

//Convert response into my custom class AccessTokenResponse that represents the json Object but in c#
string jsonResult = await response.Content.ReadAsStringAsync();
AccessTokenResponse result = JsonConvert.DeserializeObject<AccessTokenResponse>(jsonResult);

return result;
}

I hope this helps!

Homeslyce
Regular Visitor

After HOURS of research and tests and everything nothing worked, I was goign to flip that table. Your post saved my week, so far the best how to I've seen on the subject.

 

Microsoft should hire you!

 

For those wondering, you better start with Postman or any other API test application to test the 1st and 3rd section.

rajulshah
Solution Sage
Solution Sage

Hello @adamwallace3,

 

Can you please guide me as to how secure this is?

jhabek
New Member

Hi there, I am trying to embed report with PHP curl. I got everything working, but when I am trying to implement row level security I got stuck.

First I get access token (this works):

 

$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' => '0aa12345-1234-1234-1234-123412341234', // registered App ApplicationID
'username' => 'name@domain.com', // your Power BI Pro account, e.g. john.doe@yourdomain.com
'password' => 'mysecretpassword'  // password for above user
)
));

$tokenResponse = curl_exec($curl1);
$tokenError = curl_error($curl1);

curl_close($curl1);

$tokenResult = json_decode($tokenResponse, true);
$token = $tokenResult["access_token"];
$embeddedToken = "Bearer "  . ' ' .  $token;

 

 

With this access token I should be able to create embed token with RLS for each user BUT it doesn't work:

 

$curl3 = curl_init();
curl_setopt($curl3, CURLOPT_URL, 'https://api.powerbi.com/v1.0/myorg/groups/'.$group_Id.'/reports/'.$report_ID.'/GenerateToken');
curl_setopt($curl3, CURLOPT_RETURNTRANSFER, TRUE);
//curl_setopt($curl3, CURLOPT_SSL_VERIFYPEER, false); //Might be required for https
curl_setopt($curl3, CURLOPT_ENCODING, "");
curl_setopt($curl3, CURLOPT_MAXREDIRS, 10);
curl_setopt($curl3, CURLOPT_TIMEOUT, 30);
curl_setopt($curl3, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($curl3, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt ($curl3, CURLOPT_HTTPHEADER,array(
    'Authorization: '.$embeddedToken,
    'Content-Type:application/json; charset=utf-8',
    'Accept:application/json',
    "accessLevel: View",
    "username: userOne",
    "roles: Tenant",
    "datasets: 12345678-1234-1234-1234-123123123"

));

$RLStokenResponse  = curl_exec($curl3);
$RLStokenError = curl_error($curl3);
curl_close($curl3);
if ($RLStokenError) {
echo "cURL Error #:" . $RLStokenError;
} else {
$RLStokenResult = json_decode($RLStokenResponse, true);
$RLStoken = $RLStokenResult["access_token"];
$RLSembeddedToken = "Bearer " . ' ' . $RLStoken;
}

 

This request returns an error. Could you please advise me what I am doing wrong?

 

franck_axires
Frequent Visitor

Just great, thanks for sharing !

irfanharun
Frequent Visitor

Hi, I've been able to complete the first 4 steps in Postman. 

However on testing the embed code in Microsoft Power BI Embedded Playground, i keep getting following error :

> Json Object { "message": "LoadReportFailed", "detailedMessage": "Fail to initialize - Could not resolve cluster", "errorCode": "403", "level": 6, "technicalDetails": { "requestId": "57679585-022b-4871-ae6d-bb722d4a07cc" } }

Also, when trying the alternative, HTML setup provided in STEP 5, i again keep getting 403 error stating : "GET https://wabi-india-west-redirect.analysis.windows.net/powerbi/globalservice/v201606/clusterdetails 403 (Forbidden)"

Please help. I've been trying to get this thing to work for over a week now.

d_u_a
Helper II
Helper II

@adamwallace3 I'm sending Post request with like in your first step. But getting this error : 


"error": "invalid_request",
"error_description": "AADSTS90014: The request body must contain the following parameter: 'grant_type'.\r\

My App type is web/api in azure . Is there a solution to fix this grant_type issue? 

You get this "invalid_request" error probably because you simply copy/pasted data: {} into body raw. I got the same error when I did it, but got it work by copy only the key/value pairs inside the curely braces and paste it into form-data using Bulk Edit (of course enter your credentials).

ezekielvp
Frequent Visitor


@d_u_a wrote:

@adamwallace3 I'm sending Post request with like in your first step. But getting this error : 


"error": "invalid_request",
"error_description": "AADSTS90014: The request body must contain the following parameter: 'grant_type'.\r\

My App type is web/api in azure . Is there a solution to fix this grant_type issue? 


I used to have that error message. I tried using postman and go to the body and make sure you chose the form-data and feed the key/value needed for the request and all should work

d_u_a
Helper II
Helper II

@adamwallace3 I'm sending Post request with like in your first step. But getting this error : 


"error": "invalid_request",
"error_description": "AADSTS90014: The request body must contain the following parameter: 'grant_type'.\r\

My App type is web/api in azure . Is there a solution to fix this grant_type issue? 

aaco
Regular Visitor

Hi,

 

When executing the step 4 in Postman (adding the Authorization token in the headers and the Data in the body) I'm getting the following error:

 

{
"error": {
"code": "",
"message": "The request entity's media type 'multipart/form-data' is not supported for this resource."
}
}

 

Capture.JPG

 

Also, when running step 5 in Chrome, I get this error message:

 

GET https://wabi-north-europe-redirect.analysis.windows.net/metadata/cluster 403 (Forbidden)

 

 

From step 1 to step 3 all works as described. Is someone else getting the same error message? Any ideas of how to fix it or where it should be coming from?

 

Many thanks

aaco
Regular Visitor

So, I figured out that I wasn't using the Body > raw > JSON (application/json) option in Postman. Now I do it but am getting a different error:

 

{
"error": {
"code": "Unauthorized",
"message": "Report.Read.All Dataset.Read.All"
}
}

 

Capture2.JPG

 

For info, steps 1 to 3 are still OK and permissions on the Azure App Registration side for 'Power BI Service' are all set to 'DELEGATED' (19 in total).

 

Thanks again.

@aaco Did you find the source of this issue please ?

ashleymartin
Frequent Visitor

Step 4 is not working for me. I was able to get the access token in step 2 and then able to run step 3. For step 4 I entered the header information into postman under header and the data information under the body but I am getting this error:

 

{
"error": {
"code": "BadRequest",
"message": "Bad Request",
"details": [
{
"message": "Unexpected character encountered while parsing number: W. Path '', line 1, position 6.",
"target": "request"
}
]
}
}
]
}
}

 

Is anyone else experiencing this or know of a way I can fix this? Also for reference I am doing a server-web app and have added the client secret into the first step, not sure if I would need to add anything in this 4th step too or if there is another reason it is showing this error.

@ashleymartin The "data= {}" section of step 4 needs to be put into the "Body" tab on Postman. You can click the "raw" radio button to be able  to paste it in directly. The headers go in the headers tab as well. Other than that, make sure that the access token you have is not expired. From there, you can use the embed token where ever you deem appropriate.

Hi,

Did you manage to find a solution to the error you were getting in step 4 of this guide?

Regards,

Matt

Hi,

Did you find the solution to the error you were getting in Step 4 ?

Thanks in advance!

azulcore
Frequent Visitor

All of the steps work except for the last step. I entered all the values in the https://microsoft.github.io/PowerBI-JavaScript/demo and it works well. But using your html code at the end just gives a blank page, any ideas? I use clientid and clientsecret if that makes a difference

Helpful resources

Announcements
Power BI December 2021 Update_carousel 768x460.jpg

Check it Out!

Click here to read more about the December 2021 Updates!

Jan 2022 Dev Camp 768x460 copy.png

Power BI Dev Camp- January 27th, 2022

Mark your calendars and join us for our next Power BI Dev Camp!

UG GA Amplification 768x460.png

Launching new user group features

Learn how to create your own user groups today!

Top Solution Authors