Setup order matters:
1. Cluster has OIDC issuer enabled: `az aks update -g [rg] -n [cluster] --enable-oidc-issuer`.
2. Create a user-assigned managed identity for the workload.
3. Create a federated identity credential on that identity: issuer = the cluster OIDC URL, subject = `system:serviceaccount:[namespace]:[sa-name]`, audience `api://AzureADTokenExchange`.
4. Annotate the K8s service account: `azure.workload.identity/use: "true"`, and set the pod label `azure.workload.identity/use: "true"`.
5. Grant the managed identity the data-plane role it needs (e.g. Storage Blob Data Contributor).
6. In code, just use DefaultAzureCredential. The workload-identity step in the chain picks up the projected service-account token automatically.
Traps:
- **Subject must match exactly.** `system:serviceaccount:default:my-sa` vs a typo means the token exchange fails with an audience/subject error. Copy the OIDC issuer URL from `az aks show` and the subject from your YAML; do not hand-type either.
- **Label AND annotation.** The pod needs the label `azure.workload.identity/use=true` and the service account needs the annotation. One without the other = no token projected, and DefaultAzureCredential falls through to managed identity (which is not there) and fails.
- **Old clusters.** AAD pod identity is the legacy path; do not mix both on one cluster.
- **Local testing.** Workload identity only works in the cluster. Locally, DefaultAzureCredential falls back to az login, which is the intended dev story; do not bake the federated token into local config.
Verify: exec into the pod, check for AZURE_FEDERATED_TOKEN_FILE env, then run a tiny SDK call (e.g. list blobs) from inside the pod.