How can i, using API, retrieve all PowerBI apps with links using a frontend javascript application?

Viewed 66

PowerBI has a good API, but i probably making a mistake with the flow to retrieve data from it.

What we need to do:

  1. Get Power BI apps listed in a menu.
  2. With the menu, when a user click on a app link, the app should render on an iframe.

What we got so far:

  1. We can call the oauth and generate tokens to interact with the API.
  2. We can call the API and retrieve results.

The problems we're facing:

  1. Lack of security to generate the token. We shouldn't make APPLICATION_ID and APPLICATION_SECRET available to frontend by security reasons. A better solution could be generate the application links using a backend for that, but this is not desirable by our deploy requirements.
  2. We're facing issues related to CSP.iframe with source to the app Refused to frame 'https://app.powerbi.com/' because it violates the following Content Security Policy directive: "child-src 'none'". Note that 'frame-src' was not explicitly set, so 'child-src' is used as a fallback.

Example code (not the real code. just a draft):

var apps = [];
var APPLICATION_ID = "NOT INFORMED HERE";

axios.get("POWERBI URL").then(function(result) {
    result["values"].forEach((item) => {
        apps.push({id:item.id, name:item.name, link:`https://app.powerbi.com/Redirect?action=OpenApp&appId=${item.id}&ctid=${APPLICATION_ID}`})
    });
});

Any idea of how can we get this done considering security and front-end only approach?

1 Answers

Add reportId, workspaceId and all details to the request and fetch the details from the request.

// Add report id in the request
let formData = {
  reports: [
    {
      id: reportId,
    },
  ],
};

// Add dataset ids in the request
formData["datasets"] = [];
for (const datasetId of datasetIds) {
  formData["datasets"].push({
    id: datasetId,
  });
}

// Add targetWorkspace id in the request
if (targetWorkspaceId) {
  formData["targetWorkspaces"] = [];
  formData["targetWorkspaces"].push({
    id: targetWorkspaceId,
  });
}

const embedTokenApi = "https://api.powerbi.com/v1.0/myorg/GenerateToken";
const headers = await getRequestHeader();

// Generate Embed token for single report, workspace, and multiple datasets. Refer https://aka.ms/MultiResourceEmbedToken
const result = await fetch(embedTokenApi, {
  method: "POST",
  headers: headers,
  body: JSON.stringify(formData),
});

enter image description here

Alternate way you can do is to use Manage Service Identity (MSI) to get the certificate from Azure Key vault where one don't need to manage credentials evens credentials are not accessible.

References:

https://docs.microsoft.com/power-bi/developer/embedded/embed-service-principal-certificate#step-4---get-the-certificate-from-azure-key-vault

Related