Skip to content

Commit 828a14d

Browse files
authored
[Identity] Update credential docstrings (#37207)
ClientAssertionCredential docstrings were updated to advertise the fact that `cache_persistence_options` is supported. Fixed a docstring type in DeviceCodeCredential. Signed-off-by: Paul Van Eck <[email protected]>
1 parent 2b48d42 commit 828a14d

File tree

6 files changed

+106
-5
lines changed

6 files changed

+106
-5
lines changed

sdk/identity/azure-identity/TOKEN_CACHING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ The following table indicates the state of in-memory and persistent caching in e
9292
| `AzureDeveloperCliCredential` | Not Supported | Not Supported |
9393
| `AzurePipelinesCredential` | Supported | Not Supported |
9494
| `AzurePowershellCredential` | Not Supported | Not Supported |
95-
| `ClientAssertionCredential` | Supported | Not Supported |
95+
| `ClientAssertionCredential` | Supported | Supported |
9696
| `CertificateCredential` | Supported | Supported |
9797
| `ClientSecretCredential` | Supported | Supported |
9898
| `DefaultAzureCredential` | Supported if the target credential in the credential chain supports it | Not Supported |

sdk/identity/azure-identity/azure/identity/_credentials/client_assertion.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ class ClientAssertionCredential(GetTokenMixin):
2424
:keyword str authority: Authority of a Microsoft Entra endpoint, for example
2525
"login.microsoftonline.com", the authority for Azure Public Cloud (which is the default).
2626
:class:`~azure.identity.AzureAuthorityHosts` defines authorities for other clouds.
27+
:keyword cache_persistence_options: configuration for persistent token caching. If unspecified, the credential
28+
will cache tokens in memory.
29+
:paramtype cache_persistence_options: ~azure.identity.TokenCachePersistenceOptions
2730
:keyword List[str] additionally_allowed_tenants: Specifies tenants in addition to the specified "tenant_id"
2831
for which the credential may acquire tokens. Add the wildcard value "*" to allow the credential to
2932
acquire tokens for any tenant the application can access.

sdk/identity/azure-identity/azure/identity/_credentials/device_code.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class DeviceCodeCredential(InteractiveCredential):
2323
SSH session. If a web browser is available, :class:`~azure.identity.InteractiveBrowserCredential` is more
2424
convenient because it automatically opens a browser to the login page.
2525
26-
:keyword str client_id: Client ID of the Microsoft Entra application that users will sign into. It is recommended
26+
:param str client_id: Client ID of the Microsoft Entra application that users will sign into. It is recommended
2727
that developers register their applications and assign appropriate roles. For more information,
2828
visit https://aka.ms/azsdk/identity/AppRegistrationAndRoleAssignment. If not specified, users will
2929
authenticate to an Azure development application, which is not recommended for production scenarios.

sdk/identity/azure-identity/azure/identity/aio/_credentials/client_assertion.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ class ClientAssertionCredential(AsyncContextManager, GetTokenMixin):
2424
:keyword str authority: Authority of a Microsoft Entra endpoint, for example
2525
"login.microsoftonline.com", the authority for Azure Public Cloud (which is the default).
2626
:class:`~azure.identity.AzureAuthorityHosts` defines authorities for other clouds.
27+
:keyword cache_persistence_options: configuration for persistent token caching. If unspecified, the credential
28+
will cache tokens in memory.
29+
:paramtype cache_persistence_options: ~azure.identity.TokenCachePersistenceOptions
2730
:keyword List[str] additionally_allowed_tenants: Specifies tenants in addition to the specified "tenant_id"
2831
for which the credential may acquire tokens. Add the wildcard value "*" to allow the credential to
2932
acquire tokens for any tenant the application can access.

sdk/identity/azure-identity/tests/test_client_assertion_credential.py

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@
33
# Licensed under the MIT License.
44
# ------------------------------------
55
from typing import Callable
6-
from unittest.mock import MagicMock
7-
from azure.identity import ClientAssertionCredential, WorkloadIdentityCredential
6+
from unittest.mock import MagicMock, Mock, patch
7+
8+
from azure.identity._internal.aad_client_base import JWT_BEARER_ASSERTION
9+
from azure.identity import ClientAssertionCredential, TokenCachePersistenceOptions
10+
11+
from helpers import build_aad_response, mock_response
812

913

1014
def test_init_with_kwargs():
@@ -34,3 +38,46 @@ def test_context_manager():
3438
assert transport.__enter__.called
3539
assert not transport.__exit__.called
3640
assert transport.__exit__.called
41+
42+
43+
def test_token_cache_persistence():
44+
"""The credential should use a persistent cache if cache_persistence_options are configured."""
45+
46+
access_token = "foo"
47+
tenant_id: str = "TENANT_ID"
48+
client_id: str = "CLIENT_ID"
49+
scope = "scope"
50+
assertion = "ASSERTION_TOKEN"
51+
func: Callable[[], str] = lambda: assertion
52+
53+
def send(request, **kwargs):
54+
assert request.data["client_assertion"] == assertion
55+
assert request.data["client_assertion_type"] == JWT_BEARER_ASSERTION
56+
assert request.data["client_id"] == client_id
57+
assert request.data["grant_type"] == "client_credentials"
58+
assert request.data["scope"] == scope
59+
60+
return mock_response(json_payload=build_aad_response(access_token=access_token))
61+
62+
with patch("azure.identity._internal.aad_client_base._load_persistent_cache") as load_persistent_cache:
63+
credential = ClientAssertionCredential(
64+
tenant_id=tenant_id,
65+
client_id=client_id,
66+
func=func,
67+
cache_persistence_options=TokenCachePersistenceOptions(),
68+
transport=Mock(send=send),
69+
)
70+
71+
assert load_persistent_cache.call_count == 0
72+
assert credential._client._cache is None
73+
assert credential._client._cae_cache is None
74+
75+
token = credential.get_token(scope)
76+
assert token.token == access_token
77+
assert load_persistent_cache.call_count == 1
78+
assert credential._client._cache is not None
79+
assert credential._client._cae_cache is None
80+
81+
token = credential.get_token(scope, enable_cae=True)
82+
assert load_persistent_cache.call_count == 2
83+
assert credential._client._cae_cache is not None

sdk/identity/azure-identity/tests/test_client_assertion_credential_async.py

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,15 @@
33
# Licensed under the MIT License.
44
# ------------------------------------
55
from typing import Callable
6-
from unittest.mock import MagicMock
6+
from unittest.mock import MagicMock, Mock, patch
77

88
import pytest
9+
from azure.identity._internal.aad_client_base import JWT_BEARER_ASSERTION
10+
from azure.identity import TokenCachePersistenceOptions
911
from azure.identity.aio import ClientAssertionCredential
1012

13+
from helpers import build_aad_response, mock_response
14+
1115

1216
def test_init_with_kwargs():
1317
tenant_id: str = "TENANT_ID"
@@ -38,3 +42,47 @@ async def test_context_manager():
3842
assert not transport.__aexit__.called
3943

4044
assert transport.__aexit__.called
45+
46+
47+
@pytest.mark.asyncio
48+
async def test_token_cache_persistence():
49+
"""The credential should use a persistent cache if cache_persistence_options are configured."""
50+
51+
access_token = "foo"
52+
tenant_id: str = "TENANT_ID"
53+
client_id: str = "CLIENT_ID"
54+
scope = "scope"
55+
assertion = "ASSERTION_TOKEN"
56+
func: Callable[[], str] = lambda: assertion
57+
58+
async def send(request, **kwargs):
59+
assert request.data["client_assertion"] == assertion
60+
assert request.data["client_assertion_type"] == JWT_BEARER_ASSERTION
61+
assert request.data["client_id"] == client_id
62+
assert request.data["grant_type"] == "client_credentials"
63+
assert request.data["scope"] == scope
64+
65+
return mock_response(json_payload=build_aad_response(access_token=access_token))
66+
67+
with patch("azure.identity._internal.aad_client_base._load_persistent_cache") as load_persistent_cache:
68+
credential = ClientAssertionCredential(
69+
tenant_id=tenant_id,
70+
client_id=client_id,
71+
func=func,
72+
cache_persistence_options=TokenCachePersistenceOptions(),
73+
transport=Mock(send=send),
74+
)
75+
76+
assert load_persistent_cache.call_count == 0
77+
assert credential._client._cache is None
78+
assert credential._client._cae_cache is None
79+
80+
token = await credential.get_token(scope)
81+
assert token.token == access_token
82+
assert load_persistent_cache.call_count == 1
83+
assert credential._client._cache is not None
84+
assert credential._client._cae_cache is None
85+
86+
token = await credential.get_token(scope, enable_cae=True)
87+
assert load_persistent_cache.call_count == 2
88+
assert credential._client._cae_cache is not None

0 commit comments

Comments
 (0)