onedrive-api-docs: Problems uploading into uploadUrl: 401 Unauthorized

This started happening sometime between April 18-22. We can obtain the upload URL for a new file (so we create the upload session), but when uploading the first chunk, it fails with a 401 Unauthorized error. This only happens when using an ADMINISTRATOR access token. When using a single-user access token, this does not happen. So this applies to OneDrive for Business (with administrator token) and not single user.

Request (to get the upload URL):

> POST /personal/{email}/_api/v2.0/drive/root:/robots2.txt:/createUploadSession HTTP/1.1
Accept: application/json
Authorization: Bearer {access_token}
User-Agent: GuzzleHttp/6.1.1 curl/7.35.0 PHP/5.6.29-1+deb.sury.org~trusty+1
Content-Type: application/json
Host: {tenant}-my.sharepoint.com
Content-Length: 56

Response:

< HTTP/1.1 200 OK
< Cache-Control: private, max-age=0
< Transfer-Encoding: chunked
< Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8
< Expires: Mon, 10 Apr 2017 21:30:46 GMT
< Last-Modified: Tue, 25 Apr 2017 21:30:46 GMT
* Server Microsoft-IIS/8.5 is not blacklisted
< Server: Microsoft-IIS/8.5
< P3P: CP="ALL IND DSP COR ADM CONo CUR CUSo IVAo IVDo PSA PSD TAI TELo OUR SAMo CNT COM INT NAV ONL PHY PRE PUR UNI"
< X-SharePointHealthScore: 0
< X-SP-SERVERSTATE: ReadOnly=0
< ODATA-VERSION: 4.0
< SPClientServiceRequestDuration: 1100
< SPRequestDuration: 1235
< X-AspNet-Version: 4.0.30319
< SPRequestGuid: 2f93eb9d-e033-4000-e1b2-d0dc23d8504c
< request-id: 2f93eb9d-e033-4000-e1b2-d0dc23d8504c
< Strict-Transport-Security: max-age=31536000
< X-FRAME-OPTIONS: SAMEORIGIN
< X-Powered-By: ASP.NET
< MicrosoftSharePointTeamServices: 16.0.0.6413
< X-Content-Type-Options: nosniff
< X-MS-InvokeApp: 1; RequireReadOnly
< X-MSEdge-Ref: Ref A: 0CB89A006F6D4DDDB7067CD67FBDAD30 Ref B: CH1EDGE0521 Ref C: Tue Apr 25 14:30:47 2017 PST
< Date: Tue, 25 Apr 2017 21:30:47 GMT
< 

We got the uploadUrl, we now try to upload:

> PUT /personal/{email}/_api/v2.0/drive/items/01VKXHYLN6Y2GOVW7725BZO354PWSELRRZ/uploadSession?guid='guid'&path='~tmpE3_robots2.txt'&overwrite=True&rename=False&access_token={access_token}
HTTP/1.1
Accept: application/json
Authorization: Bearer {access_token}
User-Agent: GuzzleHttp/6.1.1 curl/7.35.0 PHP/5.6.29-1+deb.sury.org~trusty+1
Host: {tenant}-my.sharepoint.com
Content-Range: bytes 0-22379/22380
Content-Length: 22380

Response:

< HTTP/1.1 401 Unauthorized
< Content-Length: 0
* Server Microsoft-IIS/8.5 is not blacklisted
< Server: Microsoft-IIS/8.5
< P3P: CP="ALL IND DSP COR ADM CONo CUR CUSo IVAo IVDo PSA PSD TAI TELo OUR SAMo CNT COM INT NAV ONL PHY PRE PUR UNI"
< WWW-Authenticate: Bearer realm="96f92206-b32e-4ed0-8020-9e0984ce71c4",client_id="00000003-0000-0ff1-ce00-000000000000",trusted_issuers="00000001-0000-0000-c000-000000000000@*,https://sts.windows.net/*/,00000003-0000-0ff1-ce00-000000000000@90140122-8516-11e1-8eff-49304924019b",authorization_uri="https://login.windows.net/common/oauth2/authorize"
< SPRequestGuid: 2f93eb9d-007d-4000-e6b6-6c8efd18b843
< request-id: 2f93eb9d-007d-4000-e6b6-6c8efd18b843
< Strict-Transport-Security: max-age=31536000
< X-FRAME-OPTIONS: SAMEORIGIN
< x-ms-suspended-features: features=""
< X-Powered-By: ASP.NET
< MicrosoftSharePointTeamServices: 16.0.0.6413
< X-Content-Type-Options: nosniff
< X-MS-InvokeApp: 1; RequireReadOnly
< X-MSEdge-Ref: Ref A: 4A6D4FE3B7494A589915F680E32C91DD Ref B: CH1EDGE0521 Ref C: Tue Apr 25 14:30:48 2017 PST
< Date: Tue, 25 Apr 2017 21:30:47 GMT
* HTTP error before end of send, stop sending
< 

This is happening consistently with different admin tokens and for different tenants and admin accounts. Has anything changed that might only be affecting ODB with admin tokens?

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 2
  • Comments: 45 (17 by maintainers)

Most upvoted comments

The patch should be, for all intents and purposes, fully deployed. Can anyone that was having this issue ( @dluces @amagliul @ad2012 ) please try again and confirm we’ve resolved the issue?

I can also confirm that this has resolved the issue for us. Great work @ificator! I really appreciate the swift resolution.

@ificator Same here, it seems to be working now. We have about 10 tests for filenames with UTF-8 characters that were failing before and are passing now. Thank you!

Tried it successfully 👍 Thank you very much! Great work, fast fix 🥇

This is the received uploadUri:

https://tenant-my.sharepoint.com/personal/useruri/_api/v2.0/drive/items/01I4ZPDBMWKPH7KUEWBRDILTOZJNYMC2FN/uploadSession?guid='cf753484-891d-4f31-8d
ac-61ec7cd85773'&path='Bonit%C3%A4ts%C3%BCbersicht.xlsx'&overwrite=True&rename=False&tempauth=eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJhdWQiOiIwMDAwMDAwMy0wMDAwLTBmZjEtY2Uw
MC0wMDAwMDAwMDAwMDAvYXJ2aWNvci1teS5zaGFyZXBvaW50LmNvbUBjNThkZmYzNC1lOTlkLTQxNzQtYThhMS05ZTk2MTMwZGM3N2QiLCJpc3MiOiIwMDAwMDAwMy0wMDAwLTBmZjEtY2UwMC0wMDAwMDAwMDAwMDAiLCJuYm
YiOiIxNTAyNzI0ODE5IiwiZXhwIjoiMTUwMjgxMTIxOSIsImVuZHBvaW50dXJsIjoic2FVaS83RWh2U3YrcnhNY3VMZWFUdmhrWnd3bktnSUlDUzd2L0VJa2dGWT0iLCJlbmRwb2ludHVybExlbmd0aCI6IjIzMyIsImlzbG9v
cGJhY2siOiJUcnVlIiwiY2lkIjoiWldFellUazFObUV0TXpJMU9DMDBOV1kyTFRsall6Y3RPVGhpWkdSbFlUUTBPVGM0IiwidmVyIjoiaGFzaGVkcHJvb2Z0b2tlbiIsInNpdGVpZCI6IlpEVmpPVFE1TXpjdFpUSTNPUzAwTl
RSaExXRmhaV0l0WmpNM04yRXpZMkZqTVRWaSIsIm5hbWVpZCI6IjAjLmZ8bWVtYmVyc2hpcHxhcm5kdEBhcnZpY29yLm5ldCIsIm5paSI6Im1pY3Jvc29mdC5zaGFyZXBvaW50IiwiaXN1c2VyIjoidHJ1ZSIsImNhY2hla2V5
IjoiMGguZnxtZW1iZXJzaGlwfDEwMDM3ZmZlOGJmMTEzZThAbGl2ZS5jb20iLCJ0dCI6IjAiLCJ1c2VQZXJzaXN0ZW50Q29va2llIjpudWxsfQ.M0hYc2ZGZEovbG1vOEluQ3ZBYlRBaUhkS01KSkR3d0ZRUGMzMWVsdTlEdz0

It looks like .NETs Uri class will auto encode %uXXXX to %25uXXXX so this may be pretty hard to work around on the clients side (at least for .NET). I’m going to push a code change now and see if we can fast track deployment.

We are seeing the same issue that @dluces is describing above where filenames with non-ASCII characters will generate a 401 exception when attempting an upload.

For example, trying to upload a file with the name ä.jpg in the root of a user’s drive will produce a 401 response with error message: “This access token is not valid on this endpoint.”

Hello @ificator

I might be seeing this issue happening again since Friday at about 4pm MT. The upload URL does not contain access_token or prooftoken anymore. Instead, it now has a tempauth parameter that seems to be a valid JWT. However, the URL is about 1178 characters long with this parameter, so I’m guessing it’s pushing the URL over the limit.

I’ve tried removing this parameter and putting it in the Authorization header without luck. I’ve tried removing this parameter and using the regular access token (the one used to create the upload session) and it did not work either. I’ve tried just removing the parameter and of course that didn’t work.

Also, this doesn’t break our tests for regular filenames but only for filenames with UTF-8 characters in them, which become way longer when URL-encoding them. This can potentially push the limit for the URL.

This is how the payload of the JWT in the tempauth parameter looks:

{
  "aud": "00000003-0000-0ff1-ce00-000000000000/{tenant}-my.sharepoint.com@{some-guid}",
  "iss": "00000003-0000-0ff1-ce00-000000000000",
  "nbf": "1502209530",
  "exp": "1502295930",
  "endpointurl": "zxoxXci0hS33Z8PG2d2cS8y93I9jC1pLY9m1T98HHKY=",
  "endpointurlLength": "237",
  "isloopback": "True",
  "cid": "NzI0ZDBkOWUtMDBmOS00MDAwLWUwNzctMTI3YWM0NWFhOGUy",
  "ver": "hashedprooftoken",
  "siteid": "MmQ1NWNlN2UtZTE2My00ZWRhLWIyYWEtMjhmNTIzZTdkMWE1",
  "nameid": "0#.f|membership|test@{tenant}",
  "nii": "microsoft.sharepoint",
  "isuser": "true",
  "cachekey": "0h.f|membership|10033fff9ab21e22@live.com",
  "tt": "0",
  "usePersistentCookie": null
}

Any ideas? Workaround?

I just wanted to update you guys on a couple of things.

  1. There was a recent change in upload urls for app-only scenarios that increased their lengths so we’re rolling that back over the weekend.
  2. We’re doing work to decrease the size of the urls for app+user scenarios.

Be aware that the work done for item 2 above will change the structure of the URLs, and so if you’re utilizing the work around we discussed earlier you’ll want to make sure it’s resilient (e.g. only do it when you see both the access_token and prooftoken query string parameters)

@desmondyeung did you also include the X-PROOF_TOKEN header?

@dluces shouldn’t be related to this thread so go ahead and create a new issue and we’ll investigate

Update:

A few months ago I remember a similar issue happening. MS acknowledged it and fixed it. However, they provided a workaround: to remove the Authorization header when uploading into the upload URL. This workaround does NOT work this time, as doing that just returns 404 Not Found instead.

Great report. If it’s helpful, here another example request/response:

Create Upload Request:

POST https://devman1-my.sharepoint.com/personal/admin_devman1_onmicrosoft_com/_api/v2.0/drives/b!TRL-vrd7NUuJC6RejF5gcNs0MNAAvJ5BrstNszo2dl0D5LTbVMGXQrq0G6FOHjDx/items/01CSENZRQCRTBA5PFUGBFKOSAEEXKPZNZS:/forms.less:/createUploadSession
Authorization: Bearer <access token>


Create Upload Response:

200 OK

{"@odata.context":"https://devman1-my.sharepoint.com/personal/admin_devman1_onmicrosoft_com/_api/v2.0/$metadata#oneDrive.uploadSession","expirationDateTime":"2017-04-25T20:45:35.5730268Z","nextExpectedRanges":["0-"],"uploadUrl":"https://devman1-my.sharepoint.com/personal/admin_devman1_onmicrosoft_com/_api/v2.0/drives/b!TRL-vrd7NUuJC6RejF5gcNs0MNAAvJ5BrstNszo2dl0D5LTbVMGXQrq0G6FOHjDx/items/01CSENZRQCRTBA5PFUGBFKOSAEEXKPZNZS/uploadSession?guid='abd3b7d9-0ff5-4274-b80b-219b1fc2e289'&path='~tmp49_forms.less'&overwrite=True&rename=False&access_token=<upload access token>&prooftoken=<proof token>"}

PUT Request:

PUT https://devman1-my.sharepoint.com/personal/admin_devman1_onmicrosoft_com/_api/v2.0/drives/b!TRL-vrd7NUuJC6RejF5gcNs0MNAAvJ5BrstNszo2dl0D5LTbVMGXQrq0G6FOHjDx/items/01CSENZRQCRTBA5PFUGBFKOSAEEXKPZNZS/uploadSession?guid='abd3b7d9-0ff5-4274-b80b-219b1fc2e289'&path='~tmp49_forms.less'&overwrite=True&rename=False&access_token=<upload access token>&prooftoken=<proof token>
Content-Range: bytes 0-15835/15836
Authorization: Bearer <access token> 

<15836 byte body>

PUT Response:

401 Unauthorized
Server: Microsoft-IIS/8.5, P3P: CP="ALL IND DSP COR ADM CONo CUR CUSo IVAo IVDo PSA PSD TAI TELo OUR SAMo CNT COM INT NAV ONL PHY PRE PUR UNI"
WWW-Authenticate: Bearer realm="bae0dc89-7ffc-430a-ba94-f32f319d0fd7",client_id=00000003-0000-0ff1-ce00-000000000000,trusted_issuers="00000001-0000-0000-c000-000000000000@*,https://sts.windows.net/*/,00000003-0000-0ff1-ce00-000000000000@90140122-8516-11e1-8eff-49304924019b",authorization_uri="https://login.windows.net/common/oauth2/authorize"
SPRequestGuid: bd8feb9d-60aa-3000-edf3-db51a8ffeb31, request-id: bd8feb9d-60aa-3000-edf3-db51a8ffeb31
Strict-Transport-Security: max-age=31536000
X-FRAME-OPTIONS: SAMEORIGIN, x-ms-suspended-features: features=""
X-Powered-By: ASP.NET, MicrosoftSharePointTeamServices: 16.0.0.6413
X-Content-Type-Options: nosniff, X-MS-InvokeApp: 1; RequireReadOnly
X-MSEdge-Ref: Ref A: A1ACF91841B44824AC947F3C8421F05A Ref B: BLUEDGE0712 Ref C: Tue Apr 25 13:30:36 2017 PST
Date: Tue, 25 Apr 2017 20:30:36 GMT

<empty body>

I’m observing the same behavior using app-tokens for ODB. Started happening in the last week or so.