我正在尝试通过Microsoft Graph API更新用户,我可以更新DisplayName
,但PasswordProfile
我收到错误:
Insufficient privileges to complete the operation.
以下是我在http://jwt.io解码JWT令牌时与令牌关联的角色:
"roles": [
"User.ReadWrite.All",
"Directory.ReadWrite.All",
"Group.ReadWrite.All"
],
基于the documentation,似乎这些权限就足够了。
这是我的代码(取自控制台应用程序),我能够通过Fiddler找出调用失败,UpdateAsync
不会抛出异常。
try
{
var userId = "9a5413cd-85ff-4ad1-ab2f-b443941abd8e";
var token = GetToken().Result;
System.Console.Write($"Token: {token}");
var newPassword = "TwDx5zgHxe51DZZ";
GraphServiceClient graphClient = GetAuthenticatedClient(token);
// This works -- Updating Display name
graphClient.Users[userId].Request().UpdateAsync(new User
{
DisplayName = "NewDisplayName"
});
// This does not work - Updating password
graphClient.Users[userId].Request().UpdateAsync(new User
{
PasswordProfile = new PasswordProfile
{
Password = newPassword,
ForceChangePasswordNextSignIn = true
}
});
System.Console.WriteLine("---Update Complete---");
}
catch (Exception e)
{
System.Console.WriteLine(e);
}
获取令牌的方法:
public async Task<string> GetToken()
{
// Constants
var tenant = "dev-mytenantmydomaincom";
var resource = "https://graph.microsoft.com/";
var clientID = "XXXXXXXX-87ef-494d-b921-cf8956006b0e";
var secret = "zgkzas2THJLiD5XXXXXX";
// Ceremony
var authority = $"https://login.microsoftonline.com/{tenant}";
var authContext = new AuthenticationContext(authority);
var credentials = new ClientCredential(clientID, secret);
var authResult = await authContext.AcquireTokenAsync(resource, credentials);
return authResult.AccessToken;
}
以下是Fiddler的完整回复:
HTTP/1.1 403 Forbidden
Cache-Control: private
Transfer-Encoding: chunked
Content-Type: application/json
request-id: 6edcf194-7705-4cd7-8144-767925cc9ee4
client-request-id: 6edcf194-7705-4cd7-8144-767925cc9ee4
x-ms-ags-diagnostic: {"ServerInfo":{"DataCenter":"East US","Slice":"SliceB","ScaleUnit":"001","Host":"AGSFE_IN_27","ADSiteName":"EST"}}
Duration: 69.2849
Date: Thu, 31 Aug 2017 13:15:34 GMT
{
"error": {
"code": "Authorization_RequestDenied",
"message": "Insufficient privileges to complete the operation.",
"innerError": {
"request-id": "6edcf194-7705-4cd7-8144-767925cc9ee4",
"date": "2017-08-31T13:15:34"
}
}
}
答案 0 :(得分:3)
密码是一种特别敏感的数据集,因此具有一些独特的权限。来自documentation:
更新
passwordProfile
属性时,需要以下范围:Directory.AccessAsUser.All
。
Directory.AccessAsUser.All是委派权限,需要管理员。换句话说,它允许某人全局管理员更改其他用户的passwordProfile
。
如果您希望允许最终用户自行更改密码,则SDK中的ChangePassword
方法也会出现:
await graphClient.Me.ChangePassword("current-pwd, "new-pwd").Request().PostAsync();
注意:这还要求在用户执行之前为DirectoryAccessAsUser.All
授予管理员同意权。)
请记住,DirectoryAccessAsUser.All
是“委派”而非“应用程序”权限范围。这意味着它仅受Authorization Code和Implicit流量的支持;它不适用于使用Client Credentials流的守护进程/服务方案。
如果您考虑具有能够随意更改用户密码的非交互式应用程序可能实现的潜在攻击,则此限制的原因非常明确。
答案 1 :(得分:1)
我们发现一个简单的解决方案是将应用程序主体添加到“帮助台管理员”角色。
答案 2 :(得分:1)
对于 2021 年到达此问答的任何人 - Graph 中有一个密码重置端点:
POST /users/{id | userPrincipalName}/authentication/passwordMethods/{id}/resetPassword
您必须首先检索密码验证方法的 id。
此操作所需的权限为 UserAuthenticationMethod.ReadWrite.All
,可以作为应用程序类型权限授予。
查看文档:{{3}}
更新
即使该权限可以作为应用程序类型权限授予,在应用程序上下文中调用也不会成功。 见https://docs.microsoft.com/en-us/graph/api/passwordauthenticationmethod-resetpassword