我正在使用MSAL样本,并将其转换为使用MS Graph读取SharePoint,但是当涉及到读取列表项时,似乎遇到了权限问题。
为确保语法正确,我将Graph Explorer和AD帐户一起使用,并且能够读取列表项并确认URI正确。我也能够阅读并获得一系列列表。但是,只要我尝试获取列表的列表项,就不会返回任何内容。
基本代码在https://docs.microsoft.com/en-us/azure/active-directory/develop/tutorial-v2-javascript-spa
这是我从示例中转换的代码。如果更新变量并在Azure中注册,则应该可以在SPO网站上运行。
<!DOCTYPE html>
<html>
<head>
<title>Quickstart for MSAL JS</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/3.3.4/bluebird.min.js"></script>
<script src="https://secure.aadcdn.microsoftonline-p.com/lib/1.0.0/js/msal.js"></script>
</head>
<body>
<h2>Welcome to MSAL.js Quickstart</h2><br />
<h4 id="WelcomeMessage"></h4>
<button id="SignIn" onclick="signIn()">Sign In</button><br /><br />
<button id="btnAllLists" onclick="GetWithEndPoint()">Get All Lists</button><br /><br />
<button id="btnListItems" onclick="GetWithEndPoint()">Get List Items</button><br /><br />
<button id="btnListItemsAllFields" onclick="GetWithEndPoint()">Get List Items All Fields</button><br /><br />
<pre id="json"></pre>
<script>
var config = {
portalname: "yourportalname",
sitename: "yoursitename",
listid: "guidofalist"
}
var msalConfig = {
auth: {
clientId: "azureclientguid",
authority: "https://login.microsoftonline.com/yourportal.onmicrosoft.com"
},
cache: {
cacheLocation: "localStorage",
storeAuthStateInCookie: true
}
};
var graphConfig = {
graphMeEndpoint: "https://graph.microsoft.com/v1.0/me",
spShowAllListsEp: "https://graph.microsoft.com/v1.0/sites/" + config.portalname + ".sharepoint.com:/sites/" + config.sitename + ":/lists",
spShowListItemsEp: "https://graph.microsoft.com/v1.0/sites/" + config.portalname + ".sharepoint.com:/sites/" + config.sitename + ":/lists/" + config.listid + "/items",
spShowListItemsAllFieldsEp: "https://graph.microsoft.com/v1.0/sites/" + config.portalname + ".sharepoint.com:/sites/" + config.sitename + ":/lists/" + config.listid + "/items?expand=fields",
};
// this can be used for login or token request, however in more complex situations this can have diverging options
var requestObj = {
scopes: ["user.read"]
};
var myMSALObj = new Msal.UserAgentApplication(msalConfig);
// Register Callbacks for redirect flow
myMSALObj.handleRedirectCallback(authRedirectCallBack);
function callMSGraph(theUrl, accessToken, callback) {
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200)
callback(JSON.parse(this.responseText));
}
xmlHttp.open("GET", theUrl, true); // true for asynchronous
xmlHttp.setRequestHeader('Authorization', 'Bearer ' + accessToken);
xmlHttp.send();
}
function signIn() {
myMSALObj.loginPopup(requestObj).then(function (loginResponse) {
//Login Success
showWelcomeMessage();
acquireTokenPopupAndCallMSGraph();
}).catch(function (error) {
console.log(error);
});
}
function acquireTokenPopupAndCallMSGraph() {
//Always start with acquireTokenSilent to obtain a token in the signed in user from cache
myMSALObj.acquireTokenSilent(requestObj).then(function (tokenResponse) {
callMSGraph(graphConfig.graphMeEndpoint, tokenResponse.accessToken, graphAPICallback);
}).catch(function (error) {
console.log(error);
// Upon acquireTokenSilent failure (due to consent or interaction or login required ONLY)
// Call acquireTokenPopup(popup window)
if (requiresInteraction(error.errorCode)) {
myMSALObj.acquireTokenPopup(requestObj).then(function (tokenResponse) {
callMSGraph(graphConfig.graphMeEndpoint, tokenResponse.accessToken, graphAPICallback);
}).catch(function (error) {
console.log(error);
});
}
});
}
function graphAPICallback(data) {
document.getElementById("json").innerHTML = JSON.stringify(data, null, 2);
}
function showWelcomeMessage() {
var divWelcome = document.getElementById('WelcomeMessage');
divWelcome.innerHTML = 'Welcome ' + myMSALObj.getAccount().userName + "to Microsoft Graph API";
var loginbutton = document.getElementById('SignIn');
loginbutton.innerHTML = 'Sign Out';
loginbutton.setAttribute('onclick', 'signOut();');
var btn1 = document.getElementById('btnAllLists');
btn1.setAttribute('onclick', "GetWithEndPoint('" + graphConfig.spShowAllListsEp + "');");
var btn2 = document.getElementById('btnListItems');
btn2.setAttribute('onclick', "GetWithEndPoint('" + graphConfig.spShowListItemsEp + "');");
var btn3 = document.getElementById('btnListItemsAllFields');
btn3.setAttribute('onclick', "GetWithEndPoint('" + graphConfig.spShowListItemsAllFieldsEp + "');");
}
//This function can be removed if you do not need to support IE
function acquireTokenRedirectAndCallMSGraph() {
//Always start with acquireTokenSilent to obtain a token in the signed in user from cache
myMSALObj.acquireTokenSilent(requestObj).then(function (tokenResponse) {
callMSGraph(graphConfig.graphMeEndpoint, tokenResponse.accessToken, graphAPICallback);
}).catch(function (error) {
console.log(error);
// Upon acquireTokenSilent failure (due to consent or interaction or login required ONLY)
// Call acquireTokenRedirect
if (requiresInteraction(error.errorCode)) {
myMSALObj.acquireTokenRedirect(requestObj);
}
});
}
function authRedirectCallBack(error, response) {
if (error) {
console.log(error);
}
else {
if (response.tokenType === "access_token") {
callMSGraph(graphConfig.graphEndpoint, response.accessToken, graphAPICallback);
} else {
console.log("token type is:" + response.tokenType);
}
}
}
function requiresInteraction(errorCode) {
if (!errorCode || !errorCode.length) {
return false;
}
return errorCode === "consent_required" ||
errorCode === "interaction_required" ||
errorCode === "login_required";
}
function signOut() {
myMSALObj.logout();
}
// Browser check variables
var ua = window.navigator.userAgent;
var msie = ua.indexOf('MSIE ');
var msie11 = ua.indexOf('Trident/');
var msedge = ua.indexOf('Edge/');
var isIE = msie > 0 || msie11 > 0;
var isEdge = msedge > 0;
//If you support IE, our recommendation is that you sign-in using Redirect APIs
//If you as a developer are testing using Edge InPrivate mode, please add "isEdge" to the if check
// can change this to default an experience outside browser use
var loginType = isIE ? "REDIRECT" : "POPUP";
if (loginType === 'POPUP') {
if (myMSALObj.getAccount()) {// avoid duplicate code execution on page load in case of iframe and popup window.
showWelcomeMessage();
acquireTokenPopupAndCallMSGraph();
}
}
else if (loginType === 'REDIRECT') {
document.getElementById("SignIn").onclick = function () {
myMSALObj.loginRedirect(requestObj);
};
if (myMSALObj.getAccount() && !myMSALObj.isCallback(window.location.hash)) {// avoid duplicate code execution on page load in case of iframe and popup window.
showWelcomeMessage();
acquireTokenRedirectAndCallMSGraph();
}
} else {
console.error('Please set a valid login type');
}
</script>
<script>
function GetWithEndPoint(endpointString) {
myMSALObj.acquireTokenSilent(requestObj).then(function (tokenResponse) {
callMSGraph(endpointString, tokenResponse.accessToken, graphAPICallback);
}).catch(function (error) {
console.log(error);
if (requiresInteraction(error.errorCode)) {
myMSALObj.acquireTokenPopup(requestObj).then(function (tokenResponse) {
callMSGraph(endpointString, tokenResponse.accessToken, graphAPICallback);
}).catch(function (error) {
console.log(error);
});
}
});
}
</script>
</body>
</html>
单击任一返回列表项的按钮将引发此消息,我理解这是权限。
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#Collection(microsoft.graph.list)('myid')/items",
"value": []
}
我的期望是,我将从Graph Explorer获得相同的结果。但这表明我没有权限。我尝试了一些不同的列表,结果始终相同。我可以得到所有清单的清单。但是尝试从列表中获取项目失败。
我们不能在JS中使用Graph API来获取列表项吗?
答案 0 :(得分:1)
但这表明我没有权限
是的,空白结果通常表示Get Items
endpoint缺少以下权限之一(在您的情况下为已委派的权限):
Sites.Read.All
-阅读所有网站集中的项目Sites.ReadWrite.All
-编辑或删除所有网站集中的项目