Hello Stephen.
Stephen Isard wrote in
<[email protected]>:
|I have found that when my Microsoft oauth2 refresh token expires, the
|oauth2-helper.py program doesn't get me a new one. The song and dance
|with typing a code into a browser window gets a new access token, but no
|new refresh token.
|
|The reason is that in order to get a refresh token, your resource file
|has to include "offline_access" in its scope. However, when you
|authorize with Microsoft they produce a response that doesn't include
|"offline_access" in its scope, even if the resource file that you are
|starting with does. The helper program produces a template that
|includes "offline_access" and so you do get a refresh token when you
|start from scratch. But the resource file that your first authorization
|produces doesn't have "offline_access", so when its refresh token
|eventually expires, you don't get a new one.
|
|I have found several Microsoft pages that confirm this behavior, but I
|don't understand their explanation for it - I get a headache trying.
I also have some trouble understanding, so please bear with me
trying to get this right. I do not like OAuth, and am not really
in that material. And, of course, in fact the players all come
with their own cards, especially Microsoft (it seemed/s).
First, to reiterate the first paragraph
|I have found that when my Microsoft oauth2 refresh token expires, the
|oauth2-helper.py program doesn't get me a new one. The song and dance
|with typing a code into a browser window gets a new access token, but no
|new refresh token.
This is already hard. I have two Outlook accounts for testing
(plus one that is hard locked without phone, and thus unusable),
and i refresh them about once a month.
This just works, but unfortunately Microsoft does not simply allow
refreshing the access token, like Google and Yandex:
* OAuth 2.0 RFC 6749, 6. Refreshing an Access Token
! refresh_token response: HTTP Error 400: Bad Request
! Let us try --authorize instead (sleeping 3 seconds)
* OAuth 2.0 RFC 6749, 4.1.1. Authorization Request
. To create an authorization code, please visit the shown URL:
etc etc. This then requires interaction, once a day thus.
|However, there appears to be simple solution: ignore the scope in the
|response from Microsoft and keep the scope you already have. I have
|attached a patch that comments out a couple of lines in the helper
|program to achieve that. It seems to work for me. I note that you
|already describe the lines I have commented out as "optional". It looks
|as if they are in fact positively harmful.
Hmm, ok, but if i place this line in my config
scope=offline_access https://outlook.office.com/IMAP.AccessAsUser.All
https://outlook.office.com/POP.AccessAsUser.All
https://outlook.office.com/SMTP.Send
so that the initial URL contains
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?....&scope=offline_access+....
then the above still results?
I mean, yes it is true, that "offline_access" seems to be missing
in the response, and it was not in the config file, but adding it
does not change the behaviour? I still have to become
interactive? Where is the improvement?
|--- ./s-nail-oauth-helper.py 2025/05/17 19:40:51 1.1
|+++ ./s-nail-oauth-helper.py 2025/05/17 19:43:23
|@@ -342,8 +342,8 @@
| # OPTIONAL
| if resp.get('refresh_token'):
| cfg['refresh_token'] = resp.get('refresh_token')
|- if resp.get('scope'):
|- cfg['scope'] = resp.get('scope')
|+ #if resp.get('scope'):
|+ # cfg['scope'] = resp.get('scope')
|
| print('%s' % cfg['access_token'])
| return config_save(args, cfg, dt)
--End of <[email protected]>
--steffen
|
|Der Kragenbaer, The moon bear,
|der holt sich munter he cheerfully and one by one
|einen nach dem anderen runter wa.ks himself off
|(By Robert Gernhardt)