Search code examples
pythonauthenticationoauth-2.0microsoft-graph-apipostman

How to authenticate MS graph requests?


I am using https://developer.microsoft.com/en-us/graph/graph-explorer to make requests

I am trying to convert them to Python to use for general automation.

I always copy from browser>postman>code, so I have all the cookies/tokens/etc. I need, and my python request will work until something expires. In this case, that something is a bearer token.

I can’t figure out how to get a new, valid bearer token other than re-doing above process or copying just the token and copy-pasting into my code.

While trying to find an auth request that would spit one out, I came across a collection for Postman here:

https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow

and when I replace {{tenant}} with my orgs tenant_id, I get a 200 request with a bearer token, but when I insert this bearer token into my Graph API request code I get the following error:

{"error":{"code":"BadRequest","message":"/me request is only valid with delegated authentication flow.","innerError":{"date":"2022-10-23T14:31:22","request-id":"...","client-request-id":"..."}}}

Here is a screenshot of the Postman Auth

enter image description here

Here is my Graph API call that only works with bearer tokens copied from graph-explorer

def recreate_graph_request1(bearer = None):
  '''
  I went to https://developer.microsoft.com/en-us/graph/graph-explorer
  and picked a request. Outlook>GET emails from a user
  at first response was for some generic user, but I logged in using my account and it actually worked.
  Then I used my old copy curl as bash trick to make it python

  :return:
  '''
  url = "https://graph.microsoft.com/v1.0/me/messages?$filter=(from/emailAddress/address)%20eq%20%[email protected]%27"

  payload = {}
  headers = {
    'Accept': '*/*',
    'Accept-Language': 'en-US,en;q=0.9',
    'Authorization': bearer,
    'Connection': 'keep-alive',
    'Origin': 'https://developer.microsoft.com',
    'Referer': 'https://developer.microsoft.com/',
    'SdkVersion': 'GraphExplorer/4.0, graph-js/3.0.2 (featureUsage=6)',
    'Sec-Fetch-Dest': 'empty',
    'Sec-Fetch-Mode': 'cors',
    'Sec-Fetch-Site': 'same-site',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36',
    'client-request-id': 'n0t_th3_s4m3_4s_1n_P05tm4n',
    'sec-ch-ua': '"Chromium";v="106", "Google Chrome";v="106", "Not;A=Brand";v="99"',
    'sec-ch-ua-mobile': '?0',
    'sec-ch-ua-platform': '"Windows"'
  }

  response = requests.request("GET", url, headers=headers, data=payload)

  return response

token_from_ms_auth = 'eyCOPIED_FROM_POSTMAN....'
bearer_from_ms_auth = 'Bearer '+token_from_ms_auth
print(recreate_graph_request1(bearer_from_ms_auth).text)

TBH, I was not overly optimistic that any bearer token would work, even if it was somehow associated with my tenant - but I hoped it would, and the resulting disappointment has driven me to ask the universe for help. I do not understand these meandering flows and looking at others' answers only confuses me more. I am hoping someone can help me figure out this scenario.


Solution

  • Access tokens are short lived. Refresh them after they expire to continue accessing resources.

    enter image description here

    Please refer this document: https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow#refresh-the-access-token

    Hope this helps.