Power Bi Embedded Not working, Can't login with Master User

1.8k views Asked by At

Good day to all of you. I have a problem with probably not fully understanding how to embed PBI report in my Xamarin app.  I got my access token and I used Master User for this, but after i GET EmbedUrl and put it in Source proprety of WebView, i get a message: "Please sing in to view this report". This is a problem because my customers don't have PowerBi account and I want them to be able to see this report. Problem might be in my headers I use to get access token, so below is code I use

string url = "https://login.microsoftonline.com/" + tennant_id + "/oauth2/token"; //url to which I POST to

IEnumerable<KeyValuePair<string, string>> parameters = new List<KeyValuePair<string, string>>()
{
new KeyValuePair<string, string>("authenticationType", "MasterUser"),
new KeyValuePair<string, string>("name", "<name>"),
new KeyValuePair<string, string>("workspaceId", "<workspaceId>"),
new KeyValuePair<string, string>("grant_type", "password"),
new KeyValuePair<string, string>("scope", "https://analysis.windows.net/powerbi/api/.default"),
new KeyValuePair<string, string>("resource", "https://analysis.windows.net/powerbi/api"),
new KeyValuePair<string, string>("authorityUrl", "https://login.microsoftonline.com/organizations/"),
new KeyValuePair<string, string>("urlPowerBiServiceApiRoot", "https://api.powerbi.com/"),
new KeyValuePair<string, string>("client_id", "<clientID>"),
new KeyValuePair<string, string>("username", "<username>"),
new KeyValuePair<string, string>("password", "<password>"),
new KeyValuePair<string, string>("client_secret", "<clientSecret>")
};

 After I get access token, I use it in GET request to 

https://api.powerbi.com/v1.0/myorg/reports/<report_it>

 and I pass AuthenticationHeader as 

client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);

Then I get my embed url which I use in WebView Source property but I am not logged in. When I do login i see this report, but otherwise I can't. Where am I making a mistake/mistakes? I'm new to PowerBi embedding so please explain it like you would to a child.

1

There are 1 answers

0
Andreja Zivanovic On BEST ANSWER

I did it, and I will post solution here for anyone in the future having similar problems. As @AndreyNikolov said I had to use JavaScript SDK, but his references were a bit old and stuff there is no longer fully useful, but they served as great reference. Anyway let's start from beginning first I had to place WebView in xaml file like this:

<WebView x:Name="WVtest" HeightRequest="300" WidthRequest="50" Navigated="WVtest_Navigated">
            
</WebView>

Then I added files from JavaScript API, but I couldn't make them work (because they made docs there complicated as hell) so I made some changes and I used files which you can find on my github repo. These files are there to display your PBI Embedded report from embed url, so they are essential. I placed them in Android Assets folder like this:

enter image description here

Then in code behind in constructor I added following code:

WVtest.Source = "file:///android_asset/html/index.html";

This is so WebView knows to set it's source to index.html file. It will load this .html and load .js files from it for calling pbi client and showing PBI report.

"Navigated" event is where I call all REST API's to PowerBI and Azure. First I send POST request to get my access token. Url to where I send POST request is like this:

string url = "https://login.microsoftonline.com/" + tennant + "/oauth2/token";

where tennant is your apps tennant. For body I needed few parameters like:

IEnumerable<KeyValuePair<string, string>> parameters = new List<KeyValuePair<string, string>>()
{
    new KeyValuePair<string, string>("authentication_type",  "MasterUser"),
                        new KeyValuePair<string, string>("name",                "<name_of_app>"),
                        new KeyValuePair<string, string>("workspaceId",         "<workspace_id>"),
                        new KeyValuePair<string, string>("grant_type",          "password"),
                        new KeyValuePair<string, string>("scope",               "https://analysis.windows.net/powerbi/api/.default"),
                        new KeyValuePair<string, string>("resource",            "https://analysis.windows.net/powerbi/api"),
                        new KeyValuePair<string, string>("authorityUrl",        "<your auth url from azure, redirect url>"),
                        new KeyValuePair<string, string>("client_id",           "<client_id>"),
                        new KeyValuePair<string, string>("username",            "<username>"),
                        new KeyValuePair<string, string>("password",            "<pass>"),
                        new KeyValuePair<string, string>("client_secret",       "<clinet_secret>")
}

After I made this key value pairs, I needed to transform them in something that POST request can understand. I used HttpContent as in code below:

HttpContent content = new FormUrlEncodedContent(parameters);
using (HttpResponseMessage response = await client.PostAsync(url, content)){
//rest of code from below
}

I used them as options in POST request to url from above. In response of that request I got access_token which is only thing I needed for next steps. Now I do GET request to powerBI API:

string pbiUrl = "https://api.powerbi.com/v1.0/myorg/reports/<report_id>";
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken); //client is of type HttpClient

Now I got my embedUrl in response which I need to deserialize like this:

var response = await client.GetStringAsync(pbiUrl);

var rese = JsonConvert.DeserializeObject<PBIReport>(response2);
                                
await WVtest?.EvaluateJavaScriptAsync($"LoadEmbeddedObject('{rese.embedUrl}', '{accessToken}', '0', '{<reportId>}')"); //Here I call JavaScript function with parameters

First parameter is embedUrl containing link from response, second is access token, third is '0' because in ReportLoader.js translates zero to AAD type of token, use '1' here if you are using embed token. Last parameter is your report_id. I don't know why I had to use it again considering I used it when getting my access token, but it needs to be there.

Now it should be working correctly. Give it a bit time to load, it's really slow. If you don't like the look of your report, use config object in ReportLoadder.js, you have nice documentation on official PowerBi JavaScript client wiki I really hope this will help someone, because I couldn't figure it out for couple of weeks. If you have any simpler solution, please post it here, this is just one way that worked for me. Feel free to ask anything, I will be glad to help.