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?