0
# Async Support
1
2
Asynchronous versions of all azure-identity credentials for use with asyncio-based applications and Azure SDK async clients. All async credentials implement the `AsyncTokenCredential` protocol and provide the same authentication capabilities as their synchronous counterparts.
3
4
## Core Async Module
5
6
```python { .api }
7
# Import async credentials from azure.identity.aio
8
from azure.identity.aio import (
9
DefaultAzureCredential,
10
ClientSecretCredential,
11
CertificateCredential,
12
ManagedIdentityCredential,
13
InteractiveBrowserCredential,
14
DeviceCodeCredential,
15
AzureCliCredential,
16
ChainedTokenCredential
17
)
18
```
19
20
## Capabilities
21
22
### AsyncTokenCredential Protocol
23
24
All async credentials implement the `AsyncTokenCredential` protocol, providing asynchronous token acquisition methods.
25
26
```python { .api }
27
from abc import ABC, abstractmethod
28
from typing import Optional, Any
29
from azure.core.credentials import AccessToken
30
31
class AsyncTokenCredential(ABC):
32
@abstractmethod
33
async def get_token(self, *scopes: str, claims: Optional[str] = None, tenant_id: Optional[str] = None, **kwargs: Any) -> AccessToken:
34
"""
35
Asynchronously request an access token for the specified scopes.
36
37
Args:
38
*scopes: Desired scopes for the access token
39
claims: Additional claims required in the token
40
tenant_id: Optional tenant ID override
41
**kwargs: Additional keyword arguments
42
43
Returns:
44
AccessToken: The access token with expiration information
45
"""
46
47
async def get_token_info(self, *scopes: str, options: Optional[dict] = None) -> dict:
48
"""
49
Asynchronously request an access token with additional information.
50
51
Args:
52
*scopes: Desired scopes for the access token
53
options: Additional options for token acquisition
54
55
Returns:
56
dict: Token information including access token and metadata
57
"""
58
59
async def close(self) -> None:
60
"""Close the credential's transport session."""
61
62
async def __aenter__(self):
63
"""Async context manager entry."""
64
return self
65
66
async def __aexit__(self, *args):
67
"""Async context manager exit."""
68
await self.close()
69
```
70
71
### DefaultAzureCredential (Async)
72
73
Asynchronous version of the intelligent credential chain that automatically detects available authentication methods.
74
75
```python { .api }
76
from azure.identity.aio import DefaultAzureCredential
77
78
class DefaultAzureCredential:
79
def __init__(self, **kwargs):
80
"""
81
Create an async DefaultAzureCredential with the same parameters as the sync version.
82
83
Attempts credentials in the same order as the synchronous version:
84
1. EnvironmentCredential
85
2. WorkloadIdentityCredential
86
3. ManagedIdentityCredential
87
4. SharedTokenCacheCredential
88
5. VisualStudioCodeCredential (excluded by default)
89
6. AzureCliCredential
90
7. AzurePowerShellCredential
91
8. AzureDeveloperCliCredential
92
9. InteractiveBrowserCredential (excluded by default)
93
"""
94
95
async def get_token(self, *scopes: str, **kwargs) -> AccessToken:
96
"""Asynchronously request an access token using the credential chain."""
97
98
async def get_token_info(self, *scopes: str, options: Optional[dict] = None) -> dict:
99
"""Asynchronously request access token with additional information."""
100
101
async def close(self) -> None:
102
"""Close the credential and its underlying transport."""
103
```
104
105
**Usage Example:**
106
107
```python
108
import asyncio
109
from azure.identity.aio import DefaultAzureCredential
110
from azure.storage.blob.aio import BlobServiceClient
111
112
async def main():
113
# Create async credential
114
credential = DefaultAzureCredential()
115
116
try:
117
# Use with async Azure SDK client
118
async with BlobServiceClient(
119
account_url="https://account.blob.core.windows.net",
120
credential=credential
121
) as blob_client:
122
123
# Asynchronously list containers
124
async for container in blob_client.list_containers():
125
print(f"Container: {container.name}")
126
127
finally:
128
# Always close the credential
129
await credential.close()
130
131
# Run async application
132
asyncio.run(main())
133
```
134
135
### Service Principal Credentials (Async)
136
137
Asynchronous versions of service principal authentication methods.
138
139
```python { .api }
140
from azure.identity.aio import ClientSecretCredential, CertificateCredential, ClientAssertionCredential
141
142
# All service principal credentials support the same constructor parameters
143
# as their synchronous counterparts
144
145
class ClientSecretCredential:
146
def __init__(self, tenant_id: str, client_id: str, client_secret: str, **kwargs): ...
147
async def get_token(self, *scopes: str, **kwargs) -> AccessToken: ...
148
async def close(self) -> None: ...
149
150
class CertificateCredential:
151
def __init__(self, tenant_id: str, client_id: str, certificate_path: Optional[str] = None, **kwargs): ...
152
async def get_token(self, *scopes: str, **kwargs) -> AccessToken: ...
153
async def close(self) -> None: ...
154
155
class ClientAssertionCredential:
156
def __init__(self, tenant_id: str, client_id: str, func: Callable[[], str], **kwargs): ...
157
async def get_token(self, *scopes: str, **kwargs) -> AccessToken: ...
158
async def close(self) -> None: ...
159
```
160
161
**Usage Example:**
162
163
```python
164
import asyncio
165
from azure.identity.aio import ClientSecretCredential
166
from azure.keyvault.secrets.aio import SecretClient
167
168
async def access_secrets():
169
credential = ClientSecretCredential(
170
tenant_id="your-tenant-id",
171
client_id="your-client-id",
172
client_secret="your-client-secret"
173
)
174
175
async with credential: # Use context manager for automatic cleanup
176
async with SecretClient(
177
vault_url="https://vault.vault.azure.net/",
178
credential=credential
179
) as secret_client:
180
181
secret = await secret_client.get_secret("database-password")
182
print(f"Retrieved secret: {secret.name}")
183
184
asyncio.run(access_secrets())
185
```
186
187
### Interactive Credentials (Async)
188
189
Asynchronous versions of interactive user authentication methods.
190
191
```python { .api }
192
from azure.identity.aio import (
193
InteractiveBrowserCredential,
194
DeviceCodeCredential,
195
UsernamePasswordCredential
196
)
197
198
class InteractiveBrowserCredential:
199
def __init__(self, **kwargs): ...
200
async def authenticate(self, *scopes: str, **kwargs) -> AuthenticationRecord: ...
201
async def get_token(self, *scopes: str, **kwargs) -> AccessToken: ...
202
async def close(self) -> None: ...
203
204
class DeviceCodeCredential:
205
def __init__(self, **kwargs): ...
206
async def authenticate(self, *scopes: str, **kwargs) -> AuthenticationRecord: ...
207
async def get_token(self, *scopes: str, **kwargs) -> AccessToken: ...
208
async def close(self) -> None: ...
209
210
class UsernamePasswordCredential:
211
def __init__(self, client_id: str, username: str, password: str, **kwargs): ...
212
async def authenticate(self, *scopes: str, **kwargs) -> AuthenticationRecord: ...
213
async def get_token(self, *scopes: str, **kwargs) -> AccessToken: ...
214
async def close(self) -> None: ...
215
```
216
217
**Usage Example:**
218
219
```python
220
import asyncio
221
from azure.identity.aio import InteractiveBrowserCredential
222
223
async def interactive_auth():
224
credential = InteractiveBrowserCredential()
225
226
try:
227
# Perform async authentication
228
record = await credential.authenticate(
229
scopes=["https://graph.microsoft.com/.default"]
230
)
231
print(f"Authenticated user: {record.username}")
232
233
# Get token asynchronously
234
token = await credential.get_token("https://graph.microsoft.com/.default")
235
print("Token acquired successfully")
236
237
finally:
238
await credential.close()
239
240
asyncio.run(interactive_auth())
241
```
242
243
### Azure Platform Credentials (Async)
244
245
Asynchronous versions of Azure-native authentication methods.
246
247
```python { .api }
248
from azure.identity.aio import (
249
ManagedIdentityCredential,
250
WorkloadIdentityCredential,
251
AzurePipelinesCredential
252
)
253
254
class ManagedIdentityCredential:
255
def __init__(self, *, client_id: Optional[str] = None, **kwargs): ...
256
async def get_token(self, *scopes: str, **kwargs) -> AccessToken: ...
257
async def close(self) -> None: ...
258
259
class WorkloadIdentityCredential:
260
def __init__(self, **kwargs): ...
261
async def get_token(self, *scopes: str, **kwargs) -> AccessToken: ...
262
async def close(self) -> None: ...
263
264
class AzurePipelinesCredential:
265
def __init__(self, *, system_access_token: str, service_connection_id: str, **kwargs): ...
266
async def get_token(self, *scopes: str, **kwargs) -> AccessToken: ...
267
async def close(self) -> None: ...
268
```
269
270
**Usage Example:**
271
272
```python
273
import asyncio
274
from azure.identity.aio import ManagedIdentityCredential
275
from azure.storage.blob.aio import BlobServiceClient
276
277
async def managed_identity_example():
278
# Use managed identity in Azure-hosted application
279
credential = ManagedIdentityCredential()
280
281
async with credential:
282
async with BlobServiceClient(
283
account_url="https://account.blob.core.windows.net",
284
credential=credential
285
) as blob_client:
286
287
containers = []
288
async for container in blob_client.list_containers():
289
containers.append(container.name)
290
291
print(f"Found {len(containers)} containers")
292
293
asyncio.run(managed_identity_example())
294
```
295
296
### Developer Tool Credentials (Async)
297
298
Asynchronous versions of developer tool authentication methods.
299
300
```python { .api }
301
from azure.identity.aio import (
302
AzureCliCredential,
303
AzureDeveloperCliCredential,
304
AzurePowerShellCredential,
305
VisualStudioCodeCredential,
306
SharedTokenCacheCredential
307
)
308
309
class AzureCliCredential:
310
def __init__(self, *, process_timeout: int = 10, **kwargs): ...
311
async def get_token(self, *scopes: str, **kwargs) -> AccessToken: ...
312
async def close(self) -> None: ...
313
314
class AzureDeveloperCliCredential:
315
def __init__(self, *, process_timeout: int = 10, **kwargs): ...
316
async def get_token(self, *scopes: str, **kwargs) -> AccessToken: ...
317
async def close(self) -> None: ...
318
319
class AzurePowerShellCredential:
320
def __init__(self, *, process_timeout: int = 10, **kwargs): ...
321
async def get_token(self, *scopes: str, **kwargs) -> AccessToken: ...
322
async def close(self) -> None: ...
323
324
class VisualStudioCodeCredential:
325
def __init__(self, **kwargs): ...
326
async def get_token(self, *scopes: str, **kwargs) -> AccessToken: ...
327
async def close(self) -> None: ...
328
329
class SharedTokenCacheCredential:
330
def __init__(self, username: Optional[str] = None, **kwargs): ...
331
async def get_token(self, *scopes: str, **kwargs) -> AccessToken: ...
332
async def close(self) -> None: ...
333
```
334
335
### ChainedTokenCredential (Async)
336
337
Asynchronous version of the configurable credential chain.
338
339
```python { .api }
340
from azure.identity.aio import ChainedTokenCredential
341
342
class ChainedTokenCredential:
343
def __init__(self, *credentials):
344
"""
345
Create an async credential chain from async credential instances.
346
347
Args:
348
*credentials: AsyncTokenCredential instances to try in order
349
"""
350
351
async def get_token(self, *scopes: str, **kwargs) -> AccessToken:
352
"""Asynchronously request token using first available credential."""
353
354
async def close(self) -> None:
355
"""Close all credentials in the chain."""
356
```
357
358
**Usage Example:**
359
360
```python
361
import asyncio
362
from azure.identity.aio import (
363
ChainedTokenCredential,
364
ManagedIdentityCredential,
365
AzureCliCredential
366
)
367
368
async def custom_chain_example():
369
# Create async credential chain
370
credential = ChainedTokenCredential(
371
ManagedIdentityCredential(), # Try managed identity first
372
AzureCliCredential() # Fall back to Azure CLI
373
)
374
375
try:
376
token = await credential.get_token("https://management.azure.com/.default")
377
print("Authentication successful with credential chain")
378
finally:
379
await credential.close()
380
381
asyncio.run(custom_chain_example())
382
```
383
384
## Async Utility Functions
385
386
Asynchronous versions of utility functions for working with credentials.
387
388
```python { .api }
389
from azure.identity.aio import get_bearer_token_provider
390
from typing import Callable, Coroutine, Any
391
392
def get_bearer_token_provider(credential: AsyncTokenCredential, *scopes: str) -> Callable[[], Coroutine[Any, Any, str]]:
393
"""
394
Returns a callable that asynchronously provides a bearer token string.
395
396
Args:
397
credential: The async credential used to authenticate requests
398
*scopes: The scopes required for the bearer token
399
400
Returns:
401
Callable that returns a coroutine yielding a bearer token string
402
"""
403
```
404
405
**Usage Example:**
406
407
```python
408
import asyncio
409
import aiohttp
410
from azure.identity.aio import DefaultAzureCredential, get_bearer_token_provider
411
412
async def make_graph_request():
413
credential = DefaultAzureCredential()
414
token_provider = get_bearer_token_provider(
415
credential,
416
"https://graph.microsoft.com/.default"
417
)
418
419
try:
420
# Get token asynchronously
421
token = await token_provider()
422
423
# Use with aiohttp
424
headers = {"Authorization": f"Bearer {token}"}
425
async with aiohttp.ClientSession() as session:
426
async with session.get(
427
"https://graph.microsoft.com/v1.0/me",
428
headers=headers
429
) as response:
430
user_data = await response.json()
431
print(f"User: {user_data.get('displayName')}")
432
433
finally:
434
await credential.close()
435
436
asyncio.run(make_graph_request())
437
```
438
439
## Async Patterns and Best Practices
440
441
### Context Manager Pattern
442
443
```python
444
import asyncio
445
from azure.identity.aio import DefaultAzureCredential
446
from azure.storage.blob.aio import BlobServiceClient
447
448
async def context_manager_pattern():
449
# Use async context managers for automatic cleanup
450
async with DefaultAzureCredential() as credential:
451
async with BlobServiceClient(
452
account_url="https://account.blob.core.windows.net",
453
credential=credential
454
) as blob_client:
455
456
# Perform operations
457
async for container in blob_client.list_containers():
458
print(f"Container: {container.name}")
459
460
# Credentials and clients are automatically closed
461
462
asyncio.run(context_manager_pattern())
463
```
464
465
### Resource Management
466
467
```python
468
import asyncio
469
from azure.identity.aio import ClientSecretCredential
470
471
async def proper_resource_management():
472
credential = ClientSecretCredential(
473
tenant_id="your-tenant-id",
474
client_id="your-client-id",
475
client_secret="your-client-secret"
476
)
477
478
try:
479
# Use credential
480
token = await credential.get_token("https://management.azure.com/.default")
481
print("Token acquired")
482
483
# Perform other async operations
484
await asyncio.sleep(1) # Simulate work
485
486
except Exception as e:
487
print(f"Error: {e}")
488
finally:
489
# Always close credential to free resources
490
await credential.close()
491
492
asyncio.run(proper_resource_management())
493
```
494
495
### Concurrent Authentication
496
497
```python
498
import asyncio
499
from azure.identity.aio import DefaultAzureCredential
500
501
async def concurrent_token_requests():
502
credential = DefaultAzureCredential()
503
504
try:
505
# Request multiple tokens concurrently
506
tasks = [
507
credential.get_token("https://graph.microsoft.com/.default"),
508
credential.get_token("https://storage.azure.com/.default"),
509
credential.get_token("https://management.azure.com/.default")
510
]
511
512
tokens = await asyncio.gather(*tasks)
513
print(f"Acquired {len(tokens)} tokens concurrently")
514
515
finally:
516
await credential.close()
517
518
asyncio.run(concurrent_token_requests())
519
```
520
521
### Error Handling in Async Context
522
523
```python
524
import asyncio
525
from azure.identity.aio import (
526
DefaultAzureCredential,
527
InteractiveBrowserCredential,
528
CredentialUnavailableError,
529
AuthenticationRequiredError
530
)
531
532
async def robust_async_authentication():
533
try:
534
# Try DefaultAzureCredential first
535
credential = DefaultAzureCredential()
536
token = await credential.get_token("https://graph.microsoft.com/.default")
537
print("Automatic authentication successful")
538
return credential
539
540
except CredentialUnavailableError:
541
print("Default authentication unavailable, trying interactive")
542
543
# Fall back to interactive authentication
544
interactive_credential = InteractiveBrowserCredential()
545
try:
546
token = await interactive_credential.get_token("https://graph.microsoft.com/.default")
547
print("Interactive authentication successful")
548
return interactive_credential
549
550
except AuthenticationRequiredError as e:
551
print(f"Authentication required for scopes: {list(e.scopes)}")
552
record = await interactive_credential.authenticate(*e.scopes)
553
print(f"Authentication completed for: {record.username}")
554
return interactive_credential
555
556
async def main():
557
credential = None
558
try:
559
credential = await robust_async_authentication()
560
# Use credential for subsequent operations
561
562
except Exception as e:
563
print(f"Authentication failed: {e}")
564
finally:
565
if credential:
566
await credential.close()
567
568
asyncio.run(main())
569
```
570
571
### Integration with FastAPI
572
573
```python
574
from fastapi import FastAPI, Depends, HTTPException
575
from azure.identity.aio import DefaultAzureCredential
576
from azure.storage.blob.aio import BlobServiceClient
577
import asyncio
578
579
app = FastAPI()
580
581
# Shared credential instance
582
credential = DefaultAzureCredential()
583
584
@app.on_event("startup")
585
async def startup_event():
586
"""Initialize credential on startup."""
587
pass
588
589
@app.on_event("shutdown")
590
async def shutdown_event():
591
"""Clean up credential on shutdown."""
592
await credential.close()
593
594
@app.get("/containers")
595
async def list_containers():
596
"""List blob containers using async credential."""
597
try:
598
async with BlobServiceClient(
599
account_url="https://account.blob.core.windows.net",
600
credential=credential
601
) as blob_client:
602
603
containers = []
604
async for container in blob_client.list_containers():
605
containers.append(container.name)
606
607
return {"containers": containers}
608
609
except Exception as e:
610
raise HTTPException(status_code=500, detail=str(e))
611
```
612
613
## Migration from Sync to Async
614
615
### Key Differences
616
617
1. **Import Path**: Use `azure.identity.aio` instead of `azure.identity`
618
2. **Async Methods**: All token acquisition methods are coroutines
619
3. **Context Managers**: Use `async with` for automatic resource cleanup
620
4. **Error Handling**: Same exception types, but handle in async context
621
5. **Resource Management**: Always call `await credential.close()` or use context managers
622
623
### Migration Example
624
625
```python
626
# Before (sync)
627
from azure.identity import DefaultAzureCredential
628
from azure.storage.blob import BlobServiceClient
629
630
credential = DefaultAzureCredential()
631
blob_client = BlobServiceClient(
632
account_url="https://account.blob.core.windows.net",
633
credential=credential
634
)
635
636
containers = list(blob_client.list_containers())
637
638
# After (async)
639
import asyncio
640
from azure.identity.aio import DefaultAzureCredential
641
from azure.storage.blob.aio import BlobServiceClient
642
643
async def main():
644
async with DefaultAzureCredential() as credential:
645
async with BlobServiceClient(
646
account_url="https://account.blob.core.windows.net",
647
credential=credential
648
) as blob_client:
649
650
containers = []
651
async for container in blob_client.list_containers():
652
containers.append(container)
653
654
asyncio.run(main())
655
```