references/auth-best-practices.md
# Azure Authentication Best Practices
> Source: [Microsoft — Passwordless connections for Azure services](https://learn.microsoft.com/azure/developer/intro/passwordless-overview) and [Azure Identity client libraries](https://learn.microsoft.com/dotnet/azure/sdk/authentication/).
## Golden Rule
Use **managed identities** and **Azure RBAC** in production. Reserve `DefaultAzureCredential` for **local development only**.
## Authentication by Environment
| Environment | Recommended Credential | Why |
|---|---|---|
| **Production (Azure-hosted)** | `ManagedIdentityCredential` (system- or user-assigned) | No secrets to manage; auto-rotated by Azure |
| **Production (on-premises)** | `ClientCertificateCredential` or `WorkloadIdentityCredential` | Deterministic; no fallback chain overhead |
| **CI/CD pipelines** | `AzurePipelinesCredential` / `WorkloadIdentityCredential` | Scoped to pipeline identity |
| **Local development** | `DefaultAzureCredential` | Chains CLI, PowerShell, and VS Code credentials for convenience |
## Why Not `DefaultAzureCredential` in Production?
1. **Unpredictable fallback chain** — walks through multiple credential types, adding latency and making failures harder to diagnose.
2. **Broad surface area** — checks environment variables, CLI tokens, and other sources that should not exist in production.
3. **Non-deterministic** — which credential actually authenticates depends on the environment, making behavior inconsistent across deployments.
4. **Performance** — each failed credential attempt adds network round-trips before falling back to the next.
## Production Patterns
### .NET
```csharp
using Azure.Identity;
var credential = Environment.GetEnvironmentVariable("AZURE_FUNCTIONS_ENVIRONMENT") == "Development"
? new DefaultAzureCredential() // local dev — uses CLI/VS credentials
: new ManagedIdentityCredential(); // production — deterministic, no fallback chain
// For user-assigned identity: new ManagedIdentityCredential("<client-id>")
```
### TypeScript / JavaScript
```typescript
import { DefaultAzureCredential, ManagedIdentityCredential } from "@azure/identity";
const credential = process.env.NODE_ENV === "development"
? new DefaultAzureCredential() // local dev — uses CLI/VS credentials
: new ManagedIdentityCredential(); // production — deterministic, no fallback chain
// For user-assigned identity: new ManagedIdentityCredential("<client-id>")
```
### Python
```python
import os
from azure.identity import DefaultAzureCredential, ManagedIdentityCredential
credential = (
DefaultAzureCredential() # local dev — uses CLI/VS credentials
if os.getenv("AZURE_FUNCTIONS_ENVIRONMENT") == "Development"
else ManagedIdentityCredential() # production — deterministic, no fallback chain
)
# For user-assigned identity: ManagedIdentityCredential(client_id="<client-id>")
```
### Java
```java
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.identity.ManagedIdentityCredentialBuilder;
var credential = "Development".equals(System.getenv("AZURE_FUNCTIONS_ENVIRONMENT"))
? new DefaultAzureCredentialBuilder().build() // local dev — uses CLI/VS credentials
: new ManagedIdentityCredentialBuilder().build(); // production — deterministic, no fallback chain
// For user-assigned identity: new ManagedIdentityCredentialBuilder().clientId("<client-id>").build()
```
## Local Development Setup
`DefaultAzureCredential` is ideal for local dev because it automatically picks up credentials from developer tools:
1. **Azure CLI** — `az login`
2. **Azure Developer CLI** — `azd auth login`
3. **Azure PowerShell** — `Connect-AzAccount`
4. **Visual Studio / VS Code** — sign in via Azure extension
```typescript
import { DefaultAzureCredential } from "@azure/identity";
// Local development only — uses CLI/PowerShell/VS Code credentials
const credential = new DefaultAzureCredential();
```
## Environment-Aware Pattern
Detect the runtime environment and select the appropriate credential. The key principle: use `DefaultAzureCredential` only when running locally, and a specific credential in production.
> **Tip:** Azure Functions sets `AZURE_FUNCTIONS_ENVIRONMENT` to `"Development"` when running locally. For App Service or containers, use any environment variable you control (e.g. `NODE_ENV`, `ASPNETCORE_ENVIRONMENT`).
```typescript
import { DefaultAzureCredential, ManagedIdentityCredential } from "@azure/identity";
function getCredential() {
if (process.env.NODE_ENV === "development") {
return new DefaultAzureCredential(); // picks up az login / VS Code creds
}
return process.env.AZURE_CLIENT_ID
? new ManagedIdentityCredential(process.env.AZURE_CLIENT_ID) // user-assigned
: new ManagedIdentityCredential(); // system-assigned
}
```
## Security Checklist
- [ ] Use managed identity for all Azure-hosted apps
- [ ] Never hardcode credentials, connection strings, or keys
- [ ] Apply least-privilege RBAC roles at the narrowest scope
- [ ] Use `ManagedIdentityCredential` (not `DefaultAzureCredential`) in production
- [ ] Store any required secrets in Azure Key Vault
- [ ] Rotate secrets and certificates on a schedule
- [ ] Enable Microsoft Defender for Cloud on production resources
## Further Reading
- [Passwordless connections overview](https://learn.microsoft.com/azure/developer/intro/passwordless-overview)
- [Managed identities overview](https://learn.microsoft.com/entra/identity/managed-identities-azure-resources/overview)
- [Azure RBAC overview](https://learn.microsoft.com/azure/role-based-access-control/overview)
- [.NET authentication guide](https://learn.microsoft.com/dotnet/azure/sdk/authentication/)
- [Python identity library](https://learn.microsoft.com/python/api/overview/azure/identity-readme)
- [JavaScript identity library](https://learn.microsoft.com/javascript/api/overview/azure/identity-readme)
- [Java identity library](https://learn.microsoft.com/java/api/overview/azure/identity-readme)
references/sdk-usage.md
# Azure Storage SDK Usage
SDK packages and quick start examples for Azure Storage services.
## Storage SDKs by Language
| Language | Blob | Queue | File Share | Data Lake |
|----------|------|-------|------------|----------|
| .NET | `Azure.Storage.Blobs` | `Azure.Storage.Queues` | `Azure.Storage.Files.Shares` | `Azure.Storage.Files.DataLake` |
| Java | `azure-storage-blob` | `azure-storage-queue` | `azure-storage-file-share` | `azure-storage-file-datalake` |
| JavaScript | `@azure/storage-blob` | `@azure/storage-queue` | `@azure/storage-file-share` | `@azure/storage-file-datalake` |
| Python | `azure-storage-blob` | `azure-storage-queue` | `azure-storage-file-share` | `azure-storage-file-datalake` |
| Go | `azblob` | `azqueue` | `azfile` | `azdatalake` |
| Rust | `azure_storage_blob` | `azure_storage_queue` | - | - |
## Installation Commands
| Language | Install Blob SDK + Identity |
|----------|-----------------------------|
| .NET | `dotnet add package Azure.Storage.Blobs` `dotnet add package Azure.Identity` |
| Java | Maven: `com.azure:azure-storage-blob` `com.azure:azure-identity` |
| JavaScript | `npm install @azure/storage-blob @azure/identity` |
| Python | `pip install azure-storage-blob azure-identity` |
| Go | `go get github.com/Azure/azure-sdk-for-go/sdk/storage/azblob github.com/Azure/azure-sdk-for-go/sdk/azidentity` |
| Rust | `cargo add azure_storage_blob azure_identity` |
## Quick Start Examples
All examples use `DefaultAzureCredential` for authentication, which is recommended for **local development only**. In production, use `ManagedIdentityCredential` — see [auth-best-practices.md](auth-best-practices.md). Rust uses `DeveloperToolsCredential` as it doesn't have a `DefaultAzureCredential` equivalent.
**Python** - Upload Blob:
```python
from azure.identity import DefaultAzureCredential
from azure.storage.blob import BlobServiceClient
service = BlobServiceClient(account_url="https://ACCOUNT.blob.core.windows.net/", credential=DefaultAzureCredential())
container = service.get_container_client("my-container")
blob = container.get_blob_client("my-blob.txt")
blob.upload_blob(b"Hello, Azure Storage!", overwrite=True)
```
**JavaScript** - Upload Blob:
```javascript
import { DefaultAzureCredential } from "@azure/identity";
import { BlobServiceClient } from "@azure/storage-blob";
const client = new BlobServiceClient("https://ACCOUNT.blob.core.windows.net/", new DefaultAzureCredential());
const container = client.getContainerClient("my-container");
const blob = container.getBlockBlobClient("my-blob.txt");
await blob.uploadData(Buffer.from("Hello, Azure Storage!"));
```
**C#** - Upload Blob:
```csharp
using Azure.Identity;
using Azure.Storage.Blobs;
var client = new BlobServiceClient(new Uri("https://ACCOUNT.blob.core.windows.net/"), new DefaultAzureCredential());
var container = client.GetBlobContainerClient("my-container");
var blob = container.GetBlobClient("my-blob.txt");
await blob.UploadAsync(BinaryData.FromString("Hello, Azure Storage!"), overwrite: true);
```
**Java** - Upload Blob:
```java
import com.azure.identity.*;
import com.azure.storage.blob.*;
import com.azure.core.util.BinaryData;
BlobServiceClient client = new BlobServiceClientBuilder()
.endpoint("https://ACCOUNT.blob.core.windows.net/")
.credential(new DefaultAzureCredentialBuilder().build())
.buildClient();
BlobContainerClient container = client.getBlobContainerClient("my-container");
BlobClient blob = container.getBlobClient("my-blob.txt");
blob.upload(BinaryData.fromString("Hello, Azure Storage!"), true);
```
**Go** - Upload Blob:
```go
package main
import (
"context"
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob"
)
func main() {
cred, _ := azidentity.NewDefaultAzureCredential(nil)
client, _ := azblob.NewClient("https://ACCOUNT.blob.core.windows.net/", cred, nil)
data := []byte("Hello, Azure Storage!")
_, _ = client.UploadBuffer(context.Background(), "my-container", "my-blob.txt", data, nil)
}
```
**Rust** - Upload Blob:
```rust
use azure_identity::DeveloperToolsCredential;
use azure_storage_blob::{BlobClient, BlobClientOptions};
let credential = DeveloperToolsCredential::new(None)?;
let blob_client = BlobClient::new(
"https://ACCOUNT.blob.core.windows.net/",
"my-container",
"my-blob.txt",
Some(credential),
Some(BlobClientOptions::default()),
)?;
let data = b"Hello, Azure Storage!";
blob_client.upload(None, data.to_vec().into()).await?;
```
references/sdk/azure-data-tables-java.md
# Tables — Java SDK Quick Reference
> Condensed from **azure-data-tables-java**. Full patterns (typed entities,
> batch transactions, OData filters, Cosmos DB Table API)
> in the **azure-data-tables-java** plugin skill if installed.
## Install
```xml
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-data-tables</artifactId>
<version>12.6.0-beta.1</version>
</dependency>
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-identity</artifactId>
</dependency>
```
## Quick Start
> **Auth:** `DefaultAzureCredential` is for local development. See [auth-best-practices.md](../auth-best-practices.md) for production patterns.
```java
import com.azure.data.tables.TableServiceClientBuilder;
import com.azure.identity.DefaultAzureCredentialBuilder;
var serviceClient = new TableServiceClientBuilder()
.endpoint("<table-account-url>")
.credential(new DefaultAzureCredentialBuilder().build())
.buildClient();
```
## Best Practices
- Partition Key Design: choose keys that distribute load evenly
- Batch Operations: use transactions for atomic multi-entity updates
- Query Optimization: always filter by PartitionKey when possible
- Select Projection: only select needed properties for performance
- Entity Size: keep entities under 1MB (Storage) or 2MB (Cosmos)
references/sdk/azure-data-tables-py.md
# Tables — Python SDK Quick Reference
> Condensed from **azure-data-tables-py**. Full patterns (batch operations,
> async client, typed entities, query parameters)
> in the **azure-data-tables-py** plugin skill if installed.
## Install
pip install azure-data-tables azure-identity
## Quick Start
> **Auth:** `DefaultAzureCredential` is for local development. See [auth-best-practices.md](../auth-best-practices.md) for production patterns.
```python
from azure.data.tables import TableClient
from azure.identity import DefaultAzureCredential
table_client = TableClient("https://<account>.table.core.windows.net", "mytable", DefaultAzureCredential())
```
## Best Practices
- Design partition keys for query patterns and even distribution
- Query within partitions whenever possible (cross-partition is expensive)
- Use batch operations for multiple entities in same partition
- Use `upsert_entity` for idempotent writes
- Use parameterized queries to prevent injection
- Keep entities small — max 1MB per entity
- Use async client for high-throughput scenarios
references/sdk/azure-storage-blob-java.md
# Blob Storage — Java SDK Quick Reference
> Condensed from **azure-storage-blob-java**. Full patterns (SAS tokens,
> streaming, lease management, parallel uploads, proxy config)
> in the **azure-storage-blob-java** plugin skill if installed.
## Install
```xml
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-storage-blob</artifactId>
<version>12.33.0</version>
</dependency>
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-identity</artifactId>
</dependency>
```
## Quick Start
```java
import com.azure.storage.blob.BlobServiceClientBuilder;
import com.azure.identity.DefaultAzureCredentialBuilder;
var serviceClient = new BlobServiceClientBuilder()
.endpoint("<storage-account-url>")
.credential(new DefaultAzureCredentialBuilder().build())
.buildClient();
```
## Best Practices
- Use DefaultAzureCredential for **local development only** — in production, use ManagedIdentityCredential. See [auth-best-practices.md](../auth-best-practices.md)
- Use `BinaryData.fromString()` for string uploads
- Use `createIfNotExists()` for idempotent container creation
- Use `BlobParallelUploadOptions` for large file uploads with headers/metadata
- Use `BlobInputStream`/`BlobOutputStream` for streaming large blobs
- Handle `BlobStorageException` — check `getStatusCode()` and `getErrorCode()`
references/sdk/azure-storage-blob-py.md
# Blob Storage — Python SDK Quick Reference
> Condensed from **azure-storage-blob-py**. Full patterns (SAS tokens,
> async client, performance tuning, blob properties/metadata)
> in the **azure-storage-blob-py** plugin skill if installed.
## Install
pip install azure-storage-blob azure-identity
## Quick Start
```python
from azure.storage.blob import BlobServiceClient
from azure.identity import DefaultAzureCredential
blob_service_client = BlobServiceClient("https://<account>.blob.core.windows.net", DefaultAzureCredential())
```
## Best Practices
- Use DefaultAzureCredential for **local development only** — in production, use ManagedIdentityCredential. See [auth-best-practices.md](../auth-best-practices.md)
- Use context managers for async clients
- Set `overwrite=True` explicitly when re-uploading
- Use `max_concurrency` for large file transfers
- Prefer `readinto()` over `readall()` for memory efficiency
- Use `walk_blobs()` for hierarchical listing
- Set appropriate content types for web-served blobs
references/sdk/azure-storage-blob-rust.md
# Blob Storage — Rust SDK Quick Reference
> Condensed from **azure-storage-blob-rust**. Full patterns (container ops,
> blob properties, RBAC permissions)
> in the **azure-storage-blob-rust** plugin skill if installed.
## Install
cargo add azure_storage_blob azure_identity
## Quick Start
```rust
use azure_identity::DeveloperToolsCredential;
use azure_storage_blob::BlobClient;
let credential = DeveloperToolsCredential::new(None)?;
let blob_client = BlobClient::new("https://<account>.blob.core.windows.net/", "container", "blob", Some(credential), None)?;
```
## Best Practices
- Use Entra ID auth — `DeveloperToolsCredential` for dev, `ManagedIdentityCredential` for production
- Specify content length — required for uploads
- Use `RequestContent::from()` to wrap upload data
- Handle async operations — use `tokio` runtime
- Check RBAC permissions — ensure "Storage Blob Data Contributor" role
## Non-Obvious Patterns
```rust
use azure_core::http::RequestContent;
blob_client.upload(RequestContent::from(data.to_vec()), false, u64::try_from(data.len())?, None).await?;
```
references/sdk/azure-storage-blob-ts.md
# Blob Storage — TypeScript SDK Quick Reference
> Condensed from **azure-storage-blob-ts**. Full patterns (SAS generation,
> append/page blobs, streaming, browser uploads, error handling)
> in the **azure-storage-blob-ts** plugin skill if installed.
## Install
npm install @azure/storage-blob @azure/identity
## Quick Start
```typescript
import { BlobServiceClient } from "@azure/storage-blob";
import { DefaultAzureCredential } from "@azure/identity";
const client = new BlobServiceClient(`https://${accountName}.blob.core.windows.net`, new DefaultAzureCredential());
```
## Best Practices
- Use DefaultAzureCredential for **local development only** — in production, use ManagedIdentityCredential. See [auth-best-practices.md](../auth-best-practices.md)
- Use streaming for large files — `uploadStream`/`downloadToFile` for files > 256MB
- Set appropriate content types — use `setHTTPHeaders` for correct MIME types
- Use SAS tokens for client access — generate short-lived tokens for browser uploads
- Handle errors gracefully — check `RestError.statusCode` for specific handling
- Use `*IfNotExists` methods for idempotent container/blob creation
- Close clients — good practice in long-running apps
references/sdk/azure-storage-file-datalake-py.md
# Data Lake Storage Gen2 — Python SDK Quick Reference
> Condensed from **azure-storage-file-datalake-py**. Full patterns (ACL management,
> async client, directory operations, range downloads)
> in the **azure-storage-file-datalake-py** plugin skill if installed.
## Install
pip install azure-storage-file-datalake azure-identity
## Quick Start
> **Auth:** `DefaultAzureCredential` is for local development. See [auth-best-practices.md](../auth-best-practices.md) for production patterns.
```python
from azure.storage.filedatalake import DataLakeServiceClient
from azure.identity import DefaultAzureCredential
service_client = DataLakeServiceClient("https://<account>.dfs.core.windows.net", DefaultAzureCredential())
```
## Best Practices
- Use hierarchical namespace for file system semantics
- Use `append_data` + `flush_data` for large file uploads
- Set ACLs at directory level and inherit to children
- Use async client for high-throughput scenarios
- Use `get_paths` with `recursive=True` for full directory listing
- Set metadata for custom file attributes
- Consider Blob API for simple object storage use cases
## Non-Obvious Patterns
```python
# Large file upload requires append + flush
offset = 0
for chunk in chunks:
file_client.append_data(data=chunk, offset=offset, length=len(chunk))
offset += len(chunk)
file_client.flush_data(offset)
```
references/sdk/azure-storage-file-share-py.md
# File Shares — Python SDK Quick Reference
> Condensed from **azure-storage-file-share-py**. Full patterns (async client,
> snapshots, range operations, copy, SAS tokens)
> in the **azure-storage-file-share-py** plugin skill if installed.
## Install
pip install azure-storage-file-share azure-identity
## Quick Start
> **Auth:** `DefaultAzureCredential` is for local development. See [auth-best-practices.md](../auth-best-practices.md) for production patterns.
```python
from azure.storage.fileshare import ShareServiceClient
from azure.identity import DefaultAzureCredential
service = ShareServiceClient("https://<account>.file.core.windows.net", DefaultAzureCredential())
```
## Best Practices
- Use connection string for simplest setup
- Use Entra ID for production with RBAC
- Stream large files using chunks() to avoid memory issues
- Create snapshots before major changes
- Set quotas to prevent unexpected storage costs
- Use ranges for partial file updates
- Close async clients explicitly
references/sdk/azure-storage-file-share-ts.md
# File Shares — TypeScript SDK Quick Reference
> Condensed from **azure-storage-file-share-ts**. Full patterns (SAS generation,
> snapshots, range operations, streaming, copy operations)
> in the **azure-storage-file-share-ts** plugin skill if installed.
## Install
npm install @azure/storage-file-share @azure/identity
## Quick Start
```typescript
import { ShareServiceClient } from "@azure/storage-file-share";
import { DefaultAzureCredential } from "@azure/identity";
const client = new ShareServiceClient(`https://${accountName}.file.core.windows.net`, new DefaultAzureCredential());
```
## Best Practices
- Use connection strings for simplicity in development
- Use DefaultAzureCredential for **local development only** — in production, use ManagedIdentityCredential. See [auth-best-practices.md](../auth-best-practices.md)
- Set quotas on shares to prevent unexpected storage costs
- Use streaming for large files — `uploadStream`/`downloadToFile` for files > 256MB
- Use ranges for partial updates — more efficient than full file replacement
- Create snapshots before major changes — point-in-time recovery
- Handle errors gracefully — check `RestError.statusCode` for specific handling
- Use `*IfExists` methods for idempotent operations
references/sdk/azure-storage-queue-py.md
# Queue Storage — Python SDK Quick Reference
> Condensed from **azure-storage-queue-py**. Full patterns (async client,
> base64 encoding, queue properties, message updates)
> in the **azure-storage-queue-py** plugin skill if installed.
## Install
pip install azure-storage-queue azure-identity
## Quick Start
> **Auth:** `DefaultAzureCredential` is for local development. See [auth-best-practices.md](../auth-best-practices.md) for production patterns.
```python
from azure.storage.queue import QueueClient
from azure.identity import DefaultAzureCredential
queue_client = QueueClient("https://<account>.queue.core.windows.net", "myqueue", DefaultAzureCredential())
```
## Best Practices
- Delete messages after processing to prevent reprocessing
- Set appropriate visibility timeout based on processing time
- Handle `dequeue_count` for poison message detection
- Use async client for high-throughput scenarios
- Use `peek_messages` for monitoring without affecting queue
- Set `time_to_live` to prevent stale messages
- Consider Service Bus for advanced features (sessions, topics)
references/sdk/azure-storage-queue-ts.md
# Queue Storage — TypeScript SDK Quick Reference
> Condensed from **azure-storage-queue-ts**. Full patterns (SAS generation,
> poison message handling, visibility extension, message encoding)
> in the **azure-storage-queue-ts** plugin skill if installed.
## Install
npm install @azure/storage-queue @azure/identity
## Quick Start
```typescript
import { QueueServiceClient } from "@azure/storage-queue";
import { DefaultAzureCredential } from "@azure/identity";
const client = new QueueServiceClient(`https://${accountName}.queue.core.windows.net`, new DefaultAzureCredential());
```
## Best Practices
- Use DefaultAzureCredential for **local development only** — in production, use ManagedIdentityCredential. See [auth-best-practices.md](../auth-best-practices.md)
- Always delete after processing — prevent duplicate processing
- Handle poison messages — move failed messages to a dead-letter queue
- Use appropriate visibility timeout — set based on expected processing time
- Extend visibility for long tasks — update message to prevent timeout
- Use JSON for structured data — serialize objects to JSON strings
- Check dequeueCount — detect repeatedly failing messages
- Use batch receive — receive multiple messages for efficiency