Accessing sharepoint list with token unclear

Viewed 267

I only want to pull data from a list called dataacq within a group (or site?) called prod within the domain (or root site?) tenant.sharepoint.com (or tenant-my.sharepoint.com ?) and put it into a DataFrame.

I have an issue with the token gotten through app.acquire_token_silent.

Microsoft documentation is not comprehensible because it's too heavy and has little workable cookbooks/working examples (as can be seen by my numerous question marks). Also it seems they want to centralize all their APIs into graph.microsoft.com, yet there is no warning that tenant.sharepoint.com/sites/prod/_api/ is going to be discontinued.

I have gotten the following permissions from the azure portal for my app. Azure API permissions

I don't believe I need all of them, but I am not sure. I just want to read a list. So is only Microsoft Graph > Sites.read.All necessary? Or is it Sharepoint > Allsites.Read ? I know I both have an "app only" permission and a "signed in user" permission.

I did download the "quickstart" examples and I did read https://msal-python.readthedocs.io/en/latest/ . Although a token was successfully pulled using app.acquire_token_silent, using the returned token always throws some error whatever scope ('https://microsoft.sharepoint-df.com/.default' or 'https://graph.microsoft.com/.default') or API domain (graph.microsoft.com or tenant.sharepoint.com) I am using into a request:

{'error_description': 
     "Exception of type 'Microsoft.IdentityModel.Tokens.AudienceUriValidationFailedException' was thrown."}
{'error': {'code': 'AccessDenied',
  'message': 'Either scp or roles claim need to be present in the token.',
  'innerError': {'date': '2021-02-19T08:05:16',
   'request-id': '01efc071-18e6-4006-8780-f771419ebe3e',
   'client-request-id': '01efc071-18e6-4006-8780-f771419ebe3e'}}}

On the other hand, there is an API developer testing portal. When I am copying the token given in this portal into my python code, both scope/API domains work.

This is e.g. an example that works with copying & pasting the token from the portal, but not working with the token issued by the app.acquire_token_silent method:

r = requests.get(  # Use token to call downstream service
        fr'https://graph.microsoft.com/v1.0/sites/root:/sites/prod:/lists/{list_id}/items?expand=fields(select=Created))',
        headers={'Authorization': 'Bearer ' + result['access_token'],},)

So the issue is with this app.acquire_token_silent method or the configuration file. But the returned response seems alright:

{'token_type': 'Bearer',
 'expires_in': 3599,
 'ext_expires_in': 3599,
 'access_token': '...'}

What am I missing?

1 Answers

According to the code r = requests.get..... you provided in your description, it seems you use the microsoft graph api to implement it. If you use this api, you should use https://graph.microsoft.com/.default as scope to get the access token. And you can copy the access token to this page, decode the token and check if the permissions are included in it.

And according to the screenshot of "API permissions" tab of your registered app, please also do grant admin consent operation for the permission Sites.Read.All although it shows not required admin consent.

================================Update===============================

It seems the method acquire_token_silent() acquire the access token by client credential flow. So we should add the "Application" type permission but not "Delegated" permission in registered app.

Related