Can't generate Access/Refresh token for personal Outlook account
I'm trying to replicate how Mailspring generates a Refresh/Access token from Outlook credential, and it looks like they don't use a client secret but rather a "challenge" and this allows personal Outlook accounts.
How do I put a "code challenge" in Oama to replicate this?
To clarify: what I want to do is to be able to authenticate with my personal Outlook/Hotmail account and recieve a refresh/access token from it. My config file looks like this, and I am running in circles:
services
outlook:
auth_endpoint: https://login.microsoftonline.com/common/oauth2/v2.0/authorize
auth_http_method: GET
auth_params_mode: QueryString
auth_scope: offline_access
user.read
client_id: XXX
client_secret: XXX # Are we not supposed to use this??
I was just trying to authorize my Hotmail account but it kept giving me an error about an invalid scope. I ultimately changed auth_scope to scope in config.yaml and it worked fine. Maybe that will also solve your problem.
@keithbowes Can you post your config.yaml?
How did you get the redirect_uri working correctly with Microsoft?
On Sat, Mar 22, 2025 at 11:15:50PM -0700, AlexanderTheGrey wrote:
@keithbowes Can you post your
config.yaml?
Instead, both of you, please post the output of the command
oama printenv
Here's mine:
oama printenv
### Runtime environment ###
config:
encryption:
tag: KEYRING
services:
microsoft:
access_type: null
auth_endpoint: null
auth_http_method: null
auth_params_mode: null
auth_scope: https://outlook.office.com/IMAP.AccessAsUser.All https://outlook.office.com/SMTP.Send
offline_access
client_id: 9e5f94bc-e8a4-4e73-b8be-63364c29d753
client_secret: ''
prompt: null
redirect_uri: null
tenant: common
token_endpoint: null
token_http_method: null
token_params_mode: null
config_file: /root/.config/oama/config.yaml
oama_version: '0.18'
op_sys: |
Linux pop-os 6.9.3-76060903-generic #202405300957~1718348209~22.04~7817b67 SMP PREEMPT_DYNAMIC Mon J x86_64 x86_64 x86_64 GNU/Linux
options:
optCommand:
tag: PrintEnv
optConfig: ~/.config/oama/config.yaml
optDebug: false
services:
microsoft:
access_type: null
auth_endpoint: https://login.microsoftonline.com/common/oauth2/v2.0/authorize
auth_http_method: GET
auth_params_mode: QueryString
auth_scope: https://outlook.office.com/IMAP.AccessAsUser.All https://outlook.office.com/SMTP.Send
offline_access
client_id: 9e5f94bc-e8a4-4e73-b8be-63364c29d753
client_secret: ''
prompt: null
redirect_uri: null
tenant: common
token_endpoint: https://login.microsoftonline.com/common/oauth2/v2.0/token
token_http_method: POST
token_params_mode: RequestBodyForm
state_dir: /root/.local/state/oama
######
Keep in mind that when I add the redirect_uri used in mutt_oauth2.py:
redirect_uri: https://login.microsoftonline.com/common/oauth2/nativeclient
I get this error:
Authorization to grant OAuth2 access to [email protected] started ...
oama: Uncaught exception ghc-internal:GHC.Internal.Exception.ErrorCall:
Prelude.read: no parse
oama: Uncaught exception ghc-internal:GHC.Internal.Exception.ErrorCall:
Prelude.read: no parse
On Sun, Mar 23, 2025 at 01:46:22AM -0700, AlexanderTheGrey wrote:
client_id: 9e5f94bc-e8a4-4e73-b8be-63364c29d753 client_secret: ''
Where does the client_id comes from? That is what kind of client_id
this is? Why is the client_secret empty? Your initial report indicated
that both fields contained (as they should) some value.
Why are you running oama as root? It is a user space program.
Keep in mind that when I add the
redirect_uriused inmutt_oauth2.py:redirect_uri: https://login.microsoftonline.com/common/oauth2/nativeclientI get this error:
Admittedly, the error message could have been better here.
As far as oama concerned the redirect_uri is for your browser to
tell where to redirect the service provider's reply. That is where
oama's built-in http server is listening. As such it should contain a
port number.
Anyway, redirect_uri to an external webserver does not make sense here.
The client_id is from Thunderbird. It's essentially a default value, since Microsoft does not provide a default client_id, and Thunderbird's Azure app registration does not require a client_secret.
I'm running oama as root because it's inside of a container.
I'm able to get the OAuth2 token to work on mutt_oauth2.py (with the external redirect_uri that I posted), but I was looking for a more automated solution.
@keithbowes seemed to indicate that they got oama working with an @hotmail.com email domain, so that's why I inquired about it. @relma2 was the initial reporter.
On Sun, Mar 23, 2025 at 07:00:58AM -0700, AlexanderTheGrey wrote:
The
client_idis from Thunderbird. It's essentially a default value, since Microsoft does not provide one, and does not require aclient_secret.
I'm running
oamaas root because it's inside of a container.
I see, that is not really a usage situation I have foreseen. That is somewhat similar to the "remote" usage described at https://github.com/pdobsan/oama#running-oama-remotely
I suppose running oama this way would complicate using the keyring or even gpg.
Where is the browser running during the authorization, inside or outside of the container?
I'm able to get the OAuth2 token to work on
mutt_oauth2.py(with the externalredirect_urithat I posted), but I was looking
There is no such thing that "OAuth2 token", there are access_token and
refresh_token. How did you receive them in this case? Copy/paste from
the browser when the authorization completed or the script stores them
for you.
For any case, once you have them, in particular the refresh_token you
could try to put them into a JSON document. The structure is something
like that below:
{
"access_token": "ya29...",
"email": {
"unEmailAddress": ***@***.***"
},
"exp_date": "2000-01-01 10:00 UTC",
"expires_in": 3599,
"refresh_token": "1//09V...",
"scope": "https://mail.google.com/",
"service": "google",
"token_type": "Bearer"
}
Store this JSON into a keyring entry (oama @.***) or gpg encrypted file. In theory and if you get it right then oama can work with it from that point, starting with an automatic renewal ...
This would need some fiddling and is just a half solution, of course.
@keithbowes seemed to indicate that they got
oamaworking with an @.***` email domain, so that's why I inquired about it.
I am also very curious about that.
Thanks for the clarification. I copy/pasted an initial code from the browser URL provided by mutt_oauth2.py manually, inputted that into mutt_oauth2.py on the terminal, then got the access token.
Apparently there's a way to have the browser automatically follow redirects so you don't need to manually copy/paste the browser URL code to get the access token. However, nobody seems to have figured out how to do that with personal (non-business/corporate) Microsoft emails (@hotmail.com, @outlook.com), since Microsoft removed the ability to easily register an enterprise application and obtain your own client_id and client_secret.
Upgrade oama and run the authorization with the --device option.
oama: authorizeEmail:
Unknown "Error in $: Failed reading: not a valid json value"
CallStack (from HasCallStack):
error, called at lib/OAMa/Authorization.hs:491:25 in oama-0.19.0-KcEsBcgBT2n4YdjWjbjUky:OAMa.Authorization
The README documents --device but I had to find the PR (https://github.com/pdobsan/oama/pull/75) to determine that a custom auth_endpoint for the device code flow is necessary. Once I added that it worked with the Thunderbird client ID. Maybe you want to add another field to the services struct for the device code auth endpoint so you can ship the Microsoft one with the app and users can just pass --device?
As the Readme says, with device flow the only config value one needs is the client_id. In fact, the default auth_endpoint already is https://login.microsoftonline.com/common/oauth2/v2.0/devicecode
As far as I know, the device flow works both for personal and other type of
accounts at Microsoft. oama just follows how the Thunderbird's developers deal
with Microsoft accounts.
See also the output of oama template command.
I consider this issue solved with --device option
I use something like this for outlook:
https://github.com/AdityaGarg8/git-credential-outlook/blob/main/git-credential-outlook
Apparently, on outlook you MUST have https, so I have to use self signed SSL certificates.