PowerBi-API Node.js Connection doesn´t work

31 Views Asked by At

I've got a problem with my PowerBI-API / Node.js connection and I don´t know how to solve it. I use Node.js to get a dataset from Google sheets (so far it works). Now I want to automate Power BI. To do this, I created a new project in Azure AD and set the permissions to tenant.ReadWrite.all. My problem now is that I keep getting the status code 401 with my code. Unfortunately I don´t know where this comes from and how I can solve it.

I noticed that i don´t have a static access token, but rather it always changes. That´s why I built in a function so that I can see whether it is still valid. I already have the clientId, clientSecret, tenantId, reportId and tableId checked.

I have this output:

Step 1: Obtain access token
Step 2: Access token received successfully
Token expiration time: +055742-08-28T18:16:01.842Z
Step 3: API request error: Request failed with status code 401
API-Answer:
HTTP-Statuscode: 401

I have this code:

const msal = require('@azure/msal-node');
const axios = require('axios');

const reportId = '123456';
const tableId = 'ReportSection123456';
const tenantId = '123456';
const apiUrl = `https://api.powerbi.com/v1.0/myorg/reports/${reportId}/tables/${tableId}/rows`;
// const apiUrl = `https://api.powerbi.com/v1.0/myorg/reports/${reportId}/`;
const clientId = '123456';
const clientSecret = 'abc123456';

const config = {
    auth: {
        clientId: clientId,
        clientSecret: clientSecret,
        authority: `https://login.microsoftonline.com/${tenantId}`,
        knownAuthorities: [`https://login.microsoftonline.com/${tenantId}`],
    }
};

const cca = new msal.ConfidentialClientApplication(config);

let cachedAccessToken = null;
let tokenExpiration = null;

async function getAccessToken() {
    if (cachedAccessToken && !isTokenExpired()) {
        return cachedAccessToken;
    } else {
        const tokenRequest = {
            scopes: ['https://analysis.windows.net/powerbi/api/.default'],
        }

        try {
            const response = await cca.acquireTokenByClientCredential(tokenRequest);
            const accessToken = response.accessToken;

            cachedAccessToken = accessToken;
            tokenExpiration = Date.now() + response.expiresOn * 1000; 

            return accessToken;
        } catch (error) {
            console.error ('Error getting access token: ', error.message);
            throw error;
        }
    }
}

function isTokenExpired() {
    return Date.now() <= tokenExpiration;
}

console.log('Step 1: Obtain access token');

getAccessToken().then(accessToken => {
    console.log('Step 2: Access token received successfully');
    console.log('Token expiration time: ', new Date(tokenExpiration));


    axios.get(apiUrl, {
        headers: {
            'Authorization': `Bearer ${accessToken}`
        }
    })
    .then(response => {
        console.log('Step 3: API request successful');

        if(response.status === 200) {
            console.log('Data from the table: ', response.data);
        } else {
            console.log('Error calling table:', response.status);
            throw new Error('Error retrieving table. ');
        }
    })
    .catch(error => {
        console.error('Step 3: API request error: ', error.message);

        if (error.response) {
            console.error('API-Answere: ', error.response.data);
            console.error('HTTP-Statuscode: ', error.response.status);
        }
    });
}).catch(error => {
    console.error('Step 2: Error getting access token: ', error.message)
});

I´m using wrong libraries, is my code wrong or is it something else? Can someone help me?

0

There are 0 best solutions below