AzureAD / microsoft-authentication-library-for-python

Microsoft Authentication Library (MSAL) for Python makes it easy to authenticate to Microsoft Entra ID. General docs are available here https://learn.microsoft.com/entra/msal/python/ Stable APIs are documented here https://msal-python.readthedocs.io. Questions can be asked on www.stackoverflow.com with tag "msal" + "python".
https://stackoverflow.com/questions/tagged/azure-ad-msal+python
Other
788 stars 194 forks source link

Throw exception when `acquire_token_interactive` fails to open browser #421

Closed jiasli closed 2 years ago

jiasli commented 2 years ago

Goal

Suppose we don't have interest in supporting auth code flow in a docker container, and we just want to automatically fall back to device code flow.

Symptom

Currently in MSAL-based CLI, running az login in docker will hang, as MSAL doesn't throw an exception when it fails to open a web browser.

On the other hand, in ADAL-based CLI, if CLI fails to open a web browser, it throws RuntimeError and falls back to device code flow:

https://github.com/Azure/azure-cli/blob/14cc787d0f58bc649d402b486fdecc5625eee9ac/src/azure-cli-core/azure/cli/core/_profile.py#L199-L205

                try:
                    authority_url, _ = _get_authority_url(self.cli_ctx, tenant)
                    subscriptions = subscription_finder.find_through_authorization_code_flow(
                        tenant, self._ad_resource_uri, authority_url, auth_resource=auth_resource)
                except RuntimeError:
                    use_device_code = True
                    logger.warning('Not able to launch a browser to log you in, falling back to device code...')

I understand it is possible to throw an Exception at

https://github.com/AzureAD/microsoft-authentication-library-for-python/blob/0deba2e88a9595986282b14ce03a57bc9dc0539c/msal/oauth2cli/authcode.py#L253

But I am not sure if this is a good choice and the correct usage of auth_uri_callback.

To Reproduce

docker run -it -v d:/cli/azure-cli:/root/azure-cli python:3.9 bash
cd /root
python -m venv pyenv
. pyenv/bin/activate
pip install azdev
azdev setup -c azure-cli
az login
rayluo commented 2 years ago

My brain was not sharp when you brought this up in our ad-hoc meeting yesterday (mid-night time here in Redmond). Now I can answer them better.

Goal

Suppose we don't have interest in supporting auth code flow in a docker container, and we just want to automatically fall back to device code flow.

Actually, we do have interest in supporting auth code flow as much as possible, even including some situations that were not previously considered possible. We will discuss more on those challenges in separate topics.

Therefore, MSAL's acquire_token_interactive() does not aggressively error out. That is also why you would observe the following symptom.

Currently in MSAL-based CLI, running az login in docker will hang, as MSAL doesn't throw an exception when it fails to open a web browser.

...

The "hang" is kind of intentional, to allow some potential hack to make it work, such as the docker --net=host ... situation, which we will discussed in depth in a different conversation. If MSAL would error out aggressively, you won't have a chance to make it work.

In other words, MSAL's acquire_token_interactive() considers its main job as starting a mini http server and waiting for the auth response to come back. Whether a browser can be launched in the current environment is not necessarily a prerequisite. In fact, MSAL could just print the URL for the user to manually open it in their browser. As long as the auth response can somehow reach back to MSAL, acquire_token_interactive() would work.

I understand it is possible to throw an Exception at

https://github.com/AzureAD/microsoft-authentication-library-for-python/blob/0deba2e88a9595986282b14ce03a57bc9dc0539c/msal/oauth2cli/authcode.py#L253

But I am not sure if this is a good choice and the correct usage of auth_uri_callback.

Yes, it is! The main reason auth_uri_callback exists, is designed to allow you to raise exception, therefore opt out of the auth code flow. :-)