Forum Discussion

Anonymous's avatar
Anonymous
Not applicable
6 years ago

Power BI Embedded for React possible?

What is required for making possible that Power BI report is embedded to React based web portal?

Can React front-end connect to Power BI Service directly or is back-end application (Node) required?

Any tutorial or sample for this scenario?

2 Replies

  • Anonymous's avatar
    Anonymous
    Not applicable

    Hi  

    Power BI and React do work well together... and there isn't too much that you need to do in order to get started.
    I have written a couple of closed-source projects this way (but unfortunately cannot share the code here).

    The Power BI Wiki (which you have probably already seen) details the use of most features, and once you have written the initial 'embed initialisation' code - all functions work as documented.

    The trick is to make sure that changes in state/props don’t force a re-render of your embedding component.
    A quick search highlighted this blog post and associated GitHub project (I am not associated with this project in any way) -> but this could act as a starter/guide for creating your own components. https://medium.com/@akshay5995/how-to-embed-microsoft-powerbi-charts-into-your-react-application-a3078edf5dc6 GitHub: https://github.com/akshay5995/powerbi-report-component

     

    One last thing to consider.... Authentication!

    You can perform embedding without server-side/backend services, but if you go down the 'app owns data' route - and use a data model that implements Row Level Security, then you will likely want to move the embedding-token generation logic/api calls to a backend service. Otherwise you will leave yourself open to security flaws by allowing users to potentially manipulate user roles within the browser.

    Feel free to keep asking questions if you have anything more specific.
    Hope this helps.

     

    Cheers,
    Matt

  • Anonymous's avatar
    Anonymous
    Not applicable

    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:

    1. Use silent async login and get token
    2. 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;