Closed jiasli closed 11 months ago
Yes, our goal is to facilitate using auth code flow even inside a docker container. the acquire_token_interactive()
(of MSAL Python) is specifically designed to allow that, so it is already doing its part. But then it is each different deployment scenario's challenge to somehow route the incoming auth code back to MSAL. The current unfortunate situation that the docker --net=host ...
is not (yet?) supported on Windows/Mac is a feature request for docker in its own right.
MSAL Python is even implemented in a way that it would be very easy to expose that address
parameter. The question remains as how the calling app would know which IP address to be listened to. We need to investigate whether there is a way for an app running inside docker to reliably detect and choose an ip (such as 172.17.0.3) to use. Unless/until we make some breakthrough in that detection, we don't think MSAL's exposing that address
parameter would make any real difference.
Maybe a parameter like listen_to_all_addresses
? This would certainly makes MSAL easier to use in a docker container. Just a wild thought.
MSAL could expose a parameter like listen_address
, so that the MSAL caller can specify ideally one precise IP (such as 172.17.0.3), or specify a 0.0.0.0 which would mean all addresses. (The "listen_" prefix is used to differentiate from the address presented in redirect_uri: They could be confusingly different!)
And then it would in turn become MSAL's downstream app (i.e. Az CLI)'s job to expose a --listen-address
string parameter (or you could still choose to do a --listen-to-all-addresses
boolean parameter, if you insist to). Perhaps that quirky user experience would be justified by the need to "support auth code flow inside docker container when running on Windows/Mac". We may build a prototype to try it out.
Having the exact situations here.
@jiasli @rayluo
Is there a temporary workaround to make acquire_token_interactive()
work in a docker container on macOS/Windows?
I would say that even if --net=host
is supported on all platforms, an exposed listen_address
from msal would be a more fine-grained solution than using a host network.
I would say that even if
--net=host
is supported on all platforms, an exposedlisten_address
from msal would be a more fine-grained solution than using a host network.
If --net=host
is supported on all platforms, the current MSAL Python would already work out of the box, and there would be no need to expose listen_address
from msal, not until we can articulate a concrete scenario. (In other words, we tend to expose a fine-grained parameter only if it can be justified by enabling a new scenario.)
In reality, --net=host
might not be available on macOS or Windows anytime soon, so, yeah, MSAL Python is open to that listen_address
idea. Assuming MSAL exposes that parameter, @jiasli, how does Azure CLI plan to utilize it? Is the end user expected to run something like "docker run ... -p 8400:8400 ..." and then "az login --listen-address 0.0.0.0 --port 8400" when running inside a container? The user experience seems suboptimal, I doubt how many users would know it, even after we change the existing docs to point out the different docker commands.
Is there a temporary workaround to make
acquire_token_interactive()
work in a docker container on macOS/Windows?
For now, you would have to use the Device Flow in MSAL Python, or its application az login --use-device-code
.
@jiasli, how does Azure CLI plan to utilize it? Is the end user expected to run something like "docker run ... -p 8400:8400 ..." and then "az login --listen-address 0.0.0.0 --port 8400" when running inside a container?
Yes. This is the solution I can think of, and indeed, it is suboptimal...
My scenario is doing automated testing in a docker container that requires authentication for SharePoint Online, no need to az login
.
This is what I ended up doing with msal==1.16.0
, for people who have the same need:
from unittest.mock import patch
import msal.oauth2cli
def overrite_addr(original_class, new_addr):
orig_init = original_class.__init__
# Make copy of original __init__, so we can call it without recursion
def __init__(self, address, *args, **kws):
port = address[1]
orig_init(self, (new_addr, port), *args, **kws) # Call the original __init__
original_class.__init__ = __init__ # Set the class' __init__ to the new one
return original_class
with patch(target='msal.oauth2cli.authcode._AuthCodeHttpServer',
new=overrite_addr(msal.oauth2cli.authcode._AuthCodeHttpServer, '0.0.0.0')):
# This is necessary as long as:
# 1. msal hard-coded 127.0.0.1 in its source, see: https://github.com/AzureAD/microsoft-authentication-library-for-python/issues/422
# 2. We are in a docker container on a non-Linux platform (so --net=host is not supported)
result = app.acquire_token_interactive(scopes=scopes, port=REDIRECT_PORT) # the port exported by `docker run -v`
Thanks for sharing your usage, @tevino ! So, you did choose your specific port REDIRECT_PORT=xyz, and you did setup the port forwarding when you start your container "docker run ... -p xyz:xyz ...", didn't you?
Regardless, we will take a close look after holiday, and update this thread accordingly.
@rayluo That's exactly what I did, thanks for taking care of this scenario, and happy holiday! 🎉
@enerdev2022, have you tried running MSAL's interactive sample inside your Docker which was running on Linux? If so, you should have already seen this built-in hint. Please let us know if that does not work.
This is a very old thread, marking as answered and will close. Please comment if it needs to be reopened.
Goal
Support we want to support auth code flow in docker container, as opposed to https://github.com/AzureAD/microsoft-authentication-library-for-python/issues/421.
Solution 1:
--net=host
--net=host
is used to put the container directly in thehost
network. Unfortunately, as mentioned in https://github.com/AzureAD/microsoft-authentication-library-for-python/pull/309#discussion_r731469989,--net=host
doesn't work on platforms other than Linux, like Windows or MacOS:https://github.com/AzureAD/microsoft-authentication-library-for-python/blob/0deba2e88a9595986282b14ce03a57bc9dc0539c/msal/oauth2cli/authcode.py#L246
So we have to use other approaches.
Solution 2:
--publish , -p
I tried to use
--publish , -p
to expose/map certain port like8400
to the hosting Windows:However, after running
az login
, the browser fails withThis is because
AuthCodeReceiver
only listens to127.0.0.1
:https://github.com/AzureAD/microsoft-authentication-library-for-python/blob/0deba2e88a9595986282b14ce03a57bc9dc0539c/msal/oauth2cli/authcode.py#L132
As the container runs in
bridge
network (docker inspect <name>
), the IP address is actuallyIt fails because the IP doesn't match.
This can be cross-checked with
Now visiting http://127.0.0.1:8400 from the host shows the same error message.
But if we listen to all port:
http://127.0.0.1:8400 works as expected.
Experiment
After changing https://github.com/AzureAD/microsoft-authentication-library-for-python/blob/0deba2e88a9595986282b14ce03a57bc9dc0539c/msal/oauth2cli/authcode.py#L132
to
""
, I can successfully do an auth code flow in a docker container!