Reputation: 11
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
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
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
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.
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