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 !
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:
If you grant permissions of Application type, you can find them in roles
claim of decoded token like this:
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: