Python connect to SharePoint via Graph API with Delegated Permissions

Below is the sample Python code to authenticate against Microsoft 365 as current user with MSA library and to call Microsoft Graph API – specifically get SharePoint Site, get Site lists with requests library.

But first, you have to have an App Registration in Azure (Entra ID) with delegated permissions consented and authentication configured.

Delegated Permissions

If your solution needs access to all SharePoint sites – consider Sites.FullControl.All or Sites.Manage.All or Sites.ReadWrite.All or Sites.Read.All depending on access level you need. Effective permissions would be a min from both – permissions configured for app registration and permissions current user have. Once consented at the app registration – these permissions will work right away.

If your solution needs access to one (or a few) SharePoint sites – consider Sites.Selected API permissions as it will scope down access to only sites that are required for your solution to work. Remember, Sites.Selected API permissions, even consented at the app registration, does require second step – SharePoint admin should provide (read or write or manage or fullcontrol) permissions for the app registration to a specific site or sites.

Authentication

You’d also need to configure authentication blade. How? It depends on the kind of application you are building etc. For example for native apps I do:
– add platform – “Mobile and Desktop app”
– select “https://login.microsoftonline.com/common/oauth2/nativeclient”
– select “msal096fd951-7285-4e4f-9c1f-23a393556b19://auth (MSAL only)”
– add custom Redirect URI: “http://localhost”

This config works for Python code below

Python Code

You’d need to install/import the libraries: json, configparser, msal, requests

Here is the code:

import json
import configparser
import msal
import requests

config = configparser.ConfigParser()
config.read('config.cfg')
client_id = config.get('delegated','clientId')
authority = config.get('delegated','authority')
scopes = config.get('delegated','scope').split()
siteId = config.get('delegated','siteId')
print( client_id)
print( authority)
print( scopes)
print( siteId)

global_token_cache = msal.TokenCache()
global_app = msal.PublicClientApplication(
    client_id,
    authority=authority,  # For Entra ID or External ID
    token_cache=global_token_cache,  
    )

def acquire_and_use_token():
    # The pattern to acquire a token looks like this.
    result = None
    result = global_app.acquire_token_interactive(scopes)

    if "access_token" in result:
        print("Token was obtained from:", result["token_source"])  # Since MSAL 1.25
        # print("Token acquisition result", json.dumps(result, indent=2))
        return result["access_token"]
    else:
        print("Token acquisition failed", result)  # Examine result["error_description"] etc. to diagnose error
        return None


token = acquire_and_use_token()


http_headers = {'Authorization': 'Bearer ' + token,
                'Accept': 'application/json',
                'Content-Type': 'application/json'}

graph_url = 'https://graph.microsoft.com/v1.0/sites/' + siteId + '?$select=id,webUrl,displayName'

siteResponse = requests.get(graph_url, headers=http_headers)
print(siteResponse.status_code)
site = json.loads(siteResponse.content)
# print("Site (raw) : ")
# print(site)
print("Site webUrl : ", site["webUrl"])
print("Site displayName : ", site["displayName"])

# Lists
graph_url = 'https://graph.microsoft.com/v1.0/sites/' + siteId + '/lists'
listsResponse = requests.get(graph_url, headers=http_headers)
print(listsResponse.status_code)
lists = json.loads(listsResponse.content)
# print("Site lists (raw):")
# print(lists)
print("Site lists:")
for list in lists["value"]:
    print("  Display Name:", list["displayName"])
    print("   Id:", list["id"])
    print("   Web Url:", list["webUrl"])
    print("   Created Date:", list["createdDateTime"])
    print("   Last Modified Date:", list["lastModifiedDateTime"])

Leave a Reply

Your email address will not be published. Required fields are marked *