2

We've been trying to follow this Power BI article so that we can embed reports/dashboards in our SaaS product. Specifically, we're stuck at Step 3, 'Create the Embed Token.'

We're able to obtain an bearer token just fine but when the request to retrieve the reports is ultimately submitted to the API we receive:Operation returned an invalid status code 'Forbidden'

    private static string clientId = "...";
    private static string secretKey = "...";
    private static string groupId = "...";

    static void Main(string[] args)
    {
        string resourceUri = "https://analysis.windows.net/powerbi/api";
        string authorityUri = "https://login.windows.net/common/oauth2/authorize";

        ClientCredential credential = new ClientCredential(clientId, secretKey);
        AuthenticationContext authContext = new AuthenticationContext(authorityUri);

        var token = authContext.AcquireTokenAsync(resourceUri, credential).Result.AccessToken;

        var tokenCredentials = new TokenCredentials(token, "Bearer");

        using (var client = new PowerBIClient(new Uri("https://api.powerbi.com/"), tokenCredentials))
        {
            var reports = client.Reports.GetReportsInGroupWithHttpMessagesAsync(groupId);

            // !!! - Here's where the exception is thrown
            // !!! -- Operation returned an invalid status code 'Forbidden'
            var report = reports.Result.Body;
        }
    }

Here's what we've tried:

  • The required permissions have been granted (we've checked off all to ensure we're not missing anything). This includes both Windows Azure Active Directory/Power BI Service.
  • We've confirmed that the client ID, secret key and group id are correct.
  • The Power BI work-space is private, but we've tried making a public one to be sure it doesn't matter.
  • Finally, the token we receive via code matches the token on powerbi.com.
leemac
  • 350
  • 1
  • 5
  • 15

5 Answers5

4

You are using client credential flow to acquire token for Power BI API . Currently , Power BI REST API only supports delegated permissions but does not support any application permissions . So your access token get insufficient access. To use Power BI, authentication needs to be based on a particular user. Related thread here and here are for your reference .

According to your document ,the scenario is app owns access to the data. Users will not necessarily be Power BI users and the application controls authentication and access for the end users. Then you can use resource owner flow to acquiring token .

A sample of this is available within Controllers\HomeController.cs of the App Owns Data sample.

From the code sample , it is acquring token using a user password credential ,not application's credential :

            // Create a user password cradentials.
            var credential = new UserPasswordCredential(Username, Password);

            // Authenticate using created credentials
            var authenticationContext = new AuthenticationContext(AuthorityUrl);
            var authenticationResult = await authenticationContext.AcquireTokenAsync(ResourceUrl, ClientId, credential);

Please refer to Authenticate users and get an Azure AD access token for your Power BI app and check the Access token for non-Power BI users (app owns data) section .

Nan Yu
  • 26,101
  • 9
  • 68
  • 148
  • Thank you Nan Yu, however, this obtains the exact same token I've obtained in my sample. I've tried the sample you suggested before but received an error "The request body must contain the following parameter: 'client_secret or client_assertion'. The suggestions online suggest creating a 'Native App,' but this too leaves me with an error (UnAuthorized). – leemac Sep 08 '17 at 13:24
  • we can only use the resource owner flow from a native client. A confidential client, such as a web site, cannot use direct user credentials. What is the detailed error message When you get "UnAuthorized" error ? – Nan Yu Sep 11 '17 at 05:29
  • Thank you Nan. We spoke with a Microsoft rep and explained the above a little more in detail for us. We had to use a native client app and not a web app as instructed in the tutorials. Very confusing, but it seems to work. What threw us off is that it said "Native (desktop/mobile/etc)" when registering the app. – leemac Sep 24 '17 at 16:01
  • Thanks for the info. But in the link you are referring to there is https://learn.microsoft.com/en-us/power-bi/developer/get-azuread-access-token#access-token-with-service-principal a section where it is stated that access token with service principal(which implicitly means without user login) is possible. Isn't it? So it means one should be able to get embed token without giving user/pwd but client credentials instead. Many power bi documents state this. Reason i am writing this is I am also failing with 403 while trying to get embed token via Power Bi REST API. – selman Aug 02 '19 at 13:56
  • The `Access token for non-Power BI users` section doesn't exist anymore unfortunately :/ – Noah Gary Jul 29 '21 at 17:44
0

We have found that the group (App Workspace) needs to be owned by the same user who authenticates with Azure. This user also needs to be listed as the owner on the Azure App that you register.Once you revised permissions. Don't forget to republish powerbi report then only it reflects changes.

Kas Elvirov
  • 7,394
  • 4
  • 40
  • 62
dev.bv
  • 980
  • 9
  • 16
0

The best way to get the real exceptions from Power BI is to add a DelegatingHandler and look at the headers / body of the message.

https://github.com/Microsoft/PowerBI-CSharp/compare/master...mikeblakeuk:feature/exceptionHandler

Michael Blake
  • 2,068
  • 2
  • 18
  • 31
0

This is because you are trying to call some Reports/Dashboards that are in My Workspace using the SPN authentication. Currently this is the known limitation for SPN

Reference

enter image description here

Jayendran
  • 9,638
  • 8
  • 60
  • 103
0

Certain Power Bi Apis can only be accessed by using a profile Id it must be sent over the HTTP headers (X-PowerBI-Profile-Id)

The profile api can be invoked using the token associated to the service principal this way:

POST https://api.powerbi.com/v1.0/myorg/profiles HTTP/1.1
Authorization: Bearer eyJ0eXAiOiJK…UUPA
Content-Type: application/json; charset=utf-8

{"displayName":"ContosoProfile"}

It will return the profile id:

{
"@odata.context": "http://wabi-west-us- 
 redirect.analysis.windows.net/v1.0/myorg/$metadata#profiles",
"value": [
    {
        "id": "a4df5235-6f18-4141-9e99-0c3512f41306",
        "displayName": "ContosoProfile"
    }
 ]
}

After that, consume the power bi api sending the profile id into the http header X-PowerBI-Profile-Id along with the Authorization header, for instance to create a new workspace:

POST https://api.powerbi.com/v1.0/myorg/groups HTTP/1.1
Authorization: Bearer eyJ0eXA…ZUiIsg
Content-Type: application/json; charset=utf-8
X-PowerBI-Profile-Id: a4df5235-6f18-4141-9e99-0c3512f41306

{
 "name": "ContosoWorkspace"
}

Reference: https://learn.microsoft.com/en-us/power-bi/developer/embedded/embed-multi-tenancy

Jorge Valvert
  • 927
  • 1
  • 11
  • 20