diff --git a/sdk/identity/azure-identity/CHANGELOG.md b/sdk/identity/azure-identity/CHANGELOG.md index 43075dd8f743..bc728cf02ee3 100644 --- a/sdk/identity/azure-identity/CHANGELOG.md +++ b/sdk/identity/azure-identity/CHANGELOG.md @@ -8,6 +8,8 @@ - `OnBehalfOfCredential` supports the on-behalf-of authentication flow for accessing resources on behalf of users ([#19308](https://github.com/Azure/azure-sdk-for-python/issues/19308)) +- `DefaultAzureCredential` allows specifying the client ID of interactive browser via keyword argument `interactive_browser_client_id` + ([#20487](https://github.com/Azure/azure-sdk-for-python/issues/20487)) ### Breaking Changes diff --git a/sdk/identity/azure-identity/azure/identity/_credentials/default.py b/sdk/identity/azure-identity/azure/identity/_credentials/default.py index bc74b37ecc89..90ddc1b39b53 100644 --- a/sdk/identity/azure-identity/azure/identity/_credentials/default.py +++ b/sdk/identity/azure-identity/azure/identity/_credentials/default.py @@ -70,6 +70,8 @@ class DefaultAzureCredential(ChainedTokenCredential): AZURE_TENANT_ID, if any. If unspecified, users will authenticate in their home tenants. :keyword str managed_identity_client_id: The client ID of a user-assigned managed identity. Defaults to the value of the environment variable AZURE_CLIENT_ID, if any. If not specified, a system-assigned identity will be used. + :keyword str interactive_browser_client_id: The client ID to be used in interactive browser credential. If not + specified, users will authenticate to an Azure development application. :keyword str shared_cache_username: Preferred username for :class:`~azure.identity.SharedTokenCacheCredential`. Defaults to the value of environment variable AZURE_USERNAME, if any. :keyword str shared_cache_tenant_id: Preferred tenant for :class:`~azure.identity.SharedTokenCacheCredential`. @@ -102,6 +104,7 @@ def __init__(self, **kwargs): managed_identity_client_id = kwargs.pop( "managed_identity_client_id", os.environ.get(EnvironmentVariables.AZURE_CLIENT_ID) ) + interactive_browser_client_id = kwargs.pop("interactive_browser_client_id", None) shared_cache_username = kwargs.pop("shared_cache_username", os.environ.get(EnvironmentVariables.AZURE_USERNAME)) shared_cache_tenant_id = kwargs.pop( @@ -137,7 +140,14 @@ def __init__(self, **kwargs): if not exclude_powershell_credential: credentials.append(AzurePowerShellCredential(**kwargs)) if not exclude_interactive_browser_credential: - credentials.append(InteractiveBrowserCredential(tenant_id=interactive_browser_tenant_id, **kwargs)) + if interactive_browser_client_id: + credentials.append( + InteractiveBrowserCredential( + tenant_id=interactive_browser_tenant_id, client_id=interactive_browser_client_id, **kwargs + ) + ) + else: + credentials.append(InteractiveBrowserCredential(tenant_id=interactive_browser_tenant_id, **kwargs)) super(DefaultAzureCredential, self).__init__(*credentials) diff --git a/sdk/identity/azure-identity/tests/test_default.py b/sdk/identity/azure-identity/tests/test_default.py index a03a16cb85cc..8c8189996861 100644 --- a/sdk/identity/azure-identity/tests/test_default.py +++ b/sdk/identity/azure-identity/tests/test_default.py @@ -387,6 +387,21 @@ def validate_tenant_id(credential): validate_tenant_id(mock_credential) +def test_interactive_browser_client_id(): + """the credential should allow configuring a client ID for InteractiveBrowserCredential by kwarg""" + + client_id = "client-id" + + def validate_client_id(credential): + assert len(credential.call_args_list) == 1, "InteractiveBrowserCredential should be instantiated once" + _, kwargs = credential.call_args + assert kwargs["client_id"] == client_id + + with patch(DefaultAzureCredential.__module__ + ".InteractiveBrowserCredential") as mock_credential: + DefaultAzureCredential(exclude_interactive_browser_credential=False, interactive_browser_client_id=client_id) + validate_client_id(mock_credential) + + @pytest.mark.parametrize("expected_value", (True, False)) def test_allow_multitenant_authentication(expected_value): """the credential should pass "allow_multitenant_authentication" to the inner credentials which support it"""