无法访问 onedrive 内容

Unable to get access to onedrive content

我正在开发一个应用程序,我需要在其中使用 Microsoft Graph 来访问 OneDrive for Business 上的文件。我在 Azure 上创建了一个 Web 应用程序,我设法获得了身份验证令牌,并且能够使用 https://graph.microsoft.com/v1.0/me 检索用户信息。但是,如果我尝试使用 https://graph.microsoft.com/v1.0/me/drive/root/children 获取 OneDrive 的内容,我会收到拒绝访问错误。

我已经在 Graph Explorer 上进行了检查,我能够毫无问题地获得查询结果。对于我的 Web 应用程序,我使用以下 Graph 权限:

public async Task<string> GetTokenAsync()
{
    HttpResponseMessage resp;
    using(var httpClient = new HttpClient())
    {
        httpClient.DefaultRequestHeaders.Accept
            .Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));

        var req = new HttpRequestMessage(HttpMethod.Post,
            $"https://login.microsoftonline.com/{tenant}/oauth2/token/");

        req.Content = new FormUrlEncodedContent(new Dictionary<string, string>
        { { "grant_type", "password" },
            { "client_id", clientId },
            { "client_secret", clientSecret },
            { "resource", "https://graph.microsoft.com" },
            { "username", username },
            { "password", password },
            { "scope", "https%3A%2F%2Fgraph.microsoft.com%2F.default" }
        });

        resp = await httpClient.SendAsync(req);
        string content = await resp.Content.ReadAsStringAsync();
        var jsonObj = new JavaScriptSerializer().Deserialize<dynamic>(content);
        string token = jsonObj["access_token"];
        Console.WriteLine(token);
        return token;
    }
}

public async Task<string> SendGraphRequest(string requestUrl)
{
    using(HttpClient httpClient = new HttpClient())
    {
        // Set up the HTTP GET request
        HttpRequestMessage apiRequest =
            new HttpRequestMessage(HttpMethod.Get, requestUrl);
        apiRequest.Headers.UserAgent
            .Add(new ProductInfoHeaderValue("OAuthStarter", "2.0"));
        apiRequest.Headers.Authorization =
            new AuthenticationHeaderValue("Bearer", await GetTokenAsync());

        // Send the request and return the response
        HttpResponseMessage response = await httpClient.SendAsync(apiRequest);
        var s = response.Content.ReadAsStringAsync();
        Console.WriteLine(s.Result);
        return s.Result;
    }
}

我对图表 api 的要求是:

SendGraphRequest("https://graph.microsoft.com/v1.0/me/drive").Wait();

我得到的结果是:

{
  "error": {
    "code": "accessDenied",
    "message": "There has been an error authenticating the request.",
    "innerError": {
      "request-id": "request-id",
      "date": "2019-09-24T11:03:29"
    }
  }
}

您在这里过度配置了范围。例如,您不需要 both Read 和 ReadWrite 范围。您还请求了一些应用程序范围,但使用的 OAuth 密码授权仅适用于委托范围(您不能将两者混合)。

我建议将您的范围与以下委派权限配对:

openid User.ReadWrite User.ReadBasic.All Files.ReadWrite.All
People.Read Sites.ReadWrite.All Tasks.ReadWrite offline_access

请注意 Sites.ReadWrite.AllFiles.ReadWrite.All 略有不同。一个涉及 SharePoint,另一个涉及 OneDrive。

在尝试解决此问题将近两周后,我意识到问题不在于代码,而在于 azure 配置。我假设如果一个网络应用程序安装在活动目录管理员的帐户上,那么该活动目录上的所有用户都能够使用相同的网络应用程序访问他们各自的 One Drive 帐户。不幸的是,情况并非如此,如果用户(不是管理员)试图使用网络应用程序访问 One Drive,他或她唯一能够访问的是他们的帐户信息,而无法访问文件。为了使用图表 api 访问文件,网络应用程序需要安装在它们各自的活动目录中。