or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced.mdasync.mdazure-platform.mdcore-credentials.mddeveloper.mdindex.mdinteractive.mdservice-principal.md

interactive.mddocs/

0

# Interactive User Credentials

1

2

Enable user authentication through interactive flows including browser-based authentication, device code flow, and username/password authentication. These credentials are designed for applications that need to authenticate end users and operate on their behalf.

3

4

## Capabilities

5

6

### InteractiveBrowserCredential

7

8

Opens a web browser to interactively authenticate a user through Microsoft Entra ID. The most user-friendly authentication method for desktop and mobile applications with browser access.

9

10

```python { .api }

11

from azure.identity._constants import DEVELOPER_SIGN_ON_CLIENT_ID

12

13

class InteractiveBrowserCredential:

14

def __init__(

15

self,

16

*,

17

client_id: str = DEVELOPER_SIGN_ON_CLIENT_ID,

18

authority: Optional[str] = None,

19

tenant_id: Optional[str] = None,

20

redirect_uri: Optional[str] = None,

21

authentication_record: Optional[AuthenticationRecord] = None,

22

disable_automatic_authentication: bool = False,

23

cache_persistence_options: Optional[TokenCachePersistenceOptions] = None,

24

disable_instance_discovery: bool = False,

25

enable_support_logging: bool = False,

26

timeout: Optional[int] = None,

27

parent_window_handle: Optional[int] = None,

28

login_hint: Optional[str] = None,

29

enable_msa_passthrough: bool = False,

30

**kwargs

31

):

32

"""

33

Create an InteractiveBrowserCredential for user authentication via web browser.

34

35

Args:

36

client_id: Client ID of a Microsoft Entra application (defaults to Azure development application)

37

authority: Authority of a Microsoft Entra endpoint

38

tenant_id: Microsoft Entra tenant ID (restricts authentication to this tenant)

39

redirect_uri: Redirect URI for the application (default: http://localhost)

40

authentication_record: AuthenticationRecord from previous authenticate() call

41

disable_automatic_authentication: Raise AuthenticationRequiredError instead of automatically prompting

42

cache_persistence_options: Configuration for persistent token caching

43

disable_instance_discovery: Disable instance discovery and authority validation

44

enable_support_logging: Enable additional support logging

45

timeout: Request timeout in seconds

46

parent_window_handle: Handle to parent window for embedded browser scenarios (Windows only)

47

login_hint: Username hint to pre-fill during authentication

48

enable_msa_passthrough: Enable Microsoft Account (MSA) passthrough

49

"""

50

51

def authenticate(self, *scopes: str, claims: Optional[str] = None, **kwargs) -> AuthenticationRecord:

52

"""

53

Interactively authenticate a user and return an AuthenticationRecord.

54

55

Args:

56

*scopes: Desired scopes for the access token

57

claims: Additional claims required in the token

58

59

Returns:

60

AuthenticationRecord: Account information that can be used to create subsequent credentials

61

62

Raises:

63

ClientAuthenticationError: Authentication failed

64

"""

65

66

def get_token(self, *scopes: str, claims: Optional[str] = None, tenant_id: Optional[str] = None, **kwargs) -> AccessToken:

67

"""

68

Request an access token for the specified scopes.

69

70

Args:

71

*scopes: Desired scopes for the access token

72

claims: Additional claims required in the token

73

tenant_id: Optional tenant ID override

74

75

Returns:

76

AccessToken: The access token with expiration information

77

78

Raises:

79

AuthenticationRequiredError: Interactive authentication is required

80

"""

81

82

def get_token_info(self, *scopes: str, options: Optional[dict] = None) -> dict:

83

"""

84

Request access token with additional information.

85

86

Args:

87

*scopes: Desired scopes for the access token

88

options: Additional options for token acquisition

89

90

Returns:

91

dict: Token information including access token and metadata

92

"""

93

```

94

95

**Usage Example:**

96

97

```python

98

from azure.identity import InteractiveBrowserCredential

99

from azure.identity import AuthenticationRequiredError

100

101

# Basic browser authentication

102

credential = InteractiveBrowserCredential()

103

104

# Authenticate user and get account record

105

try:

106

record = credential.authenticate(scopes=["https://graph.microsoft.com/.default"])

107

print(f"Authenticated user: {record.username}")

108

except Exception as e:

109

print(f"Authentication failed: {e}")

110

111

# Reuse authentication record in subsequent sessions

112

from azure.identity import InteractiveBrowserCredential

113

114

saved_credential = InteractiveBrowserCredential(

115

authentication_record=record,

116

disable_automatic_authentication=True # Don't prompt if cache expires

117

)

118

119

# Tenant-specific authentication

120

tenant_credential = InteractiveBrowserCredential(

121

tenant_id="your-tenant-id",

122

client_id="your-app-client-id"

123

)

124

125

# Use with Azure SDK

126

from azure.storage.blob import BlobServiceClient

127

128

blob_client = BlobServiceClient(

129

account_url="https://account.blob.core.windows.net",

130

credential=credential

131

)

132

```

133

134

### DeviceCodeCredential

135

136

Authenticates users through the device code flow, where users authenticate on a different device using a browser. Ideal for devices without browsers or in headless environments.

137

138

```python { .api }

139

from azure.identity._constants import DEVELOPER_SIGN_ON_CLIENT_ID

140

141

class DeviceCodeCredential:

142

def __init__(

143

self,

144

client_id: str = DEVELOPER_SIGN_ON_CLIENT_ID,

145

*,

146

timeout: Optional[int] = None,

147

prompt_callback: Optional[Callable[[str, str, datetime], None]] = None,

148

authority: Optional[str] = None,

149

tenant_id: Optional[str] = None,

150

authentication_record: Optional[AuthenticationRecord] = None,

151

disable_automatic_authentication: bool = False,

152

cache_persistence_options: Optional[TokenCachePersistenceOptions] = None,

153

disable_instance_discovery: bool = False,

154

enable_support_logging: bool = False,

155

**kwargs

156

):

157

"""

158

Create a DeviceCodeCredential for device code flow authentication.

159

160

Args:

161

client_id: Client ID of a Microsoft Entra application (defaults to Azure development application)

162

timeout: Seconds to wait for user authentication completion

163

prompt_callback: Function to display authentication instructions to the user

164

authority: Authority of a Microsoft Entra endpoint

165

tenant_id: Microsoft Entra tenant ID

166

authentication_record: AuthenticationRecord from previous authenticate() call

167

disable_automatic_authentication: Raise AuthenticationRequiredError instead of prompting

168

cache_persistence_options: Configuration for persistent token caching

169

disable_instance_discovery: Disable instance discovery and authority validation

170

enable_support_logging: Enable additional support logging

171

"""

172

173

def authenticate(self, *scopes: str, claims: Optional[str] = None, **kwargs) -> AuthenticationRecord:

174

"""

175

Authenticate a user via device code flow and return an AuthenticationRecord.

176

177

Args:

178

*scopes: Desired scopes for the access token

179

claims: Additional claims required in the token

180

181

Returns:

182

AuthenticationRecord: Account information for subsequent authentications

183

"""

184

185

def get_token(self, *scopes: str, claims: Optional[str] = None, tenant_id: Optional[str] = None, **kwargs) -> AccessToken:

186

"""

187

Request an access token using device code flow.

188

189

Args:

190

*scopes: Desired scopes for the access token

191

claims: Additional claims required in the token

192

tenant_id: Optional tenant ID override

193

194

Returns:

195

AccessToken: The access token with expiration information

196

197

Raises:

198

AuthenticationRequiredError: User authentication is required

199

"""

200

201

def get_token_info(self, *scopes: str, options: Optional[dict] = None) -> dict:

202

"""

203

Request access token with additional information.

204

205

Args:

206

*scopes: Desired scopes for the access token

207

options: Additional options for token acquisition

208

209

Returns:

210

dict: Token information including access token and metadata

211

"""

212

```

213

214

**Usage Example:**

215

216

```python

217

from azure.identity import DeviceCodeCredential

218

from datetime import datetime

219

220

def custom_prompt_callback(verification_uri: str, user_code: str, expires_on: datetime):

221

"""Custom function to display device code to user."""

222

print("*" * 50)

223

print("DEVICE CODE AUTHENTICATION REQUIRED")

224

print(f"Please visit: {verification_uri}")

225

print(f"Enter code: {user_code}")

226

print(f"Code expires at: {expires_on}")

227

print("*" * 50)

228

229

# Device code authentication with custom prompt

230

credential = DeviceCodeCredential(

231

prompt_callback=custom_prompt_callback,

232

timeout=300 # 5 minutes for user to complete authentication

233

)

234

235

# Authenticate and save account record

236

record = credential.authenticate(scopes=["https://graph.microsoft.com/.default"])

237

238

# Use credential with Azure SDK

239

from azure.mgmt.resource import ResourceManagementClient

240

241

resource_client = ResourceManagementClient(

242

credential=credential,

243

subscription_id="your-subscription-id"

244

)

245

246

# List resource groups

247

for rg in resource_client.resource_groups.list():

248

print(rg.name)

249

```

250

251

### UsernamePasswordCredential

252

253

Authenticates a user using username and password credentials. Generally not recommended due to security concerns, but useful for legacy scenarios and automated testing.

254

255

```python { .api }

256

class UsernamePasswordCredential:

257

def __init__(

258

self,

259

client_id: str,

260

username: str,

261

password: str,

262

*,

263

authority: Optional[str] = None,

264

tenant_id: Optional[str] = None,

265

cache_persistence_options: Optional[TokenCachePersistenceOptions] = None,

266

disable_instance_discovery: bool = False,

267

additionally_allowed_tenants: List[str] = None,

268

**kwargs

269

):

270

"""

271

Create a UsernamePasswordCredential for password-based user authentication.

272

273

Args:

274

client_id: The application's client ID

275

username: The user's username (typically email address)

276

password: The user's password

277

authority: Authority of a Microsoft Entra endpoint

278

tenant_id: Microsoft Entra tenant ID

279

cache_persistence_options: Configuration for persistent token caching

280

disable_instance_discovery: Disable instance discovery and authority validation

281

additionally_allowed_tenants: Additional allowed tenants beyond the configured tenant

282

283

Warning:

284

Password-based authentication is less secure than interactive methods.

285

Consider using InteractiveBrowserCredential or DeviceCodeCredential instead.

286

"""

287

288

def authenticate(self, *scopes: str, claims: Optional[str] = None, **kwargs) -> AuthenticationRecord:

289

"""

290

Authenticate the user and return an AuthenticationRecord.

291

292

Args:

293

*scopes: Desired scopes for the access token

294

claims: Additional claims required in the token

295

296

Returns:

297

AuthenticationRecord: Account information for subsequent authentications

298

"""

299

300

def get_token(self, *scopes: str, claims: Optional[str] = None, tenant_id: Optional[str] = None, **kwargs) -> AccessToken:

301

"""

302

Request an access token using username and password.

303

304

Args:

305

*scopes: Desired scopes for the access token

306

claims: Additional claims required in the token

307

tenant_id: Optional tenant ID override

308

309

Returns:

310

AccessToken: The access token with expiration information

311

312

Raises:

313

ClientAuthenticationError: Invalid username or password

314

"""

315

316

def get_token_info(self, *scopes: str, options: Optional[dict] = None) -> dict:

317

"""

318

Request access token with additional information.

319

320

Args:

321

*scopes: Desired scopes for the access token

322

options: Additional options for token acquisition

323

324

Returns:

325

dict: Token information including access token and metadata

326

"""

327

```

328

329

**Usage Example:**

330

331

```python

332

from azure.identity import UsernamePasswordCredential

333

334

# Username/password authentication (use with caution)

335

credential = UsernamePasswordCredential(

336

client_id="your-public-client-id", # Must be a public client

337

username="user@example.com",

338

password="user-password"

339

)

340

341

# For automated testing scenarios

342

import os

343

344

test_credential = UsernamePasswordCredential(

345

client_id=os.environ["TEST_CLIENT_ID"],

346

username=os.environ["TEST_USERNAME"],

347

password=os.environ["TEST_PASSWORD"],

348

tenant_id=os.environ["TEST_TENANT_ID"]

349

)

350

351

# Use with Azure SDK (not recommended for production)

352

from azure.keyvault.secrets import SecretClient

353

354

secret_client = SecretClient(

355

vault_url="https://vault.vault.azure.net/",

356

credential=credential

357

)

358

```

359

360

## Interactive Credential Base

361

362

All interactive credentials extend a common base class that provides shared functionality:

363

364

```python { .api }

365

class InteractiveCredential:

366

"""Base class for interactive user credentials."""

367

368

def authenticate(self, *scopes: str, claims: Optional[str] = None, **kwargs) -> AuthenticationRecord:

369

"""

370

Interactively authenticate a user and return account information.

371

372

Args:

373

*scopes: Desired scopes for authentication

374

claims: Additional claims required

375

376

Returns:

377

AuthenticationRecord: Account information for caching and reuse

378

"""

379

380

def get_token(self, *scopes: str, claims: Optional[str] = None, tenant_id: Optional[str] = None, **kwargs) -> AccessToken:

381

"""Request an access token, prompting for authentication if necessary."""

382

383

def get_token_info(self, *scopes: str, options: Optional[dict] = None) -> dict:

384

"""Request access token with additional information."""

385

```

386

387

## Authentication Flow Patterns

388

389

### Silent Authentication Pattern

390

391

```python

392

from azure.identity import InteractiveBrowserCredential, AuthenticationRequiredError

393

394

# Create credential with cached authentication record

395

credential = InteractiveBrowserCredential(

396

authentication_record=saved_record,

397

disable_automatic_authentication=True

398

)

399

400

try:

401

# Try to get token silently from cache

402

token = credential.get_token("https://graph.microsoft.com/.default")

403

print("Silent authentication successful")

404

except AuthenticationRequiredError:

405

# Cache expired or invalid, need interactive authentication

406

print("Interactive authentication required")

407

record = credential.authenticate("https://graph.microsoft.com/.default")

408

# Save record for future silent authentication

409

```

410

411

### Conditional Interactive Authentication

412

413

```python

414

from azure.identity import DefaultAzureCredential

415

416

# Try DefaultAzureCredential first (non-interactive methods)

417

default_credential = DefaultAzureCredential(

418

exclude_interactive_browser_credential=True

419

)

420

421

try:

422

token = default_credential.get_token("https://graph.microsoft.com/.default")

423

print("Non-interactive authentication successful")

424

except CredentialUnavailableError:

425

# Fall back to interactive authentication

426

from azure.identity import InteractiveBrowserCredential

427

428

interactive_credential = InteractiveBrowserCredential()

429

token = interactive_credential.get_token("https://graph.microsoft.com/.default")

430

print("Interactive authentication successful")

431

```

432

433

## Common Interactive Parameters

434

435

```python { .api }

436

# Authentication record for silent authentication

437

authentication_record: Optional[AuthenticationRecord] = None

438

439

# Automatic vs. manual authentication control

440

disable_automatic_authentication: bool = False

441

442

# Tenant restriction

443

tenant_id: Optional[str] = None

444

445

# Token caching

446

cache_persistence_options: Optional[TokenCachePersistenceOptions] = None

447

448

# Authority customization

449

authority: Optional[str] = None

450

451

# Instance discovery

452

disable_instance_discovery: bool = False

453

454

# Additional logging

455

enable_support_logging: bool = False

456

457

# Client application configuration

458

client_id: str = DEVELOPER_SIGN_ON_CLIENT_ID # Default development app ID

459

460

# Multi-tenant support (UsernamePasswordCredential only)

461

additionally_allowed_tenants: List[str] = None

462

```

463

464

## Security Considerations

465

466

**Recommended Security Practices:**

467

468

1. **Use InteractiveBrowserCredential** for desktop applications

469

2. **Use DeviceCodeCredential** for headless or constrained environments

470

3. **Avoid UsernamePasswordCredential** in production - passwords are vulnerable

471

4. **Enable token caching** to reduce authentication prompts

472

5. **Use authentication records** to enable silent authentication

473

6. **Specify tenant_id** to restrict authentication to specific tenants

474

7. **Enable support logging** for troubleshooting authentication issues

475

476

**Authentication Record Management:**

477

478

```python

479

# Serialize authentication record for storage

480

record = credential.authenticate(scopes)

481

serialized = record.serialize()

482

483

# Store in secure location (encrypted file, secure keystore, etc.)

484

with open("auth_record.json", "w") as f:

485

f.write(serialized)

486

487

# Deserialize for reuse

488

with open("auth_record.json", "r") as f:

489

serialized = f.read()

490

491

record = AuthenticationRecord.deserialize(serialized)

492

credential = InteractiveBrowserCredential(authentication_record=record)

493

```