Azure 非管理员的Microsoft Graph API权限?
我正在尝试创建一个包含Office365租户中所有用户的下拉列表。我在Azure广告中创建了一个应用程序,并授予它所有必要的权限。我给了它所有的权限为微软图形实际上,应用程序和委托。都是 然后我编写了脚本,用Azure 非管理员的Microsoft Graph API权限?,azure,office365,azure-active-directory,adal,microsoft-graph-api,Azure,Office365,Azure Active Directory,Adal,Microsoft Graph Api,我正在尝试创建一个包含Office365租户中所有用户的下拉列表。我在Azure广告中创建了一个应用程序,并授予它所有必要的权限。我给了它所有的权限为微软图形实际上,应用程序和委托。都是 然后我编写了脚本,用https://graph.microsoft.com/v1.0/users 我让我的租户管理员进入并接受权限,然后在UI中输出用户列表。对管理员来说效果很好 我不是管理员,但当我进入该页面时,会出现以下错误: 此应用程序需要对其他应用程序具有应用程序权限 应用只能执行对应用程序权限的同意
https://graph.microsoft.com/v1.0/users
我让我的租户管理员进入并接受权限,然后在UI中输出用户列表。对管理员来说效果很好
我不是管理员,但当我进入该页面时,会出现以下错误:
此应用程序需要对其他应用程序具有应用程序权限
应用只能执行对应用程序权限的同意
由一名管理员负责。以管理员或管理员身份注销并登录
请与组织的管理员联系
我需要知道这是否适用于权限更低的用户。据我所知,API请求和应用程序是在Azure中授予应用程序的权限下运行的。因此,即使用户是只读的,请求也不是在用户下运行,而是在我设置的应用程序下运行。那么,为什么我会得到关于权限的错误呢
这是我正在使用的代码:
(function () {
"use strict";
// Some samples will use the tenant name here like "tenant.onmicrosoft.com"
// I prefer to user the subscription Id
var subscriptionId = "metenant.onmicrosoft.com";
// Copy the client ID of your AAD app here once you have registered one, configured the required permissions, and
// allowed implicit flow https://msdn.microsoft.com/en-us/office/office365/howto/get-started-with-office-365-unified-api
var clientId = "cccb1f2f-xxx-x-xxxxx-x-x-x-x-x-";
window.config = {
// subscriptionId: subscriptionId,
clientId: clientId,
postLogoutRedirectUri: window.location.origin,
endpoints: {
graphApiUri: 'https://graph.microsoft.com'
},
cacheLocation: 'localStorage' // enable this for IE, as sessionStorage does not work for localhost.
};
var authContext = new AuthenticationContext(config);
// Check For & Handle Redirect From AAD After Login
var isCallback = authContext.isCallback(window.location.hash);
authContext.handleWindowCallback();
if (isCallback && !authContext.getLoginError()) {
window.location = authContext._getItem(authContext.CONSTANTS.STORAGE.LOGIN_REQUEST);
}
// If not logged in force login
var user = authContext.getCachedUser();
// NOTE: you may want to render the page for anonymous users and render
// a login button which runs the login function upon click.
if (!user) authContext.login();
// Acquire token for Files resource.
authContext.acquireToken(config.endpoints.graphApiUri, function (error, token) {
// Handle ADAL Errors.
if (error || !token) {
console.log('ADAL error occurred: ' + error);
return;
}
// Execute GET request to Files API.
var filesUri = config.endpoints.graphApiUri + "/v1.0/users";
$.ajax({
type: "GET",
url: filesUri,
headers: {
'Authorization': 'Bearer ' + token,
}
}).done(function (response) {
console.log('Successfully fetched from Graph.');
console.log(response);
var container = $(".container")
container.empty();
$.each(response.value, function(index, item) {
container.append($('<li>').text(item.displayName + " " + item.mail + " " + item.mobilePhone))
})
}).fail(function (response) {
var err = JSON.parse(response.responseText)
console.log('Failed:', err.error.message);
});
});
})();
(函数(){
“严格使用”;
//有些示例将在此处使用租户名称,如“tenant.onmicrosoft.com”
//我更喜欢使用订阅Id
var subscriptionId=“metenant.onmicrosoft.com”;
//一旦您注册了AAD应用程序,配置了所需的权限,并且
//允许隐式流https://msdn.microsoft.com/en-us/office/office365/howto/get-started-with-office-365-unified-api
var clientId=“cccb1f2f-xxx-x-xxxxx-x-x-x-x-”;
window.config={
//subscriptionId:subscriptionId,
clientId:clientId,
postLogoutRedirectUri:window.location.origin,
端点:{
graphApiUri:'https://graph.microsoft.com'
},
cacheLocation:'localStorage'//为IE启用此功能,因为会话存储不适用于localhost。
};
var authContext=新的AuthenticationContext(配置);
//登录后检查并处理来自AAD的重定向(&D)
var isCallback=authContext.isCallback(window.location.hash);
authContext.HandleIndowCallback();
if(isCallback&!authContext.getLoginError()){
window.location=authContext.\u getItem(authContext.CONSTANTS.STORAGE.LOGIN\u请求);
}
//如果未登录,请强制登录
var user=authContext.getCachedUser();
//注意:您可能希望为匿名用户呈现页面并呈现
//单击后运行登录功能的登录按钮。
如果(!user)authContext.login();
//获取文件资源的令牌。
acquireToken(config.endpoints.graphApiUri,函数(错误,标记){
//处理ADAL错误。
如果(错误| |!标记){
log('发生ADAL错误:'+错误);
返回;
}
//执行GET请求到文件API。
var filesUri=config.endpoints.graphApiUri+“/v1.0/users”;
$.ajax({
键入:“获取”,
url:fileURI,
标题:{
“授权”:“持票人”+代币,
}
}).完成(功能(响应){
log('已成功从图形中获取');
控制台日志(响应);
变量容器=$(“.container”)
container.empty();
$.each(response.value,函数(索引,项){
container.append($(“”).text(item.displayName+“”+item.mail+“”+item.mobilePhone))
})
}).失败(功能(响应){
var err=JSON.parse(response.responseText)
console.log('Failed:',err.error.message);
});
});
})();
Microsoft Graph有两种权限/范围。一种是需要管理员的同意。另一个是不需要的
您为此应用程序配置的权限是什么?要在未经管理员同意的情况下列出用户,我们可以使用作用域User.ReadBasic.All,如下图所示:
您可以从获取有关权限/范围的更多详细信息
修改:
目前,adal.js没有提供管理员许可。如果要使用此功能,可以修改代码以添加prameter,如下所示:
AuthenticationContext.prototype.login = function (prompt) {
// Token is not present and user needs to login
var expectedState = this._guid();
this.config.state = expectedState;
this._idTokenNonce = this._guid();
this._logstatus('Expected state: ' + expectedState + ' startPage:' + window.location);
this._saveItem(this.CONSTANTS.STORAGE.LOGIN_REQUEST, window.location);
this._saveItem(this.CONSTANTS.STORAGE.LOGIN_ERROR, '');
this._saveItem(this.CONSTANTS.STORAGE.STATE_LOGIN, expectedState);
this._saveItem(this.CONSTANTS.STORAGE.NONCE_IDTOKEN, this._idTokenNonce);
this._saveItem(this.CONSTANTS.STORAGE.FAILED_RENEW, '');
this._saveItem(this.CONSTANTS.STORAGE.ERROR, '');
this._saveItem(this.CONSTANTS.STORAGE.ERROR_DESCRIPTION, '');
var urlNavigate = this._getNavigateUrl('id_token', null) + '&nonce=' + encodeURIComponent(this._idTokenNonce);
if (prompt && prompt === "admin_consent") {
urlNavigate = urlNavigate + "&prompt=admin_consent"
}
this.frameCallInProgress = false;
this._loginInProgress = true;
if (this.config.displayCall) {
// User defined way of handling the navigation
this.config.displayCall(urlNavigate);
} else {
this.promptUser(urlNavigate);
}
// callback from redirected page will receive fragment. It needs to call oauth2Callback
};
如果您使用的是Angular,我们还需要修改adal-Angular.js:
this.$get = ['$rootScope', '$window', '$q', '$location', '$timeout', function ($rootScope, $window, $q, $location, $timeout) {
...
return {
// public methods will be here that are accessible from Controller
config: _adal.config,
login: function (prompt) {
_adal.login(prompt);
},
...
}
然后我们可以提供两个按钮供用户登录。一个按钮用于用户自己登录。另一个是由管理员为组织提供许可。以下是代码重定向到Angular控件中管理员同意的登录页面:
$scope.login = function () {
adalService.login("admin_consent");
};
看起来您正在将当前登录用户的令牌传递给Graph API。您可以向租户中的服务主体授予适当的权限,然后获取服务主体令牌并将其用于图形调用。如果我正在使用应用程序的ADAL和clientID,我不应该将应用程序登录名传递给图形API而不是当前用户吗?我添加了用于执行此操作的代码,我授予了它所有的权限,因为我觉得API请求将在应用程序上下文而不是用户上下文下运行。看来我错了。通过ADAL发送的令牌反映用户权限。这就是为什么它失败的原因,因为用户需要是管理员,因为应用程序具有需要管理员的权限。当我只授予它非管理员权限时,它工作正常。此外,我注意到,每次用户登录到运行ADAL的页面时,它都会要求他们接受该应用程序。但是我想如果管理员批准了这个应用程序,它就不会这样做了。有什么想法吗?令牌的权限取决于您获得它的流量。对于客户端凭据,令牌在没有用户登录的情况下委托应用权限。在您的场景中,令牌是委托令牌,它要求用户具有足够的权限来同意应用程序。对于第二个问题,如果您希望管理员批准该组织的申请,