TibJnt
TibJnt

Reputation: 11

How to Embed Power BI Report in React app ? Access Token, Master User etc

I am creating a react web application to display power bi reports to my customers.

The flow is the following :

I am following a "embed for customers scenario" with a master user approach.

If I understood well, the authentication flow is like that : _ When a user authenticate with firebase, he goes to the dashboard page _ to render the power bi dashboard, I first need to authenticate against Azure AD (with clientSecret, clientID and TenantID) and receive an access token for the user.

Here is my code for dashboard.jsx, where I try to embed the power BI report :

import React from 'react'
import { PowerBIEmbed } from 'powerbi-client-react';
import { models } from 'powerbi-client';
import axios from 'axios';
import { useEffect, useState } from 'react';


const obtainAccessToken = async () => {
  try {
      const tokenUrl = `https://login.microsoftonline.com/${import.meta.env.VITE_AZURE_TENANT_ID}/oauth2/token`;

      const headers = {
          "Content-Type": "application/x-www-form-urlencoded",
      };

      const body = new URLSearchParams();
      body.append('client_id', import.meta.env.VITE_AZURE_CLIENT_ID);
      body.append('client_secret', import.meta.env.VITE_AZURE_CLIENT_SECRET);
      body.append('grant_type', 'client_credentials');
      body.append('resource', 'https://analysis.windows.net/powerbi/api');

      const response = await axios.post(tokenUrl, body, { headers });
      console.log('access token = ' + response.data.access_token);
      return response.data.access_token;
  } catch (error) {
      console.error(error);
  }
};

function Dashboard() {
  
  const [accessToken, setAccessToken] = useState(null);
  
  useEffect(() => {
    obtainAccessToken().then((token) => {
      setAccessToken(token);
    });
  }, []);

  return (
      <PowerBIEmbed
        embedConfig = {{
          type: 'report',   // Supported types: report, dashboard, tile, visual and qna
          id: 'eff45871-db5c-4bd6-a953-c492f6045044',
          embedUrl: 'https://app.powerbi.com/reportEmbed?reportId=eff45871-db5c-4bd6-a953-c492f6045044&groupId=b1554fa1-bd00-4640-850f-efc22a60b64c&w=2&config=eyJjbHVzdGVyVXJsIjoiaHR0cHM6Ly9XQUJJLUZSQU5DRS1DRU5UUkFMLUEtUFJJTUFSWS1yZWRpcmVjdC5hbmFseXNpcy53aW5kb3dzLm5ldCIsImVtYmVkRmVhdHVyZXMiOnsibW9kZXJuRW1iZWQiOnRydWUsInVzYWdlTWV0cmljc1ZOZXh0Ijp0cnVlfX0%3d',
          accessToken: accessToken,
          tokenType: models.TokenType.Aad,
          settings: {
            panes: {
              filters: {
                expanded: false,
                visible: false
              }
            },
            background: models.BackgroundType.Transparent,
          }
        }}

        eventHandlers = { 
          new Map([
            ['loaded', function () {console.log('Report loaded');}],
            ['rendered', function () {console.log('Report rendered');}],
            ['error', function (event) {console.log(event.detail);}]
          ])
        }
          
        cssClassName = { "Embed-container" }

        getEmbeddedComponent = { (embeddedReport) => {
          window.report = embeddedReport;
        }}
      />

        )
  }

export default Dashboard

The result I get with this code, a forever loading power BI logo and the following errors in the chrome dev tool console :

dashboard page waiting for power bi to load

chromeDevTool console

It seems like I cant get the access token from Azure AD. Maybe there is another problem I cant see. Has anyone an idea on how to solve the issue ? Thanks in advance !

Upvotes: 1

Views: 5570

Answers (2)

Bastek
Bastek

Reputation: 83

I've had the same problem.

Maybe to late, but i will show how I managed to solve it using @azure/react and @azure/msal-browser library.

First of all you need to register Power BI for your organization. More you can find here: https://learn.microsoft.com/en-us/power-bi/developer/embedded/register-app?tabs=customers

After that if you have client_id for your power bi application from azure portal you need to create new instance of msal instance which might looks like this:

const config = {
    auth: {
        clientId: registered_power_bi_client_id,
        authority: https://login.microsoftonline.com/your_tenant_app_id,
    },
    cache: {
        cacheLocation: 'localStorage',
        storeAuthStateInCookie: false,
    },
};

export const instance = new PublicClientApplication(config);

const loginRequest: PopupRequest = {
    scopes: [power_bi_scope], // might look like this https://analysis.windows.net/powerbi/api/Report.Read.All
    account: currently_logged_in_user,
    redirectUri: redirect_uri, // page when 
};

export const getPowerBiToken = async () => {
    let token;

    try {
        await instance.initialize();
        const res = await instance.acquireTokenSilent(loginRequest);
        token = res?.accessToken
    } catch {
        const res = await instance.acquireTokenPopup(loginRequest);
        token = res?.accessToken;
    }

    return token;
};

Then getPowerBiToken func you can utilize inside youre component logic.

If you login for the first time to the app the popup should appear asking for login. After successfull login you should get proper access token.

After that token should be acquired silently using acquireTokenSilent method.

Upvotes: 0

Kotana Sai
Kotana Sai

Reputation: 1810

Using React Developer Samples we can Embed for organization. But in your case, embed for customers, In MSAL-React, ClientCredential Auth flow is designed for Confidential Client applications. msal-react is an auth library which supports only SPA type of apps which are public client applications, hence there is no support for ClientCredential flow in the library.

So, workaround is to get the Embed Token from Azure Function.

  1. Create a HTTP Trigger function in azure portal and implement C# code to get the token using the client_credentials.
  2. Get the function URL and in React App fetch the URL to get the embedUrl, Access Token for Embedding Report.

Feel free to Reach out if you face any problems with creating the function and code to get the token in azure portal.

You can Refer to React Demo GitHub Repository.

Upvotes: 3

Related Questions