4

I'm following the Get access without a user guide to write a Python script that will call Microsoft Graph.

This script will be scheduled from cron so it cannot get admin consent (therefore authorize using Client Credentials). I am able to successfully obtain a token using this call:

request_url = "https://login.microsoftonline.com/mytenant.onmicrosoft.com/oauth2/v2.0/token"
data = { 
   'Host' : 'login.microsoftonline.com',
   'Content-Type' : 'application/x-www-form-urlencoded',
   'client_id' : 'my-client-id-1234',
   'scope' : 'https://graph.microsoft.com/.default',
   'client_secret' : client_secret,
   'grant_type' : 'client_credentials'
}
response = requests.post(url = request_url, data = data)

I then try to get a user listing with this call, using the valid token:

request_url = "https://graph.microsoft.com/v1.0/users"
headers = { 
   'Authorization' : 'Bearer ' + token,
   'Host' : 'graph.microsoft.com'
}
response = requests.get(url = request_url, headers = headers)

The problem is that I get an Authorization_IdentityNotFound error:

<Response [401]>
{
   "error": {
      "code": "Authorization_IdentityNotFound",
      "message": "The identity of the calling application could not be established.",
      "innerError": {
         "request-id": "2257f532-abc4-4465-b19f-f33541787e76",
         "date": "2018-03-27T19:11:07"
      }
   }
}

These are the permissions I've selected:

graphPermsScreenshot

Any idea how to fix this error?

Marc LaFleur
  • 31,987
  • 4
  • 37
  • 63
Ryan
  • 313
  • 3
  • 12

2 Answers2

6

For others running into this issue, I was also getting this error until found out the documentation omits a very important caveat:

  • For client credentials, if the app belongs to a work or school (organization) context then for https://login.microsoftonline.com/common/oauth2/token replace common with a tenantId or domain name

See Authorization_IdentityNotFound on Microsoft Graph API request

mschwartz
  • 188
  • 2
  • 6
  • You are right, your answer complements the accepted answer. I had to replace common by my tenantID (which can be found on Azure) – Luis Gouveia Nov 27 '19 at 10:24
2

First things first, you can go ahead an remove all those Delegated Permission scopes. If you're using the Client Credentials Grant, you will only be using Application Permission scopes.

Second, you need to execute the Admin Consent flow before you can use Client Credentials. This is done by having a Global Admin from the tenant authenticate and accept your scope request:

https://login.microsoftonline.com/common/adminconsent?client_id=[APPLICATION ID]&redirect_uri=[REDIRECT URI]

You can read more about Admin Consent here: v2 Endpoint and Admin Consent

Marc LaFleur
  • 31,987
  • 4
  • 37
  • 63
  • Thank you. This was the piece I was missing. I pasted your consent URL in a brower and substituted a bogus redirect_uri. The consent process errored out because of this but it looks like I received consent. The API calls are working now! – Ryan Jun 11 '18 at 19:31
  • This was important for me, but I still needed one other thing: replace tenant=common by the real tenant you can get on Azure (overview tab). – Luis Gouveia Nov 27 '19 at 10:20
  • Still my go-to after all these years, when setting up a new daemon process and I ask myself "How do I add consent again???" :) – Ryan Dec 17 '22 at 18:59