Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Register now to learn Fabric in free live sessions led by the best Microsoft experts. From Apr 16 to May 9, in English and Spanish.

Reply
Wahid
Frequent Visitor

Integrate Power Bi Report Without Authentication ?

Hello,
I just succeed to integrate Power Bi Report into an app following examples given on powerbi.com.
(https://msdn.microsoft.com/en-us/library/azure/dn645542.aspx)
(https://github.com/Microsoft/PowerBI-CSharp)

 

Right now, the user had to authenticate to get an authentication code, then I can get an access_token which allows me to get my report and to publish it.

 

However I would like to integrate report without asking the user to authenticate.

 

I tried to use an other method (https://msdn.microsoft.com/en-us/library/azure/dn645543.aspx) to get a token but I only got response 403 Forbidden when I was asking the Power Bi API to get my report.

 

I found a related topic with a potential solution to my problem :
http://community.powerbi.com/t5/Developer/How-to-use-Power-BI-Rest-API-without-GUI-authentication-re...

 

But when I try it, I am getting a weird? error :

 

Error: https://app.powerbi.com/13.0.1100.519/scripts/powerbiportal.dependencies.bundle.min.js is being assigned a //# sourceMappingURL, but already has one
Error: https://app.powerbi.com/13.0.1100.519/scripts/powerbiportal.common.bundle.min.js is being assigned a //# sourceMappingURL, but already has one
Error: https://app.powerbi.com/13.0.1100.519/scripts/powerbiportal.explore.bundle.min.js is being assigned a //# sourceMappingURL, but already has one
Error: https://app.powerbi.com/13.0.1100.519/scripts/powerbireportembed.common.bundle.min.js is being assigned a //# sourceMappingURL, but already has one
Error: https://app.powerbi.com/13.0.1100.519/scripts/ODataExplore.min.js is being assigned a //# sourceMappingURL, but already has one
// Weird Error coming from JS ??
"AI: USRACT_StringValueTooLong message:"string value is too long. It has been truncated to 1024 characters." props:"{value:f3eee70c-fa06-4f54-aae8-19f58fd9025feyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik1uQ19WWmNBVGZNNXBPWWlKSE1iYTlnb0VLWSIsImtpZCI6Ik1uQ19WWmNBVGZNNXBPWWlKSE1iYTlnb0VLWSJ9.eyJhdWQiOiJodHRwczovL2FuYWx5c2lzLndpbmRvd3MubmV0L3Bvd2VyYmkvYXBpIiwiaXNzIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNTEwNDM0MzItYzJlMC00YmE5LWE4NGYtMmY3NWVhZjIyMDdmLyIsImlhdCI6MTQ2Mjk1MDcyOCwibmJmIjoxNDYyOTUwNzI4LCJleHAiOjE0NjI5NTQ2MjgsImFjciI6IjEiLCJhbXIiOlsicHdkIl0sImFwcGlkIjoiYmExNzgzMjctMmE2Ni00NWU1LWJiY2ItZDczZWVmYTdjYjRkIiwiYXBwaWRhY3IiOiIxIiwiZmFtaWx5X25hbWUiOiJCdXNpbmVzc1NoYXJlIiwiZ2l2ZW5fbmFtZSI6IlN1cHBvcnQiLCJpcGFkZHIiOiI1LjEzNS4xNDIuMjI3IiwibmFtZSI6IlN1cHBvcnQgQnVzaW5lc3NTaGFyZSIsIm9pZCI6ImYyNmY0YzRmLWRmZGEtNGVlMC05Mjc2LTgzZjk0ZTE3M2Q4YiIsInB1aWQiOiIxMDAzM0ZGRjhDNTIyN0ZEIiwic2NwIjoiRGFzaGJvYXJkLlJlYWQuQWxsIERhdGFzZXQuUmVhZC5BbGwgTWV0YWRhdGEuVmlld19BbnkgUmVwb3J0LlJlYWQuQWxsIiwic3ViIjoiOGU0YjI0YkFoUUNNLVFoaUplekhYVGFNVEMzeGctekhwLXpRd1QxSE96WSIsInRpZCI6IjUxMDQzNDMyLWMyZTAtNGJhOS1hODRmLTJmNzVlYWYyMjA3ZiIsInVuaXF1ZV9uYW1lIjoic3VwcG9ydEBidXNpbmV}"" ai.0.js:1
"AI: USRACT_StringValueTooLong message:"string value is too long. It has been truncated to 1024 characters." props:"{value:f3eee70c-fa06-4f54-aae8-19f58fd9025feyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik1uQ19WWmNBVGZNNXBPWWlKSE1iYTlnb0VLWSIsImtpZCI6Ik1uQ19WWmNBVGZNNXBPWWlKSE1iYTlnb0VLWSJ9.eyJhdWQiOiJodHRwczovL2FuYWx5c2lzLndpbmRvd3MubmV0L3Bvd2VyYmkvYXBpIiwiaXNzIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNTEwNDM0MzItYzJlMC00YmE5LWE4NGYtMmY3NWVhZjIyMDdmLyIsImlhdCI6MTQ2Mjk1MDcyOCwibmJmIjoxNDYyOTUwNzI4LCJleHAiOjE0NjI5NTQ2MjgsImFjciI6IjEiLCJhbXIiOlsicHdkIl0sImFwcGlkIjoiYmExNzgzMjctMmE2Ni00NWU1LWJiY2ItZDczZWVmYTdjYjRkIiwiYXBwaWRhY3IiOiIxIiwiZmFtaWx5X25hbWUiOiJCdXNpbmVzc1NoYXJlIiwiZ2l2ZW5fbmFtZSI6IlN1cHBvcnQiLCJpcGFkZHIiOiI1LjEzNS4xNDIuMjI3IiwibmFtZSI6IlN1cHBvcnQgQnVzaW5lc3NTaGFyZSIsIm9pZCI6ImYyNmY0YzRmLWRmZGEtNGVlMC05Mjc2LTgzZjk0ZTE3M2Q4YiIsInB1aWQiOiIxMDAzM0ZGRjhDNTIyN0ZEIiwic2NwIjoiRGFzaGJvYXJkLlJlYWQuQWxsIERhdGFzZXQuUmVhZC5BbGwgTWV0YWRhdGEuVmlld19BbnkgUmVwb3J0LlJlYWQuQWxsIiwic3ViIjoiOGU0YjI0YkFoUUNNLVFoaUplekhYVGFNVEMzeGctekhwLXpRd1QxSE96WSIsInRpZCI6IjUxMDQzNDMyLWMyZTAtNGJhOS1hODRmLTJmNzVlYWYyMjA3ZiIsInVuaXF1ZV9uYW1lIjoic3VwcG9ydEBidXNpbmV}"" ai.0.js:1

I don't understand where it came from : the token is 1407 characters long with this method but it is the same with the method that work well (the first one with authentication)

 

Hope you can help me,

Wahid

 

Here is my code if it can help you to help me ^^ :

 

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
C# PART : 


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System.Threading.Tasks;
using System.Net.Http;
using System.Collections.Specialized;
using Newtonsoft.Json;
using System.Text;
using System.IO;


namespace PBIWebApp
{
    public partial class _Default : Page
    {
        string baseUri = "https://api.powerbi.com/beta/myorg/";
        string Token;
		
        private async void SetAccessToken()
        {
            List<KeyValuePair<string, string>> vals = new List<KeyValuePair<string, string>>();
            vals.Add(new KeyValuePair<string, string>("grant_type", "password"));
            vals.Add(new KeyValuePair<string, string>("scope", "openid"));
            vals.Add(new KeyValuePair<string, string>("resource", "https://analysis.windows.net/powerbi/api"));
            vals.Add(new KeyValuePair<string, string>("client_id", Properties.Settings.Default.ClientID));
            vals.Add(new KeyValuePair<string, string>("client_secret", Properties.Settings.Default.ClientSecret));
            vals.Add(new KeyValuePair<string, string>("username", "<MYUSERNAME>"));
            vals.Add(new KeyValuePair<string, string>("password", "<MYPASSWORD>"));
            string TenantId = Properties.Settings.Default.TenantID;
            string url = string.Format("https://login.windows.net/{0}/oauth2/token", TenantId);
            HttpClient hc = new HttpClient();
            HttpContent content = new FormUrlEncodedContent(vals);
            HttpResponseMessage hrm = hc.PostAsync(url, content).Result;
            string responseData = "";
            if (hrm.IsSuccessStatusCode)
            {
                Stream data = await hrm.Content.ReadAsStreamAsync();
                using (StreamReader reader = new StreamReader(data, Encoding.UTF8))
                {
                    responseData = reader.ReadToEnd();
                }
            }
            Token = responseData;
        }

        protected void Page_Load(object sender, EventArgs e)
        {
                SetAccessToken();
                getReportsButton_Click();
        }

        protected void getReportsButton_Click()//getReportsButton_Click(object sender, EventArgs e)
        {
            string responseContent = string.Empty;

            //Configure reports request
            System.Net.WebRequest request = System.Net.WebRequest.Create(String.Format("{0}reports", baseUri)) as System.Net.HttpWebRequest;
            request.Method = "GET";
            request.ContentLength = 0;
			
            var acctoken = Token.Split(',');
            var split = acctoken[6].Split('"');
            var access = split[3];
			// access give me the access_token I need to get the information I am asking for.
			
            request.Headers.Add("Authorization", String.Format("Bearer {0}", access));

            //Get reports response from request.GetResponse()
            using (var response = request.GetResponse() as System.Net.HttpWebResponse)
            {
                //Get reader from response stream
                using (var reader = new System.IO.StreamReader(response.GetResponseStream()))
                {
                    responseContent = reader.ReadToEnd();

                    //Deserialize JSON string
                    PBIReports PBIReports = JsonConvert.DeserializeObject<PBIReports>(responseContent);

                    tb_reportsResult.Text = string.Empty;
                    //Get each report 
                    foreach (PBIReport rpt in PBIReports.value)
                    {
                        if (rpt.name.Contains("TestIframe"))
                        {
							// This step is OK, I can get the embedUrl I am asking for and the access_token 
                            tb_reportsResult.Text += String.Format("{0}\t{1}", rpt.embedUrl, access);
                        }
                    }
                }
            }
        }
    }


    public class AccessToken
    {
        public string token_type;
        public string scope { get; set; }
        public string expires_in { get; set; }
        public string expires_on { get; set; }
        public string not_before { get; set; }
        public string resource { get; set; }
        public string access_token { get; set; }
        public string refresh_token { get; set; }
        public string id_token { get; set; }
    }
    //Power BI Datasets
	public class PBIDatasets
	{
		public Dataset[] Datasets { get; set; }
	}
	public class PBIGroups
	{
		public PBIGroup[] value { get; set; }
	}
	public class Dataset
	{
		public string Id { get; set; }
		public string Name { get; set; }
	}
	public class PBIGroup
	{
		public string id { get; set; }
		public string name {get; set;}
	}
	public class PBIDashboards
	{
		public PBIDashboard[] value { get; set; }
	}
	public class PBIDashboard
	{
		public string id { get; set; }
		public string displayName { get; set; }
	}
	public class PBIReports
	{
		public PBIReport[] value { get; set; }
	}
	public class PBIReport
	{
		public string id { get; set; }
		public string name { get; set; }
		public string webUrl { get; set; }
		public string embedUrl { get; set; } 
	}
	public class PBITiles
	{
		public PBITile[] value { get; set; }
	}
	public class PBITile
	{
		public string id { get; set; }
		public string title { get; set; }
		public string embedUrl { get; set; }
	}

}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
JS part :

<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs" Inherits="PBIWebApp.SiteMaster" %>

<!DOCTYPE html>

<html lang="en">
<head runat="server">
    <title>Power BI - Web application</title>
    <script type="text/javascript">

        window.onload = function () {
            // listen for message to receive message from embedded report.
            if (window.addEventListener) {
                window.addEventListener("message", receiveMessage, false);
            } else {
                window.attachEvent("onmessage", receiveMessage);
            }
            // handle server side post backs, optimize for reload scenarios
            // show embedded report if all fields were filled in.
			var report = document.getElementById('MainContent_tb_reportsResult').value;
			var tableau = report.split("\t");
			var accessTokenElement = tableau[1];
			console.log("textbox " + accessTokenElement + " report " + report);
            if(null !== accessTokenElement){
                if ("" !== accessTokenElement)
				    console.log("JE SUIS LA");
                    updateEmbedReport();
            }
        };

        // The embedded report posts message for errors to parent window.  listen and handle as appropriate
        function receiveMessage(event)
        {
            if (event.data) {
                try {
                    messageData = JSON.parse(event.data);
                    if (messageData.event === "reportPageLoaded")
                    {
                    }
                }
                catch (e) {
                    // do something smart
                }
            }
        }

        var valB = false;

        // update embed report
        function updateEmbedReport() {

            // check if the embed url was selected
			//Console.WriteLine("doc : "+document.getElementById('tb_reportsResult').value)
            var embedUrl = document.getElementById('MainContent_tb_reportsResult').value;
            if ("" === embedUrl)
                return;

            // to load a report do the following:
            // 1: set the url
            // 2: add a onload handler to submit the auth token
            iframe = document.getElementById('iFrameEmbedReport');
            iframe.src=embedUrl;
			console.log("ok1");
            iframe.onload = postActionLoadReport;
			console.log("ok2");
        }

        
        // post the auth token to the iFrame. 
        function postActionLoadReport() {

            // get the access token.
			var report = document.getElementById('MainContent_tb_reportsResult').value;
			var tableau = report.split("\t");
			var accessTokenElement = tableau[1];
            accessToken = accessTokenElement;

            // return if no a
            if ("" === accessToken)
                return;

            // construct the push message structure
            // this structure also supports setting the reportId, groupId, height, and width.
            // when using a report in a group, you must provide the groupId on the iFrame SRC
            var m = { action: "loadReport", accessToken: accessToken};
            message = JSON.stringify(m);
            console.log(message);
            // push the message.
            iframe = document.getElementById('iFrameEmbedReport');
            iframe.contentWindow.postMessage(message, "*"); 


//<==   My error came from the line above  



        }

    </script>
</head>
<body>
    <form runat="server">
        <div>
            <asp:ContentPlaceHolder ID="Stylesheets" runat="server">
                <link rel="stylesheet" href="/css/master.css" type="text/css" />
            </asp:ContentPlaceHolder>
            <asp:ContentPlaceHolder ID="MainContent" runat="server">
            </asp:ContentPlaceHolder>
        </div>
    </form>
</body>
</html>

 

3 REPLIES 3
spappuru
New Member

Can you please clarify what the TenantId represents in the above code..

Greg_Deckler
Super User
Super User

If you do not want to authenticate, why not just use the Publish to Web feature and essentially iframe it?


@ me in replies or I'll lose your thread!!!
Instead of a Kudo, please vote for this idea
Become an expert!: Enterprise DNA
External Tools: MSHGQM
YouTube Channel!: Microsoft Hates Greg
Latest book!:
The Definitive Guide to Power Query (M)

DAX is easy, CALCULATE makes DAX hard...

I tried to use the Publish to Web feature but it seems that with this feature I won't be able to filter the report like I am doing it right now.(Except if you know a way to add filter on a publish to web report ? But I didn't find it if this way exist)

Helpful resources

Announcements
Microsoft Fabric Learn Together

Microsoft Fabric Learn Together

Covering the world! 9:00-10:30 AM Sydney, 4:00-5:30 PM CET (Paris/Berlin), 7:00-8:30 PM Mexico City

PBI_APRIL_CAROUSEL1

Power BI Monthly Update - April 2024

Check out the April 2024 Power BI update to learn about new features.

April Fabric Community Update

Fabric Community Update - April 2024

Find out what's new and trending in the Fabric Community.