Skip to content

Commit

Permalink
DefaultAzureCredential can configure InteractiveBrowserCredential's t…
Browse files Browse the repository at this point in the history
…enant (Azure#11662)
  • Loading branch information
chlowell authored May 27, 2020
1 parent 3ce958f commit fa26e7c
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 1 deletion.
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)

0 comments on commit fa26e7c

Please sign in to comment.