尝试使用 JavaScript 从 azure 获取访问令牌时加载响应数据失败
Failed to load response data when tried to get access token from azure using JavaScript
我想为我在 Azure 上注册的应用程序获取访问令牌。为此,我写了一段代码来点击 rest-API.
这是我的代码:
<html>
<head>
<title>Test</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://secure.aadcdn.microsoftonline-p.com/lib/1.0.12/js/adal.min.js"></script>
<script src="/static/powerbi.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="captionArea">
<h1>Power BI Embed test</h1>
</div>
<div id="embedContainer" style="height:500px">
</div>
<script>
(function () {
var reportId = 'xxxxxxxxxx'
var groupId = 'xxxxxxxxxx' //workspace_id
var datasetId = 'xxxxxxxxxx'
var settings = {
"url": "https://login.microsoftonline.com/common/oauth2/token",
"method": "POST",
"crossDomain": true,
"dataType": 'jsonp',
"timeout": 0,
"headers": {
"Content-Type": "application/x-www-form-urlencoded"
},
"data": {
"client_id": "********",
"username": "***",
"password": "***",
"grant_type": "password",
"resource": "https://analysis.windows.net/powerbi/api"
}
};
$.ajax(settings).done(function (response) {
console.log(response);
});
}());
</script>
</body>
</html>
在此之后,我收到了回复。在控制台中,在 header 部分下,我得到状态:200 和请求方法:GET 但在我的代码中,请求方法是“POST”,在响应部分,它显示“This请求没有可用的响应数据”:
我不知道,为什么我没有收到任何响应以及我的请求方法如何从“POST”更改为“GET”?
您的数据类型为 JSONP。它只是创建一个元素来获取必须是 GET 请求的数据。
参考:
How to use type: "POST" in jsonp ajax call
您可以通过发出 POST 请求获得响应,然后使用获得的访问令牌作为嵌入令牌。
如下所示:
var getAccessToken = function {
return new Promise(function(resolve, reject) {
var url = 'https://login.microsoftonline.com/common/oauth2/token';
var username = // Username of PowerBI "pro" account - stored in config
var password = // Password of PowerBI "pro" account - stored in config
var clientId = // Applicaton ID of app registered via Azure Active Directory - stored in config
var headers = {
'Content-Type' : 'application/x-www-form-urlencoded'
};
var formData = {
grant_type:'password',
client_id: clientId,
resource:'https://analysis.windows.net/powerbi/api',
scope:'openid',
username:username,
password:password
};
request.post({
url:url,
form:formData,
headers:headers
}, function(err, result, body) {
if(err) return reject(err);
var bodyObj = JSON.parse(body);
resolve(bodyObj.access_token);
})
});
}
// -------------------------------------------
var getEmbedToken = function(accessToken, groupId, reportId) {
return new Promise(function(resolve, reject) {
var url = 'https://api.powerbi.com/v1.0/myorg/groups/' + groupId + '/reports/' + reportId + '/GenerateToken';
var headers = {
'Content-Type' : 'application/x-www-form-urlencoded',
'Authorization' : 'Bearer ' + accessToken
};
var formData = {
"accessLevel": "View"
};
request.post({
url:url,
form:formData,
headers:headers
}, function(err, result, body) {
if(err) return reject(err);
console.log(body)
var bodyObj = JSON.parse(body);
resolve(bodyObj.token);
})
})
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="js/msal.js"></script>
</head>
<body>
<div style="font-size: 12px;">
this sample used implicit grant flow to get access token
</div>
<div style="margin-top: 15px; background-color: #DDDDDD;">
<button type="button" id="signIn" onclick="signIn()">Sign In</button>
<button type="button" id="getAccessToken" onclick="getAzureAccessToken()">getAccessToken</button>
<button type="button" id="accessApi" onclick="accessApi()">getApiResponse</button>
<h5 class="card-title" id="welcomeMessage">Please sign-in to see your profile and read your mails</h5>
<div>
<div>
accesstoken :
<div id="accesstoken">
</div>
</div>
<div id="">
api response :
<div id="json">
</div>
</div>
</div>
</div>
<script type="text/javascript">
const msalConfig = {
auth: {
clientId: "<applicationId>",
authority: "https://login.microsoftonline.com/<tenantId>",
redirectUri: "http://localhost:8848/Demo0819/new_file.html",
},
cache: {
cacheLocation: "sessionStorage", // This configures where your cache will be stored
storeAuthStateInCookie: false, // Set this to "true" if you are having issues on IE11 or Edge
}
};
const loginRequest = {
scopes: ["openid", "profile", "User.Read"]
};
//scope for getting accesstoken
const AzureMgmtScops ={
scopes:["https://management.azure.com/user_impersonation"]
}
//used for calling api
const apiConf = {
endpoint:"https://management.azure.com/subscriptions/<subscriptionId>/providers/Microsoft.CostManagement/query?api-version=2019-11-01"
};
let accessToken = '';
const myMSALObj = new Msal.UserAgentApplication(msalConfig);
function signIn() {
myMSALObj.loginPopup(loginRequest)
.then(loginResponse => {
console.log("id_token acquired at: " + new Date().toString());
console.log(loginResponse);
if (myMSALObj.getAccount()) {
showWelcomeMessage(myMSALObj.getAccount());
}
}).catch(error => {
console.log(error);
});
}
function showWelcomeMessage(account) {
document.getElementById("welcomeMessage").innerHTML = `Welcome ${account.name}`;
}
function getAzureAccessToken(){
myMSALObj.acquireTokenSilent(AzureMgmtScops).then(tokenResponse => {
showAccesstoken(tokenResponse.accessToken)
accessToken = tokenResponse.accessToken;
// console.info("======the accesstoken is ======:"+tokenResponse.accessToken);
// callMSGraph(apiConf.endpoint, tokenResponse.accessToken, showResult);
}).catch(function (error) {
console.log(error);
})
}
function accessApi(){
callMSGraph(apiConf.endpoint, accessToken, showResult);
}
function callMSGraph(endpoint, token, callback) {
const data = {
"type": "Usage",
"timeframe": "MonthToDate",
"dataset": {
"granularity": "Daily",
}
}
const headers = new Headers();
const bearer = `Bearer ${token}`;
headers.append("Content-Type", "application/json");
headers.append("Authorization", bearer);
const options = {
body: JSON.stringify(data),
method: "POST",
headers: headers
};
console.log('request made to Graph API at: ' + new Date().toString());
fetch(endpoint, options)
.then(response => response.json())
.then(response => callback(response, endpoint))
.catch(error => console.log(error))
}
function showAccesstoken(data){
document.getElementById("accesstoken").innerHTML = JSON.stringify(data, null, 2);
}
function showResult(data){
document.getElementById("json").innerHTML = JSON.stringify(data, null, 2);
}
</script>
</body>
</html>
=========更新======
例如
我想调用这个 api 来获取信息 'https://api.powerbi.com/v1.0/myorg/groups' ,所以先添加 api 权限。
下一步是获取此范围的访问令牌。
有了这个访问令牌,调用 api 就可以了。
我想为我在 Azure 上注册的应用程序获取访问令牌。为此,我写了一段代码来点击 rest-API.
这是我的代码:
<html>
<head>
<title>Test</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://secure.aadcdn.microsoftonline-p.com/lib/1.0.12/js/adal.min.js"></script>
<script src="/static/powerbi.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="captionArea">
<h1>Power BI Embed test</h1>
</div>
<div id="embedContainer" style="height:500px">
</div>
<script>
(function () {
var reportId = 'xxxxxxxxxx'
var groupId = 'xxxxxxxxxx' //workspace_id
var datasetId = 'xxxxxxxxxx'
var settings = {
"url": "https://login.microsoftonline.com/common/oauth2/token",
"method": "POST",
"crossDomain": true,
"dataType": 'jsonp',
"timeout": 0,
"headers": {
"Content-Type": "application/x-www-form-urlencoded"
},
"data": {
"client_id": "********",
"username": "***",
"password": "***",
"grant_type": "password",
"resource": "https://analysis.windows.net/powerbi/api"
}
};
$.ajax(settings).done(function (response) {
console.log(response);
});
}());
</script>
</body>
</html>
在此之后,我收到了回复。在控制台中,在 header 部分下,我得到状态:200 和请求方法:GET 但在我的代码中,请求方法是“POST”,在响应部分,它显示“This请求没有可用的响应数据”:
我不知道,为什么我没有收到任何响应以及我的请求方法如何从“POST”更改为“GET”?
您的数据类型为 JSONP。它只是创建一个元素来获取必须是 GET 请求的数据。
参考:
How to use type: "POST" in jsonp ajax call
您可以通过发出 POST 请求获得响应,然后使用获得的访问令牌作为嵌入令牌。
如下所示:
var getAccessToken = function {
return new Promise(function(resolve, reject) {
var url = 'https://login.microsoftonline.com/common/oauth2/token';
var username = // Username of PowerBI "pro" account - stored in config
var password = // Password of PowerBI "pro" account - stored in config
var clientId = // Applicaton ID of app registered via Azure Active Directory - stored in config
var headers = {
'Content-Type' : 'application/x-www-form-urlencoded'
};
var formData = {
grant_type:'password',
client_id: clientId,
resource:'https://analysis.windows.net/powerbi/api',
scope:'openid',
username:username,
password:password
};
request.post({
url:url,
form:formData,
headers:headers
}, function(err, result, body) {
if(err) return reject(err);
var bodyObj = JSON.parse(body);
resolve(bodyObj.access_token);
})
});
}
// -------------------------------------------
var getEmbedToken = function(accessToken, groupId, reportId) {
return new Promise(function(resolve, reject) {
var url = 'https://api.powerbi.com/v1.0/myorg/groups/' + groupId + '/reports/' + reportId + '/GenerateToken';
var headers = {
'Content-Type' : 'application/x-www-form-urlencoded',
'Authorization' : 'Bearer ' + accessToken
};
var formData = {
"accessLevel": "View"
};
request.post({
url:url,
form:formData,
headers:headers
}, function(err, result, body) {
if(err) return reject(err);
console.log(body)
var bodyObj = JSON.parse(body);
resolve(bodyObj.token);
})
})
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="js/msal.js"></script>
</head>
<body>
<div style="font-size: 12px;">
this sample used implicit grant flow to get access token
</div>
<div style="margin-top: 15px; background-color: #DDDDDD;">
<button type="button" id="signIn" onclick="signIn()">Sign In</button>
<button type="button" id="getAccessToken" onclick="getAzureAccessToken()">getAccessToken</button>
<button type="button" id="accessApi" onclick="accessApi()">getApiResponse</button>
<h5 class="card-title" id="welcomeMessage">Please sign-in to see your profile and read your mails</h5>
<div>
<div>
accesstoken :
<div id="accesstoken">
</div>
</div>
<div id="">
api response :
<div id="json">
</div>
</div>
</div>
</div>
<script type="text/javascript">
const msalConfig = {
auth: {
clientId: "<applicationId>",
authority: "https://login.microsoftonline.com/<tenantId>",
redirectUri: "http://localhost:8848/Demo0819/new_file.html",
},
cache: {
cacheLocation: "sessionStorage", // This configures where your cache will be stored
storeAuthStateInCookie: false, // Set this to "true" if you are having issues on IE11 or Edge
}
};
const loginRequest = {
scopes: ["openid", "profile", "User.Read"]
};
//scope for getting accesstoken
const AzureMgmtScops ={
scopes:["https://management.azure.com/user_impersonation"]
}
//used for calling api
const apiConf = {
endpoint:"https://management.azure.com/subscriptions/<subscriptionId>/providers/Microsoft.CostManagement/query?api-version=2019-11-01"
};
let accessToken = '';
const myMSALObj = new Msal.UserAgentApplication(msalConfig);
function signIn() {
myMSALObj.loginPopup(loginRequest)
.then(loginResponse => {
console.log("id_token acquired at: " + new Date().toString());
console.log(loginResponse);
if (myMSALObj.getAccount()) {
showWelcomeMessage(myMSALObj.getAccount());
}
}).catch(error => {
console.log(error);
});
}
function showWelcomeMessage(account) {
document.getElementById("welcomeMessage").innerHTML = `Welcome ${account.name}`;
}
function getAzureAccessToken(){
myMSALObj.acquireTokenSilent(AzureMgmtScops).then(tokenResponse => {
showAccesstoken(tokenResponse.accessToken)
accessToken = tokenResponse.accessToken;
// console.info("======the accesstoken is ======:"+tokenResponse.accessToken);
// callMSGraph(apiConf.endpoint, tokenResponse.accessToken, showResult);
}).catch(function (error) {
console.log(error);
})
}
function accessApi(){
callMSGraph(apiConf.endpoint, accessToken, showResult);
}
function callMSGraph(endpoint, token, callback) {
const data = {
"type": "Usage",
"timeframe": "MonthToDate",
"dataset": {
"granularity": "Daily",
}
}
const headers = new Headers();
const bearer = `Bearer ${token}`;
headers.append("Content-Type", "application/json");
headers.append("Authorization", bearer);
const options = {
body: JSON.stringify(data),
method: "POST",
headers: headers
};
console.log('request made to Graph API at: ' + new Date().toString());
fetch(endpoint, options)
.then(response => response.json())
.then(response => callback(response, endpoint))
.catch(error => console.log(error))
}
function showAccesstoken(data){
document.getElementById("accesstoken").innerHTML = JSON.stringify(data, null, 2);
}
function showResult(data){
document.getElementById("json").innerHTML = JSON.stringify(data, null, 2);
}
</script>
</body>
</html>
=========更新======
例如
我想调用这个 api 来获取信息 'https://api.powerbi.com/v1.0/myorg/groups' ,所以先添加 api 权限。
下一步是获取此范围的访问令牌。
有了这个访问令牌,调用 api 就可以了。