C# – how to connect to Power BI API using non-interactive authentication

authenticationazurecpowerbi

Coding in C#.
I'm following this guide:

https://azure.microsoft.com/en-us/documentation/articles/resource-group-authenticate-service-principal/#authenticate-service-principal-with-password—powershell%E2%80%8C%E2%80%8B

But it is not working and it is not Power BI specific so I'm not sure exactly how to apply it to the Power BI API.

In my attempt to connect to Power BI I am getting a 403 Forbidden response.

        var authenticationContext = new AuthenticationContext("https://login.windows.net/" + Properties.Settings.Default.TenantID);
        var credential = new ClientCredential(clientId: Properties.Settings.Default.ClientID, clientSecret: Properties.Settings.Default.ClientSecretKey);
        var result = authenticationContext.AcquireToken(resource: "https://management.core.windows.net/", clientCredential: credential);

        if (result == null)
        {
            throw new InvalidOperationException("Failed to obtain the JWT token");
        }

        string accessToken = result.AccessToken;


        string responseContent = string.Empty;

        //The resource Uri to the Power BI REST API resource
        string datasetsUri = "https://api.powerbi.com/v1.0/myorg/datasets";

        //Configure datasets request
        System.Net.WebRequest request = System.Net.WebRequest.Create(datasetsUri) as System.Net.HttpWebRequest;
        request.Timeout = 20000;
        request.Method = "GET";
        request.ContentLength = 0;
        request.Headers.Add("Authorization", String.Format("Bearer {0}", accessToken));

        try
        {

            //Get datasets 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
                    //JavaScriptSerializer class is in System.Web.Script.Serialization
                    JavaScriptSerializer json = new JavaScriptSerializer();
                    Datasets datasets = (Datasets)json.Deserialize(responseContent, typeof(Datasets));

                    resultsTextbox.Text = string.Empty;
                    //Get each Dataset from 
                    foreach (dataset ds in datasets.value)
                    {
                        resultsTextbox.Text += String.Format("{0}\t{1}\n", ds.Id, ds.Name);
                    }
                }
            }
        }
        catch (WebException wex)
        {
            resultsTextbox.Text = wex.Message;
        }
    }

Best Answer

Try changing the resource URI:

var result = authenticationContext.AcquireToken(resource: "https://management.core.windows.net/", clientCredential: credential);

to

var result = authenticationContext.AcquireToken(resource: **"https://analysis.windows.net/powerbi/api"**, clientCredential: credential);

You want to acquire a token for the power bi api.

Hope that Helps.

EDIT Updating Answer Based on OP Comment:

Here is what you will need to do.

In Azure AD create a "Native App" and get that client ID there will be NO Secret.

Make sure you have the latest version of ADAL from Nuget Active Directory Authentication Library 2.23.302261847

You will need to use this Acquire Token Overload:

authContext.AcquireToken("https://analysis.windows.net/powerbi/api", clientID, new UserCredential(<Username>, <Password>));

EDIT: 2016-11-11

ADAL 3.13.7 UserCredentail no longer has a constructor as defined above. There is a new sealed class UserPasswordCredential

public sealed class UserPasswordCredential : UserCredential

Which has the constructor that matches the former UserCredential object

public UserPasswordCredential(string userName, string password)

You can acquire the token by doing this:

authContext.AcquireToken("https://analysis.windows.net/powerbi/api", clientID, new UserPasswordCredential(<Username>, <Password>));
Related Topic