0
# Azure Managed Identity
1
2
Azure managed identities provide automatically managed credentials for applications running on Azure services. MSAL Python's managed identity support eliminates the need for storing credentials in code or configuration, providing secure authentication for Azure resources including virtual machines, container instances, function apps, and other Azure services.
3
4
## Capabilities
5
6
### ManagedIdentityClient
7
8
Primary client for acquiring tokens using managed identities with automatic credential discovery and token caching.
9
10
```python { .api }
11
class ManagedIdentityClient:
12
def __init__(
13
self,
14
managed_identity: Union[dict, ManagedIdentity, SystemAssignedManagedIdentity, UserAssignedManagedIdentity],
15
*,
16
http_client, # Required
17
token_cache=None,
18
http_cache=None,
19
client_capabilities: Optional[List[str]] = None
20
):
21
"""
22
Create managed identity client.
23
24
Parameters:
25
- managed_identity: SystemAssignedManagedIdentity, UserAssignedManagedIdentity, or dict instance
26
- http_client: HTTP client instance (required)
27
- token_cache: Custom token cache (default: in-memory cache)
28
- http_cache: HTTP cache configuration
29
- client_capabilities: List of client capabilities
30
"""
31
32
def acquire_token_for_client(
33
self,
34
resource: str,
35
claims_challenge=None
36
):
37
"""
38
Acquire token for managed identity.
39
40
Parameters:
41
- resource: Target resource URL (e.g., "https://graph.microsoft.com/")
42
- claims_challenge: Additional claims from resource provider
43
44
Returns:
45
Dictionary with 'access_token' on success, 'error' on failure
46
"""
47
```
48
49
### System-Assigned Managed Identity
50
51
System-assigned identities are automatically created with the Azure resource and deleted when the resource is deleted. Each resource can have only one system-assigned identity.
52
53
```python { .api }
54
class SystemAssignedManagedIdentity:
55
def __init__(self):
56
"""Create system-assigned managed identity configuration."""
57
```
58
59
Usage example:
60
61
```python
62
import msal
63
64
# Create system-assigned managed identity
65
managed_identity = msal.SystemAssignedManagedIdentity()
66
67
# Create client
68
client = msal.ManagedIdentityClient(managed_identity)
69
70
# Acquire token for Microsoft Graph
71
result = client.acquire_token_for_client(
72
resource="https://graph.microsoft.com/"
73
)
74
75
if "access_token" in result:
76
print("Managed identity authentication successful!")
77
access_token = result["access_token"]
78
79
# Use token to call Microsoft Graph
80
import requests
81
headers = {"Authorization": f"Bearer {access_token}"}
82
response = requests.get("https://graph.microsoft.com/v1.0/me", headers=headers)
83
84
if response.status_code == 200:
85
user_info = response.json()
86
print(f"Authenticated as: {user_info.get('displayName')}")
87
else:
88
print(f"Authentication failed: {result.get('error_description')}")
89
```
90
91
### User-Assigned Managed Identity
92
93
User-assigned identities are standalone Azure resources that can be assigned to multiple Azure resources. They have independent lifecycles from the resources they're assigned to.
94
95
```python { .api }
96
class UserAssignedManagedIdentity:
97
def __init__(
98
self,
99
client_id=None,
100
object_id=None,
101
resource_id=None
102
):
103
"""
104
Create user-assigned managed identity configuration.
105
106
Parameters (specify exactly one):
107
- client_id: Client ID of user-assigned managed identity
108
- object_id: Object ID of user-assigned managed identity
109
- resource_id: Azure resource ID of user-assigned managed identity
110
"""
111
```
112
113
Usage examples:
114
115
```python
116
import msal
117
118
# Using client ID
119
managed_identity = msal.UserAssignedManagedIdentity(
120
client_id="12345678-1234-1234-1234-123456789012"
121
)
122
123
# Using object ID
124
managed_identity = msal.UserAssignedManagedIdentity(
125
object_id="abcdef12-3456-7890-abcd-123456789012"
126
)
127
128
# Using resource ID
129
managed_identity = msal.UserAssignedManagedIdentity(
130
resource_id="/subscriptions/sub-id/resourcegroups/rg-name/providers/Microsoft.ManagedIdentity/userAssignedIdentities/identity-name"
131
)
132
133
# Create client and acquire token
134
client = msal.ManagedIdentityClient(managed_identity)
135
136
result = client.acquire_token_for_client(
137
resource="https://management.azure.com/"
138
)
139
140
if "access_token" in result:
141
print("User-assigned managed identity authentication successful!")
142
access_token = result["access_token"]
143
else:
144
print(f"Authentication failed: {result.get('error_description')}")
145
```
146
147
### ManagedIdentity Base Class
148
149
Base class providing utility methods for managed identity type checking and configuration validation.
150
151
```python { .api }
152
class ManagedIdentity:
153
# Configuration keys
154
ID_TYPE = "ManagedIdentityIdType"
155
ID = "Id"
156
157
# Identity type constants
158
CLIENT_ID = "ClientId"
159
RESOURCE_ID = "ResourceId"
160
OBJECT_ID = "ObjectId"
161
SYSTEM_ASSIGNED = "SystemAssigned"
162
163
@classmethod
164
def is_managed_identity(cls, unknown) -> bool:
165
"""Check if object is a managed identity instance."""
166
167
@classmethod
168
def is_system_assigned(cls, unknown) -> bool:
169
"""Check if object is system-assigned managed identity."""
170
171
@classmethod
172
def is_user_assigned(cls, unknown) -> bool:
173
"""Check if object is user-assigned managed identity."""
174
```
175
176
Usage example:
177
178
```python
179
import msal
180
181
# Check identity types
182
system_identity = msal.SystemAssignedManagedIdentity()
183
user_identity = msal.UserAssignedManagedIdentity(client_id="...")
184
185
print(f"Is system identity: {msal.ManagedIdentity.is_system_assigned(system_identity)}")
186
print(f"Is user identity: {msal.ManagedIdentity.is_user_assigned(user_identity)}")
187
print(f"Is managed identity: {msal.ManagedIdentity.is_managed_identity(system_identity)}")
188
```
189
190
### Supported Azure Services
191
192
Managed identities work on various Azure services:
193
194
#### Azure Virtual Machines
195
```python
196
import msal
197
198
# Works automatically on VM with managed identity enabled
199
managed_identity = msal.SystemAssignedManagedIdentity()
200
client = msal.ManagedIdentityClient(managed_identity)
201
202
result = client.acquire_token_for_client(
203
resource="https://vault.azure.net/" # Azure Key Vault
204
)
205
```
206
207
#### Azure Container Instances
208
```python
209
import msal
210
import os
211
212
# Container instance with user-assigned identity
213
client_id = os.environ.get("AZURE_CLIENT_ID")
214
managed_identity = msal.UserAssignedManagedIdentity(client_id=client_id)
215
client = msal.ManagedIdentityClient(managed_identity)
216
217
result = client.acquire_token_for_client(
218
resource="https://storage.azure.com/" # Azure Storage
219
)
220
```
221
222
#### Azure Functions
223
```python
224
import msal
225
import azure.functions as func
226
227
def main(req: func.HttpRequest) -> func.HttpResponse:
228
# Function app with system-assigned identity
229
managed_identity = msal.SystemAssignedManagedIdentity()
230
client = msal.ManagedIdentityClient(managed_identity)
231
232
result = client.acquire_token_for_client(
233
resource="https://database.windows.net/" # Azure SQL
234
)
235
236
if "access_token" in result:
237
# Use token to access Azure SQL
238
access_token = result["access_token"]
239
return func.HttpResponse("Authentication successful")
240
else:
241
return func.HttpResponse("Authentication failed", status_code=401)
242
```
243
244
#### Azure App Service
245
```python
246
import msal
247
from flask import Flask
248
249
app = Flask(__name__)
250
251
@app.route('/api/data')
252
def get_data():
253
# App Service with managed identity
254
managed_identity = msal.SystemAssignedManagedIdentity()
255
client = msal.ManagedIdentityClient(managed_identity)
256
257
result = client.acquire_token_for_client(
258
resource="https://cognitiveservices.azure.com/" # Cognitive Services
259
)
260
261
if "access_token" in result:
262
# Call Cognitive Services API
263
import requests
264
headers = {"Authorization": f"Bearer {result['access_token']}"}
265
# Make API call...
266
return {"status": "success"}
267
else:
268
return {"status": "error", "message": result.get("error_description")}
269
```
270
271
### Token Caching with Managed Identity
272
273
Managed identity tokens are automatically cached to improve performance:
274
275
```python
276
import msal
277
278
# Custom cache for managed identity tokens
279
cache = msal.TokenCache()
280
281
managed_identity = msal.SystemAssignedManagedIdentity()
282
client = msal.ManagedIdentityClient(
283
managed_identity=managed_identity,
284
token_cache=cache
285
)
286
287
# First call - acquires token from Azure Instance Metadata Service (IMDS)
288
result1 = client.acquire_token_for_client(
289
resource="https://graph.microsoft.com/"
290
)
291
292
# Second call - uses cached token if still valid
293
result2 = client.acquire_token_for_client(
294
resource="https://graph.microsoft.com/"
295
)
296
297
print(f"First call successful: {'access_token' in result1}")
298
print(f"Second call successful: {'access_token' in result2}")
299
```
300
301
### Multiple Resource Access
302
303
Single managed identity can access multiple Azure resources:
304
305
```python
306
import msal
307
308
managed_identity = msal.SystemAssignedManagedIdentity()
309
client = msal.ManagedIdentityClient(managed_identity)
310
311
# Access different Azure resources
312
resources = [
313
"https://graph.microsoft.com/", # Microsoft Graph
314
"https://management.azure.com/", # Azure Resource Manager
315
"https://vault.azure.net/", # Azure Key Vault
316
"https://storage.azure.com/", # Azure Storage
317
"https://database.windows.net/", # Azure SQL Database
318
]
319
320
tokens = {}
321
for resource in resources:
322
result = client.acquire_token_for_client(resource=resource)
323
324
if "access_token" in result:
325
tokens[resource] = result["access_token"]
326
print(f"Successfully acquired token for {resource}")
327
else:
328
print(f"Failed to acquire token for {resource}: {result.get('error_description')}")
329
330
print(f"Acquired tokens for {len(tokens)} resources")
331
```
332
333
### Environment Detection
334
335
Managed identity authentication automatically detects the Azure environment:
336
337
```python
338
import msal
339
340
managed_identity = msal.SystemAssignedManagedIdentity()
341
client = msal.ManagedIdentityClient(managed_identity)
342
343
# Works across different Azure environments:
344
# - Azure Virtual Machines (IMDS endpoint)
345
# - Azure Container Instances (IMDS endpoint)
346
# - Azure Functions (MSI_ENDPOINT environment variable)
347
# - Azure App Service (MSI_ENDPOINT environment variable)
348
# - Azure Arc (Azure Arc metadata service)
349
# - Azure Cloud Shell (Azure Cloud Shell service)
350
351
result = client.acquire_token_for_client(
352
resource="https://graph.microsoft.com/"
353
)
354
355
# The client automatically detects and uses the appropriate endpoint
356
if "access_token" in result:
357
print("Managed identity authentication successful")
358
print(f"Token source: {result.get('token_source', 'unknown')}")
359
```
360
361
## Error Handling
362
363
Common error scenarios and handling patterns for managed identity authentication:
364
365
```python
366
import msal
367
368
managed_identity = msal.SystemAssignedManagedIdentity()
369
client = msal.ManagedIdentityClient(managed_identity)
370
371
try:
372
result = client.acquire_token_for_client(
373
resource="https://graph.microsoft.com/"
374
)
375
376
if "access_token" in result:
377
access_token = result["access_token"]
378
print("Authentication successful")
379
else:
380
error = result.get("error")
381
error_description = result.get("error_description", "")
382
383
if error == "managed_identity_not_available":
384
print("Managed identity not available on this resource")
385
print("Ensure managed identity is enabled on the Azure resource")
386
elif error == "invalid_resource":
387
print(f"Invalid resource specified: {error_description}")
388
elif error == "forbidden":
389
print("Managed identity doesn't have permission for this resource")
390
print("Check Azure role assignments for the managed identity")
391
elif error == "arc_platform_not_supported":
392
print("Azure Arc managed identity not supported on this platform")
393
else:
394
print(f"Authentication failed: {error} - {error_description}")
395
396
except msal.ManagedIdentityError as e:
397
print(f"Managed identity error: {e}")
398
except msal.ArcPlatformNotSupportedError as e:
399
print(f"Azure Arc platform not supported: {e}")
400
except Exception as e:
401
print(f"Unexpected error: {e}")
402
403
# User-assigned identity error handling
404
try:
405
user_identity = msal.UserAssignedManagedIdentity(
406
client_id="invalid-client-id"
407
)
408
client = msal.ManagedIdentityClient(user_identity)
409
410
result = client.acquire_token_for_client(
411
resource="https://graph.microsoft.com/"
412
)
413
414
if "access_token" not in result:
415
error = result.get("error")
416
417
if error == "identity_not_found":
418
print("User-assigned managed identity not found")
419
print("Verify the client_id/object_id/resource_id is correct")
420
print("Ensure the identity is assigned to this resource")
421
elif error == "multiple_identities_found":
422
print("Multiple user-assigned identities found")
423
print("Specify client_id, object_id, or resource_id to disambiguate")
424
425
except ValueError as e:
426
print(f"Invalid managed identity configuration: {e}")
427
```
428
429
## Best Practices
430
431
### Security Considerations
432
- Use least-privilege principle when assigning roles to managed identities
433
- Regularly review and audit managed identity role assignments
434
- Use user-assigned identities for better lifecycle management in complex scenarios
435
- Monitor managed identity usage through Azure Activity Logs
436
437
### Performance Optimization
438
- Leverage automatic token caching to minimize authentication requests
439
- Use appropriate token lifetimes for your application's needs
440
- Consider connection pooling for HTTP clients in high-throughput scenarios
441
442
### Deployment Patterns
443
```python
444
import msal
445
import os
446
447
def create_managed_identity_client():
448
"""Factory function for managed identity client creation."""
449
450
# Check for user-assigned identity configuration
451
client_id = os.environ.get("AZURE_CLIENT_ID")
452
453
if client_id:
454
# Use user-assigned identity
455
managed_identity = msal.UserAssignedManagedIdentity(client_id=client_id)
456
else:
457
# Use system-assigned identity
458
managed_identity = msal.SystemAssignedManagedIdentity()
459
460
return msal.ManagedIdentityClient(managed_identity)
461
462
# Usage in application
463
def authenticate_and_call_api():
464
client = create_managed_identity_client()
465
466
result = client.acquire_token_for_client(
467
resource="https://graph.microsoft.com/"
468
)
469
470
if "access_token" in result:
471
return result["access_token"]
472
else:
473
raise Exception(f"Authentication failed: {result.get('error_description')}")
474
```