Search code examples
pythonjsonazuremicrosoft-graph-api

Couldn't connect to a shared mailbox with my python script


I'm trying to make a python script that connects itself to an office shared mailbox. I'm trying to build an access token and to connect with Graph's API but i should have missed some steps maybe on the Microsoft side.

Here's my code (a bit updated compared to yesterday):

import msal
import json
import requests
import creds as c
import logging


tenant_id = c.tenant_id
authority = f'https://login.microsoftonline.com/{c.tenant_id}'
client_id = c.client_id
client_secret = c.secret
scope = ['https://graph.microsoft.com/.default']
app = msal.ConfidentialClientApplication(client_id, authority=authority, client_credential=client_secret)
result = app.acquire_token_silent(scopes=scope, account=None)

if not result:
    logging.info("No suitable token exists in cache. Let's get a new one from AAD.")
    result = app.acquire_token_for_client(scopes=scope)

if "access_token" in result:
    graph_data = requests.get(
        #'https://graph.microsoft.com/v1.0/users',
        headers={'Authorization': 'Bearer ' + result['access_token']},
        url=f'https://graph.microsoft.com/v1.0/users/{c.user_id}/messages').json()
    print("Graph API call result: ")
    print(json.dumps(graph_data, indent=2))
else:
    print(result.get("error"))
    print(result.get("error_description"))
    print(result.get("correlation_id"))

And here's the output : Erreur: 403, {"error":{"code":"Authorization_RequestDenied","message":"Insufficient privileges to complete the operation."

I tried to do what 'AmanpreetSingh-MSFT' said here : https://learn.microsoft.com/en-us/answers/questions/197819/insufficient-privileges-to-complete-the-operation

But it doesn't do anything.

I tried before with IMAP4_SSL but doesn't works, keep having 'LOGIN failed' in the output.

I did my application on Entra, i granted the permissions, might have all the necessary IDs (client, tenant, secret, user). I enabled App and Delegated authorization on Azure. I've the latest version of py and pip.

Edit : Here's my token decoded :

aud: https://graph.microsoft.com
iss: https://sts.windows.net/8b6b7804-1008-4f7d-b866-65d2e04d0a63/
iat: 1701244213
nbf: 1701244213
exp: 1701248113
aio: E2VgYFhmyFf87vTS8D+uYt8jTvmzAgA=
app_displayname: Redmine Informatique
appid: 1cb255a3-4211-4bba-a741-8158331c26e9
appidacr: 1
idp: https://sts.windows.net/8b6b7804-1008-4f7d-b866-65d2e04d0a63/
idtyp: app
oid: 752e091f-2a92-4838-ab77-ab3b03953d73
rh: 0.AQwABHhriwgQfU-4ZmXS4E0KYwMAAAAAAAAAwAAAAAAAAACWAAA.
sub: 752e091f-2a92-4838-ab77-ab3b03953d73
tenant_region_scope: EU
tid: 8b6b7804-1008-4f7d-b866-65d2e04d0a63
uti: ZUgikoxms0a32rCuFh5OAg
ver: 1.0
wids: ['0997a1d0-0d1d-4acb-b408-d5ca73121e90']
xms_tcdt: 1426243296
xms_tdbr: EU

I have no URI configured on Azure, i don't know what am I supposed to set.

Update 2 :

I tried with my own account and the output it the same.

Graph API call result: 
{
  "error": {
    "code": "ErrorAccessDenied",
    "message": "Access is denied. Check credentials and try again."
  }
}

I think that first my app miss some permissions, and then i may build a wrong token of connect with the wrong way... Any Microsoft expert ? The doc doesn't help me that much.

Update : It now Works thanks to @sridevi I just added the wrong permissions (Delegated instead of Application permissions). I may just followed the wrong tutorial. Thank you all for your help !


Solution

  • To resolve the error, you need to grant permissions of Application type in your application while using client credentials flow.

    I registered one Azure AD application and granted Mail.Read permission of Application type as below:

    enter image description here

    If you grant permissions of Application type, you can find them in roles claim of decoded token like this:

    enter image description here

    When I ran your code in my environment now, I got the response with user's messages successfully as below:

    import msal
    import json
    import requests
    import creds as c
    import logging
    
    tenant_id = c.tenant_id
    authority = f'https://login.microsoftonline.com/{c.tenant_id}'
    client_id = c.client_id
    client_secret = c.secret
    scope = ['https://graph.microsoft.com/.default']
    app = msal.ConfidentialClientApplication(client_id, authority=authority, client_credential=client_secret)
    result = app.acquire_token_silent(scopes=scope, account=None)
    
    if not result:
        logging.info("No suitable token exists in cache. Let's get a new one from AAD.")
        result = app.acquire_token_for_client(scopes=scope)
    
    if "access_token" in result:
        graph_data = requests.get(
            #'https://graph.microsoft.com/v1.0/users',
            headers={'Authorization': 'Bearer ' + result['access_token']},
            url=f'https://graph.microsoft.com/v1.0/users/{c.user_id}/messages').json()
        print("Graph API call result: ")
        print(json.dumps(graph_data, indent=2))
    else:
        print(result.get("error"))
        print(result.get("error_description"))
        print(result.get("correlation_id"))
    

    Response:

    enter image description here