Search code examples
pythonoauth-2.0office365apioutlook-restapi

Authentication in Outlook 365 api


My use case is: make a script that will run every hour to extract information about a user's calendar.

My script runs in Python and I get a token but I am unable to get the user's events. I have registered my app in the Microsoft Application Registration Portal and given the Calendar.read application permission. An administrator gave consent by accessing the /adminconsent endpoint.

Here is my code to get the token (documentation here):

url = 'https://login.microsoftonline.com/common/oauth2/v2.0/token'
data = {
    'grant_type': 'client_credentials',
    'client_id': app_id,
    'scope': 'https://graph.microsoft.com/.default',  <--- Really not sure about this here
    'client_secret': client_secret,
}
r = requests.post(url, data=data)
token = r.json().get('access_token')

What scope am I suppose to use? The documentation only speaks of the one above.

And to read the user's calendar:

url = 'https://outlook.office.com/api/v2.0/users/{}/events'.format(user_email)
headers = {
    'Authorization': 'Bearer {}'.format(token)
}
r = requests.get(url, headers=headers)

I am not sure of the users/{user_email}/ part.

I get an access token but I get the following error when trying to read the user's calendar:

Response [401]

The access token is acquired using an authentication method that is too weak to allow access for this application. Presented auth strength was 1, required is 2.


Solution

  • I have finally found it. I was very close.

    I had to use Microsoft Graph API endpoint instead of Outlook Unified API endpoint.

    The final code looks like:

    import requests
    
    # Get a token
    url = 'https://login.microsoftonline.com/common/oauth2/v2.0/token'
    data = {
        'grant_type': 'client_credentials',
        'client_id': app_id,
        'scope': 'https://graph.microsoft.com/.default'
        'client_secret': client_secret,
    }
    r = requests.post(url, data=data)
    token = r.json().get('access_token')
    
    # ...
    
    # Use the token using microsoft graph endpoints
    url = 'https://graph.microsoft.com/v1.0/users/{}/events'.format(user_email) # can also use the user_id (e.g. 12345-abcde-...)
    headers = {
        'Authorization': 'Bearer {}'.format(token)
    }
    r = requests.get(url, headers=headers)
    

    Microsoft's documentation really needs clarification. It has too many different APIs that do very similar things.