Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions sdk/identity/azure-identity/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# Release History

## 1.4.0b4 (Unreleased)
- When constructing `DefaultAzureCredential`, you can now configure a tenant ID
for `InteractiveBrowserCredential`. When none is specified, the credential
authenticates users in their home tenants. To specify a different tenant, use
the keyword argument `interactive_browser_tenant_id`, or set the environment
variable `AZURE_TENANT_ID`.
([#11548](https://github.com/Azure/azure-sdk-for-python/issues/11548))
- The user authentication API added to `DeviceCodeCredential` and
`InteractiveBrowserCredential` in 1.4.0b3 is available on
`UsernamePasswordCredential` as well.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ class DefaultAzureCredential(ChainedTokenCredential):
**False**.
:keyword bool exclude_interactive_browser_credential: Whether to exclude interactive browser authentication (see
:class:`~azure.identity.InteractiveBrowserCredential`). Defaults to **True**.
:keyword str interactive_browser_tenant_id: Tenant ID to use when authenticating a user through
:class:`~azure.identity.InteractiveBrowserCredential`. Defaults to the value of environment variable
AZURE_TENANT_ID, if any. If unspecified, users will authenticate in their home tenants.
: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`.
Expand All @@ -69,6 +72,10 @@ def __init__(self, **kwargs):
authority = kwargs.pop("authority", None)
authority = normalize_authority(authority) if authority else get_default_authority()

interactive_browser_tenant_id = kwargs.pop(
"interactive_browser_tenant_id", os.environ.get(EnvironmentVariables.AZURE_TENANT_ID)
)

shared_cache_username = kwargs.pop("shared_cache_username", os.environ.get(EnvironmentVariables.AZURE_USERNAME))
shared_cache_tenant_id = kwargs.pop(
"shared_cache_tenant_id", os.environ.get(EnvironmentVariables.AZURE_TENANT_ID)
Expand Down Expand Up @@ -101,7 +108,7 @@ def __init__(self, **kwargs):
if not exclude_cli_credential:
credentials.append(AzureCliCredential())
if not exclude_interactive_browser_credential:
credentials.append(InteractiveBrowserCredential())
credentials.append(InteractiveBrowserCredential(tenant_id=interactive_browser_tenant_id))

super(DefaultAzureCredential, self).__init__(*credentials)

Expand Down
27 changes: 27 additions & 0 deletions sdk/identity/azure-identity/tests/test_default.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,3 +255,30 @@ def get_credential_for_shared_cache_test(expected_refresh_token, expected_access
# this credential uses a mock shared cache, so it works on all platforms
with patch.object(SharedTokenCacheCredential, "supported"):
return DefaultAzureCredential(_cache=cache, transport=transport, **options)


def test_interactive_browser_tenant_id():
"""the credential should allow configuring a tenant ID for InteractiveBrowserCredential by kwarg or environment"""

tenant_id = "tenant-id"

def validate_tenant_id(credential):
assert len(credential.call_args_list) == 1, "InteractiveBrowserCredential should be instantiated once"
_, kwargs = credential.call_args
assert kwargs == {'tenant_id': tenant_id}

with patch(DefaultAzureCredential.__module__ + ".InteractiveBrowserCredential") as mock_credential:
DefaultAzureCredential(exclude_interactive_browser_credential=False, interactive_browser_tenant_id=tenant_id)
validate_tenant_id(mock_credential)

# tenant id can also be specified in $AZURE_TENANT_ID
with patch.dict(os.environ, {EnvironmentVariables.AZURE_TENANT_ID: tenant_id}, clear=True):
with patch(DefaultAzureCredential.__module__ + ".InteractiveBrowserCredential") as mock_credential:
DefaultAzureCredential(exclude_interactive_browser_credential=False)
validate_tenant_id(mock_credential)

# keyword argument should override environment variable
with patch.dict(os.environ, {EnvironmentVariables.AZURE_TENANT_ID: "not-" + tenant_id}, clear=True):
with patch(DefaultAzureCredential.__module__ + ".InteractiveBrowserCredential") as mock_credential:
DefaultAzureCredential(exclude_interactive_browser_credential=False, interactive_browser_tenant_id=tenant_id)
validate_tenant_id(mock_credential)