Hello i am following a tutorial on outlook python api automation and which the original code works using authority=’https://login.microsoftonline.com/consumers/’ but our situation is my mom is the boss of the company i work for (so i also have full access on her behalf for her logins along with mine) and her account must be the main overall admin user and underneath if i understand correctly is me and the other employees correct me if i’m wrong and i believe it’s a work account, i also believe using the tenant id (actual id in replace of tenantid) like authority=’https://login.microsoftonline.com/{tenant id}/’ worked at first but then kept giving the error
PS C:UsersNicolastutorial-outlook-api-crash-course> & c:/Users/Nicolas/tutorial-outlook-api-crash-course/Scripts/python.exe "c:/Users/Nicolas/tutorial-outlook-api-crash-course/ms_graph ((3 gpt))original – Copy added main.py"
APPLICATION_ID: hidden
CLIENT_SECRET: hidden
Attempting to get access token…
Error: Failed to acquire access token: {‘error’: ‘invalid_grant’,
‘error_description’: "AADSTS65001: The user or administrator has not
consented to use the application with ID ‘hidden’ named ‘azure app for
api python’. Send an interactive authorization request for this user
and resource. Trace ID: hidden Correlation ID: hidden Timestamp:
2024-11-29 02:49:38Z", ‘error_codes’: [65001], ‘timestamp’:
‘2024-11-29 02:49:38Z’, ‘trace_id’: ‘hidden’, ‘correlation_id’:
‘hidden’, ‘suberror’: ‘consent_required’}
Here is the full code
import os
import webbrowser
import msal
from dotenv import load_dotenv
MS_GRAPH_BASE_URL = 'https://graph.microsoft.com/v1.0'
def get_access_token(application_id, client_secret, scopes):
client = msal.ConfidentialClientApplication(
client_id=application_id,
client_credential=client_secret,
authority='https://login.microsoftonline.com/(hidden-tenantID#usedhere)'
####
)
# Check if there is a refresh token stored
refresh_token = None
if os.path.exists('refresh_token.txt'):
with open('refresh_token.txt', 'r') as file:
refresh_token = file.read().strip()
if refresh_token:
# Try to acquire a new access token using the refresh token
token_response = client.acquire_token_by_refresh_token(refresh_token, scopes=scopes)
else:
# No refresh token, proceed with the authorization code flow
auth_request_url = client.get_authorization_request_url(scopes)
webbrowser.open(auth_request_url)
authorization_code = input('Enter the authorization code: ')
if not authorization_code:
raise ValueError("Authorization code is empty")
token_response = client.acquire_token_by_authorization_code(
code=authorization_code,
scopes=scopes
)
if 'access_token' in token_response:
# Store the refresh token securely
if 'refresh_token' in token_response:
with open('refresh_token.txt', 'w') as file:
file.write(token_response['refresh_token'])
return token_response['access_token']
else:
raise Exception('Failed to acquire access token: ' + str(token_response))
def main():
load_dotenv()
# Check if the environment variables are loaded correctly
APPLICATION_ID = os.getenv('APPLICATION_ID')
CLIENT_SECRET = os.getenv('CLIENT_SECRET')
print(f"APPLICATION_ID: {APPLICATION_ID}") # Debug: Check if environment variable loaded correctly
print(f"CLIENT_SECRET: {CLIENT_SECRET}") # Debug: Check if environment variable loaded correctly
SCOPES = ['User.Read', 'Mail.ReadWrite', 'Mail.Send']
# add print for scopes
try:
print("Attempting to get access token...") # Debug
access_token = get_access_token(application_id=APPLICATION_ID, client_secret=CLIENT_SECRET, scopes=SCOPES)
print(f"Access Token: {access_token}") # Debug to show if token was retrieved
headers = {
'Authorization' : 'Bearer ' + access_token
}
print(f"Headers: {headers}") # Debug to show headers
except Exception as e:
print(f'Error: {e}')
if __name__ == "__main__":
main()
other steps i took
I tried redoing the whole thing and the initial setup which is creating a python venv and azure app registration for client secret and application id variables in that venv using my moms (bosses) azure account
from my moms account from azure which could be irrelevant as im still receiving the same error and not familiar with azure were (and which required me to activate my p2 subscription pls let me know if this is necessary) were going into roles and admins> admin units and created an admin unit and also added myself as a user administrator inside that admin unit under that created admin user> roles and administrators> user administrator, i also tried adding API permissions like mail.readwrite and , male.send but msgraph not listed as available option where i looked and both of these other steps of which are only attempts at resolving and not sure are even irrelevant to my code / its error
…………………….
2
Answers
I believe i ended up having a mistyped redirect url on the azure application side of things, i also first went to developer.microsoft ms graphs graph explorer and enabled consent for permissions there, but that was one of many steps i took so i dont know exactly what before or after that was involved although those were the last things i did in that order
The error
AADSTS65001: The user or administrator has not consented to use the application
occurs because the Azure AD administrator has not granted the necessary permissions for your app to access Microsoft Graph API on behalf of a user.Solution:
Grant Admin Consent:
Use the Correct Authority URL:
For work accounts, use the following authority URL:
Replace
{tenant_id}
with your organization’s Azure AD tenant ID.like Mail.ReadWrite and Mail.Send under API permissions.
Once admin consent is granted, your app should be able to acquire an access token without this error.