Search code examples
pythonsharepointsharepoint-onlinedocument-library

Office365-REST-Python-Client Access Token issue


I've found many examples of using the Office365-REST-Python-Client however, none of them are correctly obtaining the access token. I've registered an app under the Azure Portal, granted it API permissions using 'Application permissions', created a secret and used the client_secret and client_id in my settings dictionary to use in the below code.

def read_folder_and_files(context, list_title):
    """Read a folder example"""
    list_obj = context.web.lists.get_by_title(list_title)
    folder = list_obj.root_folder
    context.load(folder)
    context.execute_query()
    print("List url: {0}".format(folder.properties["ServerRelativeUrl"]))

    files = folder.files
    context.load(files)
    context.execute_query()
    for cur_file in files:
        print("File name: {0}".format(cur_file.properties["Name"]))

    folders = context.web.folders
    context.load(folders)
    context.execute_query()
    for folder in folders:
        print("Folder name: {0}".format(folder.properties["Name"]))


if __name__ == '__main__':
    ctx_auth = AuthenticationContext(url=settings['url'])
    if ctx_auth.acquire_token_for_app(client_id=settings['client_credentials']['client_id'],
                                      client_secret=settings['client_credentials']['client_secret']):
        ctx = ClientContext(settings['url'], ctx_auth)
        read_folder_and_files(ctx, "Documents")
        # read_folder_and_files_alt(ctx, "Documents")
        # upload_file_into_library(target_library, name, content)
        # download_file(ctx)
    else:
        print(ctx_auth.get_last_error())

When I run the above code I get the following error:

  File "/usr/local/lib/python3.7/site-packages/office365/runtime/auth/acs_token_provider.py", line 76, in get_authorization_header
    return 'Bearer {0}'.format(self.access_token["access_token"])
KeyError: 'access_token'

My end goal is to upload files to a Sharepoint Document Libary with metadata from a python data pipeline. Sharepoint is not hosted locally and is included in our 365 licences.

Kind Regards


Solution

  • So it looks like this error can happen when you're not getting an access token.

    I fixed this by ditching the client and secret in my Azure Portal and instead generated them in the SharePoint site under the following URL:

    URL: https://[tenant].sharepoint.com/_layouts/15/appregnew.aspx

    To find out what you should use in the space of [tenant] look at your SharePoint URL and pick out the text between 'https://' and '.sharepoint.com'. This is assuming your SharePoint is hosted by Microsoft.

    Click the generate buttons, use a relevant Title and unless you know better just enter localhost for the App Domain and Redirect URL. (My project is just a simple upload script). Take a copy of the Client ID and Secret.

    If you want your App to have full access then navigate to:

    https://[tenant]-admin.sharepoint.com/_layouts/15/appinv.aspx

    There is another link 'https://[tenant].sharepoint.com/_layouts/15/appinv.aspx' but this won't let you apply for full control permissions.

    Paste in the client id into the App id, where would be the fun in using the same field name, or linking the form together? Click lookup and use the below XML to grant full control.

      <AppPermissionRequests AllowAppOnlyPolicy="true">  
       <AppPermissionRequest Scope="http://sharepoint/content/sitecollection" Right="FullControl" />  
      </AppPermissionRequests>  
    

    Click create and on the next page click trust. You will need to be logged in as a site owner with full admin permissions to grant this control.

    I found all this info here which goes into more detail if you need it: https://www.anupams.net/app-only-policy-with-tenant-level-permissions-in-sharepoint-online/

    Bonus Info: Our Sharepoint has two 'sites' so passing the base URL of 'https://[tenant].sharepoint.com' took me to the wrong site by default and meant that the document libraries I was looking didn't exist. To fix this using Office365-REST-Python-Client in your settings dictionary make sure the URL setting has the fill path to your site like this:

    https://[tenant]-admin.sharepoint.com/sites/[site]

    Hope this helps, this info cost me far to much time!