OneDrive API Python request.post to upload file produces 401 error
<p>I am trying to use OneDrive API, ADAL and Python request.post to upload file to Sharepoint folder but am getting 401 error.</p>

<p>The ADAL authorization is working as gets correct token response and produces a viable <code>access_token</code>. </p>

<p>I can use the <code>access_token</code> to download a file from the same Sharepoint folder.</p>

<p>Although this only works when I manually copy <code>print file_url</code> url created by code into browser. However <code>urllib.urlretrieve(file_url, local_file_name)</code> only creates an file named <code>myfilename.csv</code> with contents <code>403 Forbidden</code>.</p>

<p>My authorization uses hard coded username and password, and I am saving refresh token in clear text, and always retrieving it when retrieving token response:</p>

<pre><code>import adal
import urllib
import requests

## set variables
username = 'username@mydomain.onmicrosoft.com'
password = 'mypassword'
authorization_url = 'https://login.windows.net/mydomain.onmicrosoft.com' # Authority
redirect_uri = 'https://login.microsoftonline.com/login.srf'
client_id = 'xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx' # Client id

## use ADAL to create token response
token_response = adal.acquire_token_with_username_password(
        authorization_url,
        username,
        password
    )

## create refresh token and save it to use later 
refresh_token = token_response['refreshToken']
refresh_token_file = open('refresh_token.txt', 'w')
refresh_token_file.write(refresh_token)
refresh_token_file.close()

## get saved refresh token and use it to get new token response
refresh_token = open('refresh_token.txt', 'r').read()
token_response = adal.acquire_token_with_refresh_token(authorization_url, str(refresh_token))

## get access_token from token response
access_token = token_response.get('accessToken') 
</code></pre>

<p>The token response is correct and using the access token from it the following code produces a  <code>file_url</code> url that I can manually copy and paste into browser that downloads a file successfullly. However <code>urllib.urlretrieve(file_url, local_file_name)</code> only creates an file named <code>myfilename.csv</code> with contents <code>403 Forbidden</code>:</p>

<pre><code>## download file
file_url = 'https://mydomain.sharepoint.com/Shared%20Documents/myfoldername/myfilename.csv?token_response=' + str(access_token)
local_file_name = 'myfilename.csv'
urllib.urlretrieve(file_url, local_file_name)
</code></pre>

<p>However I have not yet been able to successfully upload to this Sharepoint folder. Currently I have the following:</p>

<pre><code># upload file
site_url = 'https://mydomain.sharepoint.com/'
headers = {'Authorization':'BEARER ' + str(access_token)}
r = requests.post(site_url, files={'Shared%20Documents/myfoldername/myfilename.csv': open('myfilename.csv', 'rb')}, headers=headers)

print r.text
</code></pre>

<p>which produces response</p>

<pre><code>401 UNAUTHORIZED 
</code></pre>

<p>My Azure AD app has permissions:</p>

<pre><code>Read and write all user files 
Read and write items and lists in all site collections
(not sure both are needed to upload files)
</code></pre>

<p>Does my request.post look ok?  Pretty sure I am sending header, folder and file correctly.</p>

<p>EDIT TO ADD:</p>

<p>Given fact that both download code returns <code>403 Forbidden</code> and upload code returns <code>401 Unauthorized</code> I suspect the issue is with how <code>urllib</code> and <code>requests</code> are sending the urls. </p>

<p>EDIT TO ADD:</p>

<p>Trying to build the file url to use in GET and PUT. After I am authenticated, I can manually enter this url into browser:</p>

<pre><code>https://mydomain.sharepoint.com/_api/v1.0/files/root
</code></pre>

<p>which returns following XML:</p>

<pre><code>{"@odata.context":"https://mydomain.sharepoint.com/_api/v1.0/$metadata#files/$entity"
,"@odata.type":"#Microsoft.FileServices.Folder"
,"@odata.id":"https://mydomain.sharepoint.com/_api/v1.0/files/01QEW7725BZO3N6Y2GOV54373IPWSELRRZ"
,"@odata.editLink":"files/01QEW7725BZO3N6Y2GOV54373IPWSELRRZ"
,"createdBy":null
,"eTag":null
,"id":"01QEW7725BZO3N6Y2GOV54373IPWSELRRZ"
,"lastModifiedBy":null
,"name":"/"
,"parentReference":null
,"size":0
,"dateTimeCreated":"2013-07-31T02:35:57Z"
,"dateTimeLastModified":"2016-05-23T03:55:46Z"
,"type":"Folder"
,"webUrl":"https://mydomain.sharepoint.com/Shared%20Documents"
,"childCount":1}
</code></pre>

<p>However haven't found the correct syntax for the reference to the file. For example this isn't working:</p>

<pre><code>https://mydomain.sharepoint.com/_api/v1.0/files/root:/myfoldername/myfilename.csv:/content
</code></pre>

<p>This is returning error:</p>

<pre><code>    {"error":"invalid_client","error_description":"Invalid audience Uri 'https:\/\/m
anagement.core.windows.net\/'."}
</code></pre>

<p>I think that getting this specific reference to file is what I need to to make it work. </p>