Joseph Rhodes
Joseph Rhodes

Reputation: 107

How do I authorize a Python script to upload to SharePoint Online?

I need to use a Python script to upload files to a SharePoint Online site using a client credentials auth flow. I am a tenant administrator and have tried granting app-only access (as described here), as well as through Azure AD, in both cases giving full site permissions. In the case of Azure AD, I've tried authorizing through the MS Graph API, as well as the SharePoint API. In both cases, I can authenticate but cannot authorize for access to the SharePoint site.

I am able to generate a Bearer access token showing Sites.FullControl.All access. However, I either get Unsupported app only token (in the case of using client_id/secret from Azure AD app registration) or ID3035: The request was not valid or is malformed (in the case of in the case of using client_id/secret from app-only registration through the SharePoint admin interface).

I've also attempted to authorize via the Office365-Rest-Python-Client, which authorizes but returns a 401 when attempting to access any site resources.

I've found some evidence in the docs that obtaining a refresh token maybe required, which may require a self-signed cert, but I've gone down so many rabbit holes that I thought I'd reach out here for any potential insight.

Bottom line, I just need to run a script that uploads a file daily to a SharePoint site without any user interaction.

Upvotes: 2

Views: 16968

Answers (1)

Sridevi
Sridevi

Reputation: 22542

I tried to reproduce the same in my environment and got below results:

I registered one Azure AD application and granted API permissions as below:

enter image description here

I have one SharePoint site named sritestsite having one document library with sri folder like below:

enter image description here

I used below Python script to upload local file to SharePoint document library folder via Graph API without user interaction like this:

import os
import requests

# Azure AD app registration credentials
client_id = '376f340a-7b96-40c6-89fb-xxxxxxxxx'
client_secret = 'xxxxxxxxxxxxxxxxxxxxxxxxxx'
tenant_id = '3f5c7a77-062d-426c-8582-1xxxxxxxxxxx'

# SharePoint Online site URL and library name
site_id = '6d4d4ae7-be11-47d0-a9ad-xxxxxxxxxxx'
library_name = 'sridoclib'
drive_id = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'

# Authenticate and get an access token
auth_url = f'https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token'
data = {
    'grant_type': 'client_credentials',
    'client_id': client_id,
    'client_secret': client_secret,
    'scope': 'https://graph.microsoft.com/.default'
}
response = requests.post(auth_url, data=data)
access_token = response.json()['access_token']

# Upload a file to the SharePoint document library using the Microsoft Graph API
file_path = 'C:/Users/sridevi/Desktop/test.txt' #local file path
file_name = 'test.txt'
folder_name = 'sri'
upload_url = f'https://graph.microsoft.com/v1.0/sites/{site_id}/drives/{drive_id}/items/root:/{folder_name}/{file_name}:/content'
headers = {
    'Authorization': f'Bearer {access_token}',
    'Content-Type': 'application/octet-stream',
    'Content-Length': str(os.path.getsize(file_path))
}
with open(file_path, 'rb') as file:
    response = requests.put(upload_url, headers=headers, data=file)
    print(response.json())

Response:

enter image description here

To confirm that, I checked the same in SharePoint portal where test.txt file uploaded successfully like below:

enter image description here

You can get site_id of your site using below Graph API query:

GET https://graph.microsoft.com/v1.0/sites/root:/sites/<site_name>/

Response:

enter image description here

Using the above site_id, you can get drive_id like below:

GET https://graph.microsoft.com/v1.0/sites/6d4d4ae7-be11-47d0-a9ad-xxxxxxxxx/drives/

Response:

enter image description here

Upvotes: 15

Related Questions