Forum Discussion
Power BI Embedded for React possible?
I had the same requirement, having spent lot of time googling and going through couple of above suggested approaches, I could finally embed the reports into react app; But there comes the problem "Explicit Authentication", meaning user needs to login through azure ad login, upon successful login response redirects to application based on redirect_url configuration in azure application dashboard. Which didn't suit my requirement because user had already logged in to our application with regular credentials;
What I thought was the best approach is:
- Use silent async login and get token
- Pass the tokent to PowerBI Embed API
For step 1: I have written simple curl node service
const { Curl } = require('node-libcurl');
const path = require('path');
const tls = require('tls')
const fs = require('fs')
module.exports = {
powerBiAuth: async (req, res) => {
const certFilePath = path.join(__dirname, 'cert.pem')
const tlsData = tls.rootCertificates.join('\n')
fs.writeFileSync(certFilePath, tlsData)
const url = 'https://login.microsoftonline.com/common/oauth2/token';
const opts = [
{ name: 'grant_type', contents: 'password'},
{ name: 'scope', contents: 'openid'},
{ name: 'resource', contents: 'https://analysis.windows.net/powerbi/api'},
{ name: 'client_id', contents: '*******-****-****-****-*********'},
{ name: 'username', contents: 'user-email'},
{ name: 'password', contents: 'password'},
];
const curl = new Curl();
curl.setOpt('URL', url);
curl.setOpt('FOLLOWLOCATION', true);
curl.setOpt('caInfo', certFilePath);
curl.setOpt('verbose', true);
curl.setOpt(Curl.option.HTTPPOST, opts);
curl.on('end', function (statusCode, data, headers) {
console.info(statusCode);
console.info('---');
console.info(data.length);
console.info('---');
console.info(this.getInfo('TOTAL_TIME'));
res.render(data);
this.close();
});
curl.on('error', function(err){
console.log(err)
});
curl.perform();
},
}
Step 2: Call the above service and get the token in react
import React, { useState, lazy,useEffect } from 'react';
import { PowerBIEmbed } from 'powerbi-client-react';
import { models } from 'powerbi-client';
class Report extends React.Component {
constructor(props) {
super(props);
this.state = {
accessToken: ""
};
}
componentDidMount(){
this.getAccessToken();
}
getAccessToken() {
const thisObj = this;
let headers = new Headers();
fetch("/user/powerbi-auth", { //replace with ur service url
method: "GET"
})
.then(function (response) {
response.json()
.then(function (body) {
// Successful response
if (response.ok) {
const toknResp = JSON.parse(body.data);
thisObj.setState({ accessToken: toknResp.access_token});
}
})
.catch(function (e) {
console.log(e);
thisObj.setState({ error: e });
});
})
.catch(function (error) {
// Error in making the API call
thisObj.setState({ error: error });
})
}
render() {
if (!this.state.accessToken) {
return <span>Loading...</span>
}
return (
<PowerBIEmbed
embedConfig={{
type: 'report', // Supported types: report, dashboard, tile, visual and qna
id: '*********************', //client_id
embedUrl: "", //embed url, if u dont knw refer powerbi api docs
accessToken: this.state.accessToken,
tokenType: models.TokenType.Aad,
settings: {
panes: {
filters: {
expanded: false,
visible: true
}
},
}
}}
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 Report;