Microsoft Graph API - 更新密码 - 权限不足,无法完成操作

The*_*Guy 5 microsoft-graph-api

我正在尝试通过 Microsoft Graph API 更新用户,我能够更新DisplayNamePasswordProfile出现错误:

Insufficient privileges to complete the operation.
Run Code Online (Sandbox Code Playgroud)

以下是我在http://jwt.io解码 JWT 令牌时与令牌关联的角色:

Insufficient privileges to complete the operation.
Run Code Online (Sandbox Code Playgroud)

根据文档,这些权限似乎就足够了。

这是我的代码(取自控制台应用程序),我能够通过 Fiddler 确定调用失败,UpdateAsync不会引发异常。

"roles": [
    "User.ReadWrite.All",
    "Directory.ReadWrite.All",
    "Group.ReadWrite.All"
],
Run Code Online (Sandbox Code Playgroud)

获取token的方法:

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);
}
Run Code Online (Sandbox Code Playgroud)

以下是 Fiddler 的完整回复:

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;
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*eur 6

密码是一个特别敏感的数据集,因此对它们有一些独特的权限。从文档

更新passwordProfile属性时,需要以下范围:Directory.AccessAsUser.All.

Directory.AccessAsUser.All是委派的权限,需要一个管理员。换句话说,它允许某个全局管理员更改其他用户的passwordProfile.

如果您希望允许最终用户自己更改密码,则ChangePasswordSDK 中还有一个内置方法:

await graphClient.Me.ChangePassword("current-pwd, "new-pwd").Request().PostAsync();
Run Code Online (Sandbox Code Playgroud)

注意:这还需要DirectoryAccessAsUser.All在用户执行之前获得管理员同意)

请记住,这DirectoryAccessAsUser.All是“委派”而不是“应用程序”权限范围。这意味着它仅受授权代码隐式流支持;它不适用于使用客户端凭据流的守护程序/服务场景。

如果您考虑可以通过能够随意更改用户密码的非交互式应用程序实现的潜在攻击,那么此限制的原因就很清楚了。


sas*_*_bg 6

我们发现的一个简单的解决方案是将应用程序主体添加到“帮助台管理员”角色。

  1. 转到Azure 活动目录
  2. 在左侧单击“角色和管理员”
  3. 搜索帮助台管理员角色并单击它

在此输入图像描述

  1. 单击“添加分配”并粘贴您的应用程序对象 ID
  2. 等待 5 分钟左右,让 azure 考虑更改

在此输入图像描述

  • “密码管理员”也可能是一个不错的角色选择,因为它提供的权限比“帮助台管理员”少。文档[此处](https://learn.microsoft.com/en-us/azure/active-directory/roles/permissions-reference)。 (2认同)