使用 Microsoft Graph 的 UploadSession 出现 401 错误

Getting 401 error with UploadSession with Microsoft Graph

我正在尝试使用守护程序应用程序将大文件上传到用户的 OneDrive for Business 帐户。我已成功验证并获得不记名令牌、创建文件夹和上传小文件。

对于大文件,我创建了一个上传会话,但在尝试使用该会话添加文件部分时收到错误消息。我已经包含了我的 fiddler traces 来尝试诊断这个。我已经删除了我的敏感信息。

我请求上传会话

POST https://graph.microsoft.com/v1.0/users/{user id}/drive/items/{folder id}:/Test.csv:/createUploadSession HTTP/1.1
Authorization: Bearer {bearer token}
Content-Type: application/x-www-form-urlencoded
Host: graph.microsoft.com
Content-Length: 0

我收到了包含以下内容的回复:

"@odata.context":"https://graph.microsoft.com/v1.0/$metadata#microsoft.graph.uploadSession",
"expirationDateTime":"2016-10-05T11:39:29.5104044Z",
"nextExpectedRanges":["0-"],
"uploadUrl":"https://{my tenant name}.sharepoint.com/personal/name_domain_co_za/_api/v2.0/drive/root:/Backups/Test:/uploadSession?guid='aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'&path='~tmp12_Test.csv'&overwrite=True&rename=False"}

然后我尝试 PUT 上传 url

PUT https://{my tenant name}.sharepoint.com/personal/name_domain_co_za/_api/v2.0/drive/root:/Backups/Test:/uploadSession?guid='aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'&path='~tmp12_Test.csv'&overwrite=True&rename=False HTTP/1.1
Authorization: bearer {bearer token}
Content-Range: bytes 0-327679/16333102
Host: {my tenant name}.sharepoint.com
Content-Length: 327680
Expect: 100-continue

然后响应包含以下相关行。

HTTP/1.1 401 Unauthorized
x-ms-diagnostics: 3000006;reason="Token contains invalid signature.";category="invalid_client"

{"error_description":"Invalid issuer or signature."}

我觉得很奇怪,因为使用当前的应用程序配置,我可以成功地将一个小文件上传到相同的路径,所以除非我误解了什么,否则权限应该没有任何问题。

同样的问题:上传小文件正确执行。

要上传更大的文件,测试端点“https://graph.microsoft.com/beta”用于实现 "Upload Session"。本次请求成功。

但是当使用这个 "Upload Session" URI 时,HTTP PUT 命令失败:

x-ms-诊断:3000006;原因="Token contains invalid signature.";类别="invalid_client"

这是发送大文件的 C# 代码:

using (var client = new HttpClient())
{
    byte[] sContents = File.ReadAllBytes(@"<MYLARGEFILE>");
    long length = sContents.Length;
    client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessTokenGraphMicrosoft);
    var content = new ByteArrayContent(sContents);
    content.Headers.Add("Content-Length", length.ToString());
    var response = client.PutAsync(<UPLOADSESSIONURI>, content).Result;
}

更新:
实际问题是该请求试图使用 app-only 令牌通过图形向 OneDrive for Business 进行身份验证。不幸的是,目前不支持这种情况,虽然有些情况可能有效,但有一些情况不支持(例如这个)。虽然我们无法对时间表发表评论,但它绝对在我们的关注范围内!

原文:
通过 Graph 将片段上传到 OneDrive for Business 帐户有几个因素。

  1. 身份验证令牌不兼容。换句话说,您用来在图上调用 createUploadSession 的不记名令牌不能用于直接命中 OneDrive for Business 端点的 PUT 请求。这主要是因为令牌绑定到特定的受众 - https://graph.microsoft.com/ 的令牌不适用于 https://{my tenant name}.sharepoint.com/.

  2. 由于 #1,返回的 uploadUrl 一开始实际上不应该需要身份验证 - 我们不希望开发人员为不同的端点处理多个身份验证令牌。

似乎 #2 是您概述的再现中不太正确的地方。您能否确认您收到的 uploadUrl 值不包含 access_tokenprooftoken 查询参数?如果是这样,你能从 createUploadSession 调用的响应中得到 request-id header 吗?

我在创建上传会话后上传文件时遇到同样的错误。经过多次尝试错误后,我发现只有当文档名称包含 space 时我才会得到这个。

原因是因为在 createUploadSession 响应中返回的上传 url 已经被 URL 编码。我的 REST 客户端对它进行了双重编码,因为它假定它没有被编码。双重编码后,无法在服务器上找到上传会话,它会返回 401 和空主体。