Graph API e-mail access stopped working after three months
Hello, I used this guide to do some e-mail read/write using Python. It worked without issues for three months (running every two minutes), then after indeed three months on the day my refresh token stopped functioning.
def connect() -> dict[str, str]:
url = “https://login.microsoftonline.com/<snipped>/oauth2/v2.0/token”
payload = {
“grant_type”: “refresh_token”,
“client_id”: “<snipped>”,
“scope”: “offline_access Mail.ReadWrite”,
“code”: “<snipped>”,
“refresh_token”: “<snipped>”,
“client_secret”: “<snipped>”,
}
headers = {
“Content-Type”: “application/x-www-form-urlencoded”,
“Cookie”: “<snipped>”,
}
try:
response = requests.post(url, headers=headers, data=payload)
response.raise_for_status()
return ast.literal_eval(str(response.text))
except Exception:
return {}
Printing the exception gives me:
400 Client Error: Bad Request for url: https://login.microsoftonline.com/<snipped>/oauth2/v2.0/token
An astute reader might suspect my client secret expired, since its default duration is three months, but I gave it a longer duration than that when I created it. It is very much not expired.
I have since tried to perform the whole process from scratch. I seem to effectively get this far:
https://login.microsoftonline.com/<<Directory (tenant) ID>>/oauth2/v2.0/authorize?client_id=<<Application (client) ID>>&response_type=code&redirect_uri=https%3A%2F%2Flocalhost&response_mode=query&scope=offline_access%20Mail.ReadWrite&state=12345644
Replacing the two IDs and visiting the URL gives me a code as before. I copy the part between …code= and &state=… and perform the Postman step (from the guide) on it:
Request Type: Post
Request URL: https://login.microsoftonline.com/<tenant id>/oauth2/v2.0/token
client_id: your client id
scope: offline_access Mail.ReadWrite
code: you got in step (a)
redirect_uri: https://localhost
grant_type: authorization_code
client_secret: your secret
But that gives me this error:
{
“error”: “invalid_grant”,
“error_description”: “AADSTS70008: The provided authorization code or refresh token has expired due to inactivity. Send a new interactive authorization request for this user and resource. <snipped>”,
“error_codes”: [
70008
],
“timestamp”: “<snipped>”,
“trace_id”: “<snipped>”,
“correlation_id”: “<snipped>”,
“error_uri”: “https://login.microsoftonline.com/error?code=70008”
}
Mind you, this happens even if I corrupt the code or make it something silly like a single character, so it seems to me the problem isn’t with the code, but for the life of me I cannot figure it out. Anyone able to tell what I’m doing wrong?
Hello, I used this guide to do some e-mail read/write using Python. It worked without issues for three months (running every two minutes), then after indeed three months on the day my refresh token stopped functioning. def connect() -> dict[str, str]:
url = “https://login.microsoftonline.com/<snipped>/oauth2/v2.0/token”
payload = {
“grant_type”: “refresh_token”,
“client_id”: “<snipped>”,
“scope”: “offline_access Mail.ReadWrite”,
“code”: “<snipped>”,
“refresh_token”: “<snipped>”,
“client_secret”: “<snipped>”,
}
headers = {
“Content-Type”: “application/x-www-form-urlencoded”,
“Cookie”: “<snipped>”,
}
try:
response = requests.post(url, headers=headers, data=payload)
response.raise_for_status()
return ast.literal_eval(str(response.text))
except Exception:
return {} Printing the exception gives me:400 Client Error: Bad Request for url: https://login.microsoftonline.com/<snipped>/oauth2/v2.0/token An astute reader might suspect my client secret expired, since its default duration is three months, but I gave it a longer duration than that when I created it. It is very much not expired. I have since tried to perform the whole process from scratch. I seem to effectively get this far: https://login.microsoftonline.com/<<Directory (tenant) ID>>/oauth2/v2.0/authorize?client_id=<<Application (client) ID>>&response_type=code&redirect_uri=https%3A%2F%2Flocalhost&response_mode=query&scope=offline_access%20Mail.ReadWrite&state=12345644 Replacing the two IDs and visiting the URL gives me a code as before. I copy the part between …code= and &state=… and perform the Postman step (from the guide) on it: Request Type: PostRequest URL: https://login.microsoftonline.com/<tenant id>/oauth2/v2.0/tokenclient_id: your client idscope: offline_access Mail.ReadWritecode: you got in step (a)redirect_uri: https://localhostgrant_type: authorization_codeclient_secret: your secret But that gives me this error: {
“error”: “invalid_grant”,
“error_description”: “AADSTS70008: The provided authorization code or refresh token has expired due to inactivity. Send a new interactive authorization request for this user and resource. <snipped>”,
“error_codes”: [
70008
],
“timestamp”: “<snipped>”,
“trace_id”: “<snipped>”,
“correlation_id”: “<snipped>”,
“error_uri”: “https://login.microsoftonline.com/error?code=70008”
} Mind you, this happens even if I corrupt the code or make it something silly like a single character, so it seems to me the problem isn’t with the code, but for the life of me I cannot figure it out. Anyone able to tell what I’m doing wrong? Read More