cancel
Showing results for 
Search instead for 
Did you mean: 
Reply
seijim
Microsoft
Microsoft

How to use Power BI Rest API without GUI authentication (redirect uri)

I'm developing an Azure worker role application which pushes data to PowerBI.com service.

I referred a C# sample client application via Git Hub. But it authenticates using GUI (redirect uri) during the below step.

>> token = authContext.AcquireToken(resourceUri, clientID, new Uri(redirectUri)).AccessToken.ToString();

 

I need a sample code without GUI (redirect uri) authentication which means silent mode authentication.

 

Thanks,

-Seiji

1 ACCEPTED SOLUTION
jocaplan-MSFT
Microsoft
Microsoft

You can use the user name and password flow that AAD supports. This 3rd party client library has an example: https://github.com/Vtek/PowerBI.Api.Client

View solution in original post

53 REPLIES 53

Technically speaking, you could store their usernames/passwords and achieve the silent authentication that you desire. But I would strongly discourage doing that. Storing passwords is almost never a good idea.

 

You should look around and see if there is any way to grab the logged in user's windows credentials, and pass that to the acquireToken method instead of the username and password strings. I would imagine that there is a simple way to do that.

Thanks for your reply.

 

That is the difficulty we are having - As it doesnt appear that the acquireToken method has user name and password parameters. So whether we get their windows login, or whether the login to our application was the same as their Powerbi account, its how do we pass the username and password in the acquireToken method we are stuck on.

 

Do you have a link to an example where the acquireToken method has username and password elements for a "user owns data" scenario ? 

 

There are a number of articles online about silent authentication for "Access token for non-Power BI users (app owns data)"

I havent been able to find any about silent auhtentication for "Access token for Power BI users (user owns data)"

Reference https://powerbi.microsoft.com/en-us/documentation/powerbi-developer-get-azuread-access-token/

 

 

This article has an example.... This example is for when your users will manually log into Azure AD with their organziation login. This is used when embedding content for Power BI users that will access content they have access to within the Power BI service.

 

But like I explain above I want to log them in silently as whether we store the username and password or obtain it from another source we will have it.  As our application is non web UI, it makes it a ordinary user exeprience opening a web page for a user to log in with credentials we will already have access to, before having to run our application. We would like to do it for them in the background using the API.

 

If you have any links for additional details on how we would achieve what you have said is technically possible that would be fantastic.  Thanks in advance for the time taken to read and address my query

 

 

 

The code snippet I sent in a previous reply to you shows how to call the acquire token method with an email and password....

We must be missing something as your snippet uses authContext.AcquireToken

The AcquireToken() doesn’t accept the email and password parameters at least not from the following link

https://msdn.microsoft.com/en-us/library/microsoft.identitymodel.clients.activedirectory.authenticat...

Hi have found a way using SSIS that should work from anywhere.  I will write a blog on the www.radacad.com site and post here the details.


To learn more about DAX visit : aka.ms/practicalDAX

Proud to be a Datanaut!

Hey Phil! Sorry for reviving this old post 😅 but can you send me the link of your article? I haven't found it in the site

Thanks in advance

@ChrisWilliams I came here to post this exact thing. I can't find a simple way to "silent" authenticate because of these issues. Is there a standard approach for this now? Do we need to submit a feature request?

vijaybkodare
New Member

Below is the code for getting AccessToken by giving User credential, client Id (without AccessCode & Azure-Login UI).

 

using Newtonsoft.Json;
using System.IO;
using System.Text;

 

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", ""));
vals.Add(new KeyValuePair<string, string>("client_secret", ""));
vals.Add(new KeyValuePair<string, string>("username", ""));
vals.Add(new KeyValuePair<string, string>("password", ""));
string 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 = JsonConvert.DeserializeObject<AccessToken>(responseData);
}

 

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; }
}

Hi @vijaybkodare I have tried this using Postman and I'm getting the following error:

 

{
"error": "invalid_grant",
"error_description": "AADSTS65001: The user or administrator has not consented to use the application with ID '3cc9615b-ed4c-436b-82a5-fb701c7e240d' named 'Launch BI'. Send an interactive authorization request for this user and resource.\r\nTrace ID: 46533754-26e3-43d9-9bea-2206d7ab3100\r\nCorrelation ID: c9e76852-19f3-4173-9866-5f914509fb7b\r\nTimestamp: 2018-01-16 17:31:30Z",
"error_codes": [
65001
],
"timestamp": "2018-01-16 17:31:30Z",
"trace_id": "46533754-26e3-43d9-9bea-2206d7ab3100",
"correlation_id": "c9e76852-19f3-4173-9866-5f914509fb7b"
}

I just found the problem, the grant type needs to be "client_credentials" not "password"

I just realised that using the "client_credentials" grant type may not be suitable as the username and password parameters are not used. I switched back to using the "password" grant type but I also had to login to my Azure AD -> Registered Apps -> <App Name> -> All Settings -> Required Permissions and then click the "Grant Permissions" button

 

 

 

Hi there,

Pleased you got it working! Yes you do need to set the correct permissions in the Azure AD app. I did mention it in my post but obviously I wasn't clear enough!! Thank you for explaining it! I'm sure it will help someone! 🙂

Hi @skaratela it's odd because I didn't actually make any changes, I just clicked the "Grant Permissions" button. I think it's another bug

That's very useful. However, when registering the application, what values did you use for the redirect URL? It appears to be a mandatory field but in this case, it is not being used

Hi!

The redirect url is needed when creating the AAD app and not the post request... Unless it's changed recently.

Shaheen

After executing the above code by replacing the values for ClientID,ClientSecret and TenantId, I am seeing the below error :

Message: The remote server returned an error: (400) Bad Request.

Status: ProtocolError.

 

I have also tried using the authority uri as https://login.microsoftonline.com/<TenantID>/oauth2/token but still the same error.

 

I really appreciate your response why I am seeing this bad request error.

 

Can you please clarify what is the TenantId in the above code represents?

tarik
Regular Visitor

https://login.windows.net/common/oauth2

its actually "common" in my code. By ethier it can be domain according to azure active directory. Both works. I work as above.

Hi there,
I'm using the same flow as you mentioned here but I'm always getting error at that part.

If I use client credentials such as client_id then I get one token without any user consent dialog . (As long as I develop native java application I cant open a browser to pop it up.) Unfortunately I cant use this token to make a rest api call because I always get 403 forbidden. I understand that authentication for rest api calls should be user specific for Power Bi. So I use this example same as in the adal4f implementation and also with the post man rest tool.  I encounter same error in both as you see in the pictures.

 

{
  "error": "invalid_grant",
  "error_description": "AADSTS65001: The user or administrator has not consented to use the application with ID 'ef193d6d-5585-4286-bc7f-31eadd94446c'. Send an interactive authorization request for this user and resource.\r\nTrace ID: bd8c1e80-4965-4d85-b607-700505157055\r\nCorrelation ID: 9189059d-abea-4f30-8de1-321f25010dbd\r\nTimestamp: 2016-10-26 09:10:34Z",
  "error_codes": [
    65001
  ],
  "timestamp": "2016-10-26 09:10:34Z",
  "trace_id": "bd8c1e80-4965-4d85-b607-700505157055",
  "correlation_id": "9189059d-abea-4f30-8de1-321f25010dbd"
}

 

 private static void getPasswordCredentinal() throws IOException {
        HttpPost signIn = new HttpPost("https://login.windows.net/{mytenant}/oauth2/token");

        List<NameValuePair> nvps = new ArrayList<>();
        nvps.add(new BasicNameValuePair("grant_type","password"));
        nvps.add(new BasicNameValuePair("client_id","myId"));
        nvps.add(new BasicNameValuePair("resource","https://analysis.windows.net/powerbi/api"));
        nvps.add(new BasicNameValuePair("username","myuser"));
        nvps.add(new BasicNameValuePair("password","mypass"));
        nvps.add(new BasicNameValuePair("scope","openid")); //optinal
        signIn.setEntity(new UrlEncodedFormEntity(nvps));

        CloseableHttpClient client = HttpClients.custom().build();
        HttpResponse response = client.execute(signIn);
        System.out.println(response.getStatusLine().toString()+" "+response.getStatusLine().getReasonPhrase()+" "+response.getStatusLine().toString());
        String s = EntityUtils.toString(response.getEntity());
        JSONObject jsonObject=new JSONObject(s);
        accessToken = (String) jsonObject.opt("access_token");
        System.out.println(" json object >"+jsonObject);
      

    }

Both produce the same result. 

"error_description": "AADSTS65001: The user or administrator has not consented to use the application with ID 'ef193d6d-5585-4286-bc7f-31eadd94446c'. Send an interactive authorization request for this user and resource

So is there anyting I'm missing? Or is there any way to bypass this consent process programmatically?
Thanks for your help

Hi there,

 

What do you use for the Username/Password for your solution.  

 

We use SSO at our company so not sure what account I can use.

 

 


To learn more about DAX visit : aka.ms/practicalDAX

Proud to be a Datanaut!

I currently use my personal credentials. We're planning a change soon. What sucks is that PowerBI doesn't really allow multiple users to build reports off an API dataset. Our plan is to get a shared Service Account, pay for a license for the service account, and keep the password private to our group.

Helpful resources

Announcements
UG GA Amplification 768x460.png

Launching new user group features

Learn how to create your own user groups today!

Power BI October Update 2021.jpg

Power BI Release

Click here to read more about the October 2021 Release!

Community Connections 768x460.jpg

Community & How To Videos

Check out the new Power Platform Community Connections gallery!

Teds Dev Camp Oct. 2021 768x460.jpg

Power BI Dev Camp - October 28th, 2021

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

Top Solution Authors