pdobsan / oama

OAuth credential Manager
BSD 3-Clause "New" or "Revised" License
130 stars 10 forks source link

Microsoft service parameter 'redirect_uri' in oama ? #53

Closed ArthurBorsboom closed 5 months ago

ArthurBorsboom commented 5 months ago

The way I used mailctl was behind a proxy (https://sub.mydomain.com), which worked fine due to a microsoft service option redirect_uri to help with the response from Microsoft.

oama printenv does not show this option. A brave attempt to add redirect_uri in the config.yaml did not work either. :)

Manually changing the URL in the browser from http://localhost:8080 to the redirect URL results in a working result (oama received the token).

Is this option or an alternative available? If not, is there a plan to add it in the future? Or am I making a mistake somewhere?

pdobsan commented 5 months ago

The way I used mailctl was behind a proxy (https://sub.mydomain.com), which worked fine due to a microsoft service option redirect_uri to help with the response from Microsoft.

What was your mailctl services.yaml file?

Manually changing the URL in the browser from http://localhost:8080 to the redirect URL results in a working result (oama received the token).

Interesting, how did this go in more details?

Once you have the refresh_token oama should work as usual for ever. So you need this trick only once.

Is this option or an alternative available?

Not at the moment.

If not, is there a plan to add it in the future?

Maybe, there is a dev branch for it. This redirect_uri is much more complicated than it seems. Keep in mind I don't have any kind of microsoft account.

ArthurBorsboom commented 5 months ago

What was your mailctl services.yaml file?

[backup@xen1 mailctl]$ cat services.yaml 
microsoft:
  auth_endpoint: https://login.microsoftonline.com/common/oauth2/v2.0/authorize
  auth_http_method: GET
  auth_params_mode: query-string
  token_endpoint: https://login.microsoftonline.com/xxxxxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxxx/oauth2/v2.0/token
  token_http_method: POST
  token_params_mode: request-body-form
  redirect_uri: https://web1-oauth.mydomain.com
  auth_scope: https://outlook.office365.com/IMAP.AccessAsUser.All https://outlook.office365.com/SMTP.Send offline_access
  client_id: xxxxxxxxxxxxxxxxxxxxxxxxxx
  client_secret: xxxxxxxxxxxxxxxxxxxxxxxxxx

Interesting, how did this go in more details?

This option resulted in two differences, as far as I remember. First the generated URL on the command line changed.

From:

[backup@xen1 mailctl]$ oama authorize microsoft xxxxxxxxxxxxx
To grant OAuth2 access to xxxxxxxxxxxxx visit the local URL below with your browser.
http://localhost:8080/start
Authorization started ...

to:

[backup@xen1 mailctl]$ oama authorize microsoft xxxxxxxxxxxxx
To grant OAuth2 access to xxxxxxxxxxxxx visit the local URL below with your browser.
https://web1-oauth.mydomain.com/start
Authorization started ...

The example above is oama and contains some editing, but the essence is the same. Once Microsoft returns a token, MS generates a redirect URL in the browser.

from: http://localhost:8080/?token&xxxxxxxxxxxx

Which gives a HTTP 404, since this is a call on a remote server.

to: https://web1-oauth.mydomain.com/?token&xxxxxxxxxxxx

The URLs above are fake, but the return URL is somewhat similar.

For this to work I have to make sure the redirect URL is on an allow list at Microsoft, i.e. [Azure] > [App registration] > [Authentication] > [Web redirect URLs]

Screenshot_2024-05-24_16-32

In the example above, I recently had to add http://localhost:8080 as a workaround, since oama always sends this as the redirect URL. But ideally, this should not be there (mess and security).

Once you have the refresh_token oama should work as usual for ever. So you need this trick only once.

That is good to know. However, I vaguely recall in the past (the earlier versions of mailctl) used to 'lose' the (Microsoft) refresh token after a certain period. But I haven't been refreshing for quite a while, so I guess this is an issue of the past and got resolved.

Keep in mind I don't have any kind of microsoft account.

I feel your pain. :) That makes life harder and coding slower, but I can help with the testing.

Hopefully the source code of mailctl might give a clue. As if you wouldn't have thought about that. :)

pdobsan commented 5 months ago

Try release 0.13. I don't think it would work completely since oama cannot listen on https://web1-oauth.mydomain.com unless, as a necessary but not sufficient condition, it is running on this very host.

ArthurBorsboom commented 5 months ago

Hi Peter,

oama should not listen on the redirect URL. It should simply listen on the http://localhost:8080 as before. So that should be good. It is the work of the proxy to do the translation/routing from and to https://mydomain.com > somehost > http://localhost:8080.

I hope oama does do two things:

I will try the new version today or tomorrow. I just arrived in another country and I have to get my bearings. :) Thanks for the work, it is appreciated.

ArthurBorsboom commented 5 months ago

Here are the results of the first test run on my desktop, just for basic testing. Later I will test on a remote server behind a proxy.

Steps taken. I have added redirect_uri: https://web1-oauth.fake.com to the configuration file. Running ./oama authorize microsoft email@fake.com fails.

Authorization to grant OAuth2 access to email@fake.com started ... 
oama: Prelude.read: no parse

If I add an arbitrary port number the parsing works.

Authorization to grant OAuth2 access to support@aramgroup.com started ... 
Visit http://web1-oauth.fake.com:5657/start in your browser ...

It shows the modified FQDN with the (unwanted) port number (which I could set to 443), however the protocol is http, which is https in the redirect_uri.

Then it quickly stops working, since it cannot bind to the non-existing hostname.

oama: Network.Socket.getAddrInfo (called with preferred socket type/protocol: AddrInfo {addrFlags = [AI_PASSIVE], addrFamily = AF_UNSPEC, addrSocketType = Stream, addrProtocol = 0, addrAddress = 0.0.0.0:0, addrCanonName = Nothing}, host name: "web1-oauth.fake.com", service name: "5657"): does not exist (Name or service not known)

IMO, mailctl binded to localhost:8080 regardless of the redirect_uri and showed the URL $redirect_uri/start in the CLI.

Does this make any sense? :)

pdobsan commented 5 months ago

To make it clear, I did not expect it to work just wanted to see the change of behavior.

Does this make any sense? :)

Not really, your case seems to be a complicated special situation. Can you point me to any Microsoft documentation which explain why an external "redirect uri" is needed and what it is used for?

From the user's point of view it is not clear to me why a redirect_uri config parameter (including the port number) is needed at all. That should be an internal detail to the program. If one uses, for example, Thunderbird then I believe one is not asked about any redirect uri during the initial setup.

In fact, the current development version of oama gets rid of the redirect_uri config parameter. The program generates a random free port number and use localhost with this port as redirect uri internally. And that just works fine in the case I can test.

ArthurBorsboom commented 5 months ago

From the user's point of view it is not clear to me why a redirect_uri config parameter (including the port number) is needed at all.

oama works fine in a desktop scenario. However, when oama is being run on a remote server without desktop from a CLI, then it needs a redirect URI. Microsoft needs to find its way back to the remote server where the request came from. In my case the (web) servers are behind reverse proxies, doing the translation/routing work from external DNS/IP addresses to local IP addresses. The browser on my desktoip (where I enter the MS credentials) is a different machine than where oama is running.

The port number in the redirect_uri is in my case not needed. My redirect URL would be https://sub.domain.com. However, if I don't provide a port number in the redirect_uri, oama is not able to parse the configuration item. redirect_uri: https://sub.domain.com:443 would solve the issue of course, but it is a bit unusual to add the default port number for a https connection.

Can you point me to any Microsoft documentation which explain why an external "redirect uri" is needed and what it is used for?

https://learn.microsoft.com/en-us/entra/identity-platform/reply-url

The program generates a random free port number...

This would make it harder to do the reverse proxy routing. Reverse proxies use static routes by DNS/IP and port numbers often configured in a configuration file, for example https://sub.domain.com --> http://192.168.38.5:2345. If the port number is not fixed, like 8080, but random, then the reverse proxy does not know to which port to redirect.

I hope the MS documentation might be able to explain the redirect_uri a bit better than I am doing. :)

ArthurBorsboom commented 5 months ago

While fixing a mail problem on a Wordpress website unrelated to oama, I ran into the configuration / authentication screen of the Wordpress plugin named FluentSMTP.

I just share this screenshot, because in essence this is the same scenario "MS authentication on a remote machine".

mail5-fluentsmtp

pdobsan commented 5 months ago

During authorization oama's is supposed to run on the same host as the browser. That is its single use case. Any other situation, be it a complicated individual network setup or microsoft related "remote authentication" etc. is out of oama's scope.

The automatic selection of a free unprivileged port works fine for oama's use case. Services register redirect_uri without port numbers.

For your (and potentially for others') benefits I kept the ability to configure a redirect_uri with a fix port number so you can play whatever network tricks you can come up with. If that does not work out for you then try to use something else, there are plenty of alternatives.

This thread is wandering quite off topic so that is about the end of it for me. (Unless somebody wants to hire me to solve this particular problem.)

ArthurBorsboom commented 5 months ago

Fair enough. :-)

I am programmer myself (although Java). If I have moment of joy, I might give it a try.

Just to make sure, do you take pull requests?

On Wed, 29 May 2024, 19:38 Peter Dobsan, @.***> wrote:

During authorization oama's is supposed to run on the same host as the browser. That is its single use case. Any other situation, be it a complicated individual network setup or microsoft related "remote authentication" etc. is out of oama's scope.

The automatic selection of a free unprivileged port works fine for oama's use case. Services register redirect_uri without port numbers.

For your (and potentially for others') benefits I kept the ability to configure a redirect_uri with a fix port number so you can play whatever network tricks you can come up with. If that does not work out for you then try to use something else, there are plenty of alternatives.

This thread is wandering quite off topic so that is about the end of it for me. (Unless somebody wants to hire me to solve this particular problem.)

— Reply to this email directly, view it on GitHub https://github.com/pdobsan/oama/issues/53#issuecomment-2137938811, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABSVB43GGPZOBUUNDPJW4XLZEYHBTAVCNFSM6AAAAABIFLRT3WVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCMZXHEZTQOBRGE . You are receiving this because you authored the thread.Message ID: @.***>

pdobsan commented 5 months ago

oama works fine in a desktop scenario. However, when oama is being run on a remote server without desktop from a CLI, then it needs a redirect URI.

No, it doesn't really need a redirect_uri on the remote host. See Running oama remotely.