AzureAD/microsoft-authentication-library-for-python

[Bug] `msal==1.29.0` incompatible with `azureml-core<1.55`

hutec opened this issue · 6 comments

Describe the bug

AzureML authentication through AzureML SDK v1 fails when using msal==1.29.0 and azureml-core==1.54.0.post1.

To Reproduce

from azureml.core import Workspace, Dataset

workspace = Workspace.from_config()
dataset = Dataset.get_by_name(workspace, "Dataset", "latest")

This example works with msal==1.28.1 and fails with msal==1.29.0.

Expected behavior
Dataset should be retrieved.

What you see instead

Performing interactive authentication. Please follow the instructions on the terminal.
To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code GE3R845WZ to authenticate.
Traceback (most recent call last):
  File "minimal.py", line 3, in <module>
    workspace = Workspace.from_config()
  File "/usr/local/lib/python3.8/dist-packages/azureml/core/workspace.py", line 292, in from_config
    return Workspace.get(
  File "/usr/local/lib/python3.8/dist-packages/azureml/core/workspace.py", line 605, in get
    auth = InteractiveLoginAuthentication()
  File "/usr/local/lib/python3.8/dist-packages/azureml/core/authentication.py", line 571, in __init__
    perform_interactive_login(tenant=tenant_id, cloud_type=self._cloud_type)
  File "/usr/local/lib/python3.8/dist-packages/azureml/_base_sdk_common/common.py", line 573, in perform_interactive_login
    subscriptions = profile.login(
  File "/usr/local/lib/python3.8/dist-packages/azureml/_vendor/azure_cli_core/_profile.py", line 177, in login
    subscriptions = subscription_finder.find_using_common_tenant(username, credential)
  File "/usr/local/lib/python3.8/dist-packages/azureml/_vendor/azure_cli_core/_profile.py", line 769, in find_using_common_tenant
    specific_tenant_credential = identity.get_user_credential(username)
  File "/usr/local/lib/python3.8/dist-packages/azureml/_vendor/azure_cli_core/auth/identity.py", line 182, in get_user_credential
    return UserCredential(self.client_id, username, **self._msal_app_kwargs)
  File "/usr/local/lib/python3.8/dist-packages/azureml/_vendor/azure_cli_core/auth/msal_authentication.py", line 43, in __init__
    raise AzureMLException("User {} does not exist in MSAL token cache. Run `az login`.".format(username))
azureml._common.exceptions.AzureMLException: AzureMLException:
        Message: User ********** does not exist in MSAL token cache. Run `az login`.
        InnerException None
        ErrorResponse 
{
    "error": {
        "message": "User ********* does not exist in MSAL token cache. Run `az login`."
    }
}

The MSAL Python version you are using

The example works with msal==1.28.1 and fails with msal==1.29.0.

@hutec , I do not have a set of Azure ML environment so I have difficulty to reproduce this issue. If you happen to have a ~/.azure/msal_token_cache.json file in your environment, would you mind send it to my email (which you can find in my github profile)? That file is in json format. Feel free to alter (but not remove) your username or email before sending it.

CC Azure CLI's expert, @jiasli , do you have any suggestion on how to reproduce this?

This issue may be similar to Azure/azure-cli#29331

I think it is caused by using an old version of msal-extensions.

MSAL 1.29.0 promoted TokenCache._find() to TokenCache.search() (#693). msal-extensions made a corresponding change in 1.2.0 (AzureAD/microsoft-authentication-extensions-for-python@6fd4920).

If MSAL 1.29.0 is installed but msal-extensions is still an old version, msal-extensions will not override TokenCache.search(), thus reading from an empty token cache.

That's why the msal-extension 1.2.0 requires

https://github.com/AzureAD/microsoft-authentication-extensions-for-python/blob/1.2.0/setup.py

        'msal>=1.29,<2',  # Use TokenCache.search() from MSAL Python 1.29+

Azure CLI bumped msal and msal-extensions together in Azure/azure-cli#29236. I would suggest installing msal-extension 1.2.0 and see if it works.

Some other investigation

I downloaded the whl file of azureml-core 1.56.0 from https://pypi.org/project/azureml-core/#files and saw it vendors very old Azure CLI Core:

# azureml_core-1.56.0-py3-none-any\azureml\_vendor\azure_cli_core\__init__.py
__version__ = "2.30.0"

In Azure CLI's source code, the error User '{}' does not exist in MSAL token cache. is raised as an CLIError:

https://github.com/Azure/azure-cli/blob/azure-cli-2.62.0/src/azure-cli-core/azure/cli/core/auth/msal_authentication.py#L58

        if not accounts:
            raise CLIError("User '{}' does not exist in MSAL token cache. Run `az login`.".format(username))

But in the error's call stack, it is raised as an AzureMLException:

  File "/usr/local/lib/python3.8/dist-packages/azureml/_vendor/azure_cli_core/auth/msal_authentication.py", line 43, in __init__
    raise AzureMLException("User {} does not exist in MSAL token cache. Run `az login`.".format(username))

Apparently, the code has been customized.

@hutec , would you please share the output of pip list of your environment?

Thanks for your investigations! I'm currently on vacation without access to the Token Cache file nor the pip environment, but will provide it on Monday, when I'm back.

But I remember that the environmen has msal-extensions=1.0.0 and upgrading to 1.2.0 did indeed solve the issue, but is not compatible with azureml-core==1.54.0.post1 (that we require due to some AzureML related issues).

But I remember that the environmen has msal-extensions=1.0.0 and upgrading to 1.2.0 did indeed solve the issue, but is not compatible with azureml-core==1.54.0.post1 (that we require due to some AzureML related issues).

If an upstream library (msal) introduces breaking changes in newer versions, we can't expect existing downstream libraries (msal-extensions) that depend on it to work as expected. That's just the nature of dependency management.

I would recommend either pinning msal and msal-extensions to azureml-core==1.54.0.post1-compatible versions or reporting an issue to azureml-core and ask them to support new msal and msal-extensions.

But I remember that the environmen has msal-extensions=1.0.0 and upgrading to 1.2.0 did indeed solve the issue, but is not compatible with azureml-core==1.54.0.post1 (that we require due to some AzureML related issues).

Thanks, @hutec . That information already confirmed our hypothesis.

I agree with @jiasli 's suggestion. An old combination of msal<=1.26 and msal-extensions<=1.1 might work as a workaround, but your future-proof solution will be to ask the azureml-core to support the latest msal>=1.29 and msal-extensions>=1.2. That is all we can do here.