如何在用户上下文中查询 MS Graph API?

How to query MS Graph API in User Context?

我正在尝试使用 MS Graph API 更改用户密码。我正在检查像 this and 这样的早期问题,答案总是相似的:注册一个 AAD 应用程序,因为更改密码需要委托 UserAuthenticationMethod.ReadWrite.All 权限,您不能在 B2C 应用程序中设置该权限,因为 B2C 应用程序仅支持 offline_access 和授权的 openid。

所以答案总是建议创建一个 AAD 应用程序,使用这个应用程序我可以代表用户查询图表 API。问题是,如何实现这一点?如果我查看 Microsoft 的文档:Get access on behalf of a user,它说首先你需要获得授权,然后你才能继续获取你的访问令牌。 但作为授权过程的一部分,有一个用户同意屏幕。如果我代表我的用户调用我的 ASP.NET Core Web API 端点来更改我的密码,它将如何在服务器上工作?如果我在服务器上进行这些调用,客户端将无法同意,对吗?

此外,我正在使用 Microsoft.Graph 和 Microsoft.Graph.Auth Nuget 包,但不清楚如何代表用户执行这些调用。我正在尝试这样做:

var client = new GraphServiceClient(new SimpleAuthProvider(authToken));
await client.Users[myUserId]
      .ChangePassword(currentPassword, newPassword)
      .Request()
      .PostAsync();

其中 SimpleAuthProvider 只是一个虚拟的 IAuthProvider 实现。 任何想法如何使这项工作?

好的,知道了:

static void ChangePasswordOfAUser()
{
    var myAzureId = "65e328e8-5017-4966-93f0-b651d5261e2c"; // id of B2C user
    var currentPassword = "my_old_pwd";
    var newPassword = "newPassword!";
    using (var client = new HttpClient())
    {
        var passwordTokenRequest = new PasswordTokenRequest
        {
            Address = $"https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token",
            ClientId = clientId, // client ID of AAD app - not the B2C app!
            ClientSecret = clientSecret,
            UserName = $"{myAzureId}@contoso.onmicrosoft.com",
            Password = currentPassword,
            Scope = "https://graph.microsoft.com/.default" // you need to have delegate access
        };
        var response = client.RequestPasswordTokenAsync(passwordTokenRequest).Result;
        var userAccessToken = response.AccessToken;

        client.DefaultRequestHeaders.Add("Authorization", $"Bearer {userAccessToken}");
        var json = System.Text.Json.JsonSerializer.Serialize(new
        {
            currentPassword = currentPassword,
            newPassword = newPassword
        });
        var changePasswordResponse = client.PostAsync(
            $"https://graph.microsoft.com/v1.0/users/{myAzureId}/changePassword",
            new StringContent(json, Encoding.UTF8, "application/json"))
        .Result;

        changePasswordResponse.EnsureSuccessStatusCode();
    }
}