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

Find everything you need to get certified on Fabric—skills challenges, live sessions, exam prep, role guidance, and more. Get started

Reply
Anonymous
Not applicable

Power BI Rest API wont accept Application Token

I have multiple Admin API calls in my pbix that run just fine if I use my own or the ServiceAccount token generated using PowerShell.

 

But as soon as I try to substitute in the Access Token I get back from my Registered Application, it fails to connect to the API and doesn't provide any relavant error message. Lately it has been stuck on just asking me to Specify how to Connect and Edit Credentials. They have to be left Anonymous because selecting any others tells you the API call must be made with Anonymous.

 

The API has all of the Read permissions for Power BI Service added and Admin approved. I know that since it does produce this Token for me in Power BI Desktop is half the battle. Now I'm trying to figure out what is missing. Everyone's tutorials, blogs, YouTube videos review the App Registration, granting it Permissions, and using the Token in the API call within Power BI Desktop. Nobody seems to review if there is some other permissions necessary here.

 

Thoughts?

1 ACCEPTED SOLUTION
Anonymous
Not applicable

Solution found thanks to @SpartaBI !

 

1. Go to App registration -> New registration

ATF311_2-1652471546706.png

 

2. Give your app a name and use the default settings

ATF311_3-1652471546783.png

 


3. Create a secret, and make sure you copy the right value

ATF311_4-1652471546787.png

 

ATF311_5-1652471546754.png

 


4. Copy the ClientId & TenantId

ATF311_6-1652471546739.png

 

No need to do anything else with the app config.

Just add "MyNewApp" to the AAD security group, wait for a couple of minutes, then try your code.

 

Then for running a Non-Admin API call, the App needs added into the Workspace Permissions you want to read from.

 

You do not need to add any delegated permissions to the app.
In order to allow a service principal access no non-admin APIs, it must have the same dataset/workspace permissions as any other user. For example- you can add the service principal as a member of a workspace.

ATF311_7-1652471631467.png

 



This is exactly the purpose of the other setting in the Admin Portal.
It defines the service principals whose permissions are being managed by the Power BI Service itself.

ATF311_8-1652471631373.png

 

 

View solution in original post

15 REPLIES 15
Anonymous
Not applicable

Solution found thanks to @SpartaBI !

 

1. Go to App registration -> New registration

ATF311_2-1652471546706.png

 

2. Give your app a name and use the default settings

ATF311_3-1652471546783.png

 


3. Create a secret, and make sure you copy the right value

ATF311_4-1652471546787.png

 

ATF311_5-1652471546754.png

 


4. Copy the ClientId & TenantId

ATF311_6-1652471546739.png

 

No need to do anything else with the app config.

Just add "MyNewApp" to the AAD security group, wait for a couple of minutes, then try your code.

 

Then for running a Non-Admin API call, the App needs added into the Workspace Permissions you want to read from.

 

You do not need to add any delegated permissions to the app.
In order to allow a service principal access no non-admin APIs, it must have the same dataset/workspace permissions as any other user. For example- you can add the service principal as a member of a workspace.

ATF311_7-1652471631467.png

 



This is exactly the purpose of the other setting in the Admin Portal.
It defines the service principals whose permissions are being managed by the Power BI Service itself.

ATF311_8-1652471631373.png

 

 

SpartaBI
Community Champion
Community Champion

Hi @Anonymous,

I'm not sure why adding the Tenant.ReadAll had any effect on the admin APIs- It shouldn't have.

You do not need to add any delegated permissions to the app.
In order to allow a service principal access no non-admin APIs, it must have the same dataset/workspace permissions as any other user. For example- you can add the service principal as a member of a workspace.

SpartaBI_0-1652464529551.png

This is exactly the purpose of the other setting in the Admin Portal.
It defines the service principals whose permissions are being managed by the Power BI Service itself.

SpartaBI_2-1652464635334.png

If you need to add the service principal programmatically to workspaces, you'll need to use
Add Group User API
or Add User As Admin API

The first API can be authorized by any user or service principal which has the right level of permissions on the workspace (I imagine you do not have an existing service principal to use here...). The second API is not a read-only admin API, so you'll have to use an admin user.

 

Showcase Report – Contoso By SpartaBI


SpartaBI_3-1652115470761.png  SpartaBI_1-1652115142093.png   SpartaBI_2-1652115154505.png

Full-Logo11.png

Anonymous
Not applicable

Thanks again for your help @SpartaBI.

 

I guess the flaw was me using that API call for a dataset refresh schedule that is apparently meant for a My Workspace, but the strange thing is it still worked on a Shared Workspace when I used my PowerShell generated Token.

 

This is what I was trying to use

ATF311_1-1652470823922.png

 

 

This one just worked with the App Token with a groupid and datasetid for a test.

ATF311_0-1652470782471.png

 

I was already trying the workspace permissions thing, but was using the Security Group that had the App's SP account in it. That apparently does not work. Once I added the App itself directly into the workspace permissions, now the GroupId/DatasetId API call works for me.

 

I'll post another reply combining your solutions to mark that 1 response as the solution. Thank you again!

SpartaBI
Community Champion
Community Champion

Hi @Anonymous,

Your M code works fine- I've tried it.

Did you set the configurations in the Power BI Admin Portal to allow service principals access to the Power BI Service & usage of the admin APIs?

SpartaBI_0-1652204772968.png

I'm not sure that you need the first option, but you definitely need the second one.
You should add the service principal (it has the same name as your app) to an AAD security group, then add the latter to both settings.

Anonymous
Not applicable

Yes, we do have everything setup like this, all of the Enabled ones are set for Only our Power BI Admin Security Group.

 

Are you saying you can search for and add the Registered Application into that Security Group? Maybe thats the catch here? I had played around with removing the Only part on these settings so it was Entire Organization to see if that made a difference and it didn't.

 

**Edit, I do see under AD there is a section about Applications when viewing my Security Group. I am not an Azure Admin so I'm checking with one to try and add it here.

 

ATF311_0-1652207084579.png

 

Hi @Anonymous,

Yes. For example, in Azure I have an application

SpartaBI_1-1652208375754.png
which is a member of a security group (the actual member is the service principal of the application)

SpartaBI_2-1652208410023.png

In Power BI, the security group is set for both admin portal categories.

SpartaBI_0-1652208629144.png

I can use "SP Power BI General" to run your script.

Anonymous
Not applicable

We tried this out. No luck. Created a Security Group, Service Principle account, added it into the Group, added the SP to Own the Application, and added the Group onto the Power BI Admin portal in those API settings.

 

You said the M-code worked for you, just to confirm, was it both the GET Access Token and the API Call for Workspaces and Expanded info?

 

Besides doing this, I'm really stuck now. What else makes sense to anyone?

Hi @Anonymous,

Both the GET Access Token and the API Call for Workspaces work for me.

I'm not sure what you mean by "adding the SP to own the application".
I suggest you'll create a new app. From your opening post, I gather you grant it permissions- which is redundant. To create an app do this:

1. Go to App registration -> New registration

SpartaBI_0-1652248383212.png

2. Give your app a name and use the default settings

SpartaBI_2-1652248470054.png
3. Create a secret, and make sure you copy the right value

SpartaBI_3-1652248530902.png

SpartaBI_4-1652248606448.png
4. Copy the ClientId & TenantId

SpartaBI_6-1652248962126.png

No need to do anything else with the app config.

Just add "MyNewApp" to the AAD security group, wait for a couple of minutes, then try your code.

 

 

 

 

Anonymous
Not applicable

Hi @SpartaBI ,

 

Can you clear one thing up for me, how are you adding the App to an AAD security group?

Hi @Anonymous,

You do not need to grant the Power BI Service API Permissions to the App.
Those permissions are used to allow user delegation (i.e., the app acts on behalf of a user account).
When you use "grant_type = client_credentials", you are using the permissions granted to the app's service principal.

Adding the app's service principal to the security group:

Go to your AAD

SpartaBI_0-1652348918009.png


Find the security group
SpartaBI_1-1652348982080.png

SpartaBI_3-1652349081146.png

Choose "Add members"

SpartaBI_4-1652349145153.png
Search for the service principal (same name as the app) and add it

SpartaBI_6-1652349323500.png

 

 

 


2022-05-09 22_36_04-Power BI Workspace Datasets License Permissions - Microsoft Power BI Community.png

Showcase Report – Contoso By SpartaBI


SpartaBI_3-1652115470761.png  SpartaBI_1-1652115142093.png   SpartaBI_2-1652115154505.png

Full-Logo11.png

Anonymous
Not applicable

Hi @SpartaBI 

 

Thank you for your patience and help!

 

We have 95% Success! We created a New App (with no API Permissions) and added both into the Security Group we created just for SP's.

 

*I think my confusion was that a Service Principle exists for the App Registration, and I was thinking it had to somehow use a physically created Service Principle user we created.

 

Our 1st App Registration that had the API Permissions, but was otherwise identical to the 2nd new App Reg, still wouldn't work after adding into the Security Group.

But at least the 2nd App is working in the API.

 

I said 95% because it works on all of my admin/ API calls, but it won't work on a non-Admin call. I have one trying to get the refresh schedules across the list of WorkspaceIDs and that says Access Forbidden. This same function structure works for another one that gets all Users off the Apps because thats an admin/ call.

 

Thoughts??

I'm thinking we need to now add in the API Permissions that the non-Admin calls get treated as Delegated and will need those added? I'm also hoping by adding those permissions, it wouldn't break whats working and cause us to have to recreate again (just saying this because I know how querky MS can be sometimes).

 

*FYI, yes that previous post would be at least part of the solution to this posting, but I'm hoping we figure out how to get this non-Admin API working, then consolidate the answers into 1 post and mark that as the solution. This can hopefully help a lot of people.

 

(datasetId as text) =>
let
Source = Json.Document(Web.Contents("https://api.powerbi.com/v1.0/myorg/",
[
RelativePath = "datasets/" & datasetId & "/refreshSchedule",
Headers=[Authorization="Bearer " & #"GET Access Token"()]
] )),
value = Source[value],
#"Converted to Table" = Table.FromList(value, Splitter.SplitByNothing(), null, null, ExtraValues.Error)
in
#"Converted to Table"

 

 

Anonymous
Not applicable

Hi @SpartaBI *update

 

The strange thing here is that the Admin/ API calls worked, the datasets/ call would say Access Forbidden.

 

We tried adding API Permissions to the App Registration and when doing all of the Read permissions that did not require Azure Admin Consent, nothing changed. Once we added any of the Tenant.ReadAll (Delegated or Application) and had the Azure Admin grant permissions, then the Admin/ API calls stopped working, but the datasets/ still didn't work either.

 

I'm running out of ideas here. When reading the REST API documentation, it does says under the datasets/ that you just needed scope for Datasets.ReadAll or Datasets/ReadWriteAll so I'm not sure why it still refuses to work.

 

I was even trying this call just to make sure it was not relying on any other calls in my PQ steps. It works with my PowerShell retrieved token.

 

let
Source = Json.Document(Web.Contents("https://api.powerbi.com/v1.0/myorg/",
[
RelativePath = "datasets/{datasetid}/refreshSchedule",
Headers=[Authorization="Bearer " & #"GET Access Token"()]
] ))
in
Source

Anonymous
Not applicable

My comment about making the SP an Owner was because your picture of the App Registration that showed your SP account was an Owner on the application, I thought that was something also necessary for this to work. We can move on from that now.

 

Are you saying that you don't need to grant the Power BI Service API Permissions on this App Registration though?

ATF311_0-1652269918812.png

 

SpartaBI
Community Champion
Community Champion

Hi @Anonymous,

You manage to use a Power BI Admin API from Powershell, but fail to run the same call from PQ?
Can you share your code?

The Web.Contents doc lists a "ManualStatusHandling" parameter.
I believe you can use it to specify {401} in order to receive the actual error message.

Anonymous
Not applicable

Just to clarify something, the way I used to get my access token when doing this more manually, before trying to automate by using the Registered App, I went to the Microsoft Documents site for the Power BI APIs. You used to be able to click Try It and in that window you could copy out your Access Token. Microsoft for some reason removed that part of the website and you can't Try It anymore. I wasn't having success getting a good token either from Postman, so I went the PowerShell route just for the manual token so I can at least use the report yet while trouble shooting this Registered App token usage.

 

PowerShell was simple, just made sure to have the cdmlets, #1 logged in (didn't matter if ServiceAccount or personal Login), and then ran the #2 to Get Token

  1.      Connect-PowerBIServiceAccount
  2.      Get-PowerBIAccessToken -AsString

 

Parameter values that are not my sensitive data are:

grant_type = client_credentials

resource = https://analysis.windows.net/powerbi/api

 

This is the M-code getting the Token from the Registered App

() =>
let
body = "grant_type=" & grant_type & "&client_id=" & client_id & "&client_secret=" & client_secretvalue & "&resource=" & resource,
Data = Json.Document(Web.Contents("https://login.microsoftonline.com/" & tenant_id & "/oauth2/token/", [Headers=[#"Content-Type"="application/x-www-form-urlencoded"], Content=Text.ToBinary(body)])),
access_token = Data[access_token]
in
access_token

 

 

This is the M-code where I am running one of the API calls. *Notice where I have the CurrentToken parameter being used, which uses the PowerShell produced Token. Once I remove that and use the GET Access Token Function, it won't work. I have even tested invoking the Function and pasting the result into the CurrentToken and didn't make a difference

 

let
Source = Json.Document(Web.Contents("https://api.powerbi.com/v1.0/myorg/",
[
RelativePath = "admin/groups?$top=5000&$expand=datasets,dataflows,reports,dashboards,users",
Headers=[Authorization="Bearer " & CurrentToken/*#"GET Access Token"()*/]
] )),
value = Source[value],
#"Converted to Table" = Table.FromList(value, Splitter.SplitByNothing(), null, null, ExtraValues.Error)
in
#"Converted to Table"

 

 

Helpful resources

Announcements
July 2024 Power BI Update

Power BI Monthly Update - July 2024

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

July Newsletter

Fabric Community Update - July 2024

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