---
cuppy_hub: azure
cuppy_path: patterns/app-to-keyvault-with-managed-identity.md
cuppy_section: docs
cuppy_doc: A70E-F5FJ
cuppy_doc_uuid: 502544a1-6f03-4e60-8290-fa60d2c96bcb
cuppy_permalink: https://cuppy.io/azure/d/A70E-F5FJ
cuppy_version: 1
cuppy_updated: 2026-10-23T16:16:52.575Z
cuppy_canonical: https://cuppy.io/azure/docs/patterns/app-to-keyvault-with-managed-identity
cuppy_mcp: https://cuppy.io/mcp
cuppy_body_sha256: 0407bb0a14ed89c06b212782cca76049631046a8987865fa437345b845649596
# cuppy_body_sha256 is over the document body ALONE, excluding both generated blocks.
---


# App to Key Vault with a managed identity

**App side:** the app runs as a managed identity and asks for a token for `https://vault.azure.net`. **Vault side:** the vault's network lets the app in, and its permission model grants that identity the secret. Each failure below is one of those.

## Known-good

- A user-assigned identity `id-orders`, attached to the app. Its client ID is in the app setting `APP_IDENTITY_CLIENT_ID`.
- The vault is created with `enableRbacAuthorization: true` written in the template (API version 2026-02-01 or later), soft delete on (always), and purge protection on for production.
- **Key Vault Secrets User** assigned to the identity's `principalId`, scoped to the vault, with `principalType: ServicePrincipal` and a `guid()` name.
- Network: public access disabled and a private endpoint in the app's integrated VNet, or the vault firewall allowing the app's outbound IPs.
- Code: `new SecretClient("https://<vault>.vault.azure.net", new ManagedIdentityCredential({ clientId }))`, with the secret cached in memory rather than fetched per request.

Setting up the identity and the role: `guides/managed-identity/use-managed-identity.md` and `guides/rbac/assign-roles.md`.

## Known-bad

| Configuration | Symptom |
|---|---|
| Identity holds Contributor (or Owner) on the vault, no data role | 403 `Caller is not authorized to perform action on resource.` (`ForbiddenByRbac`) |
| Template on an API version before 2026-02-01 with no `enableRbacAuthorization`; role assignments deployed | Access-policy vault: role assignments are ignored, 403 `… does not have secrets get permission …` |
| Template moved to 2026-02-01 while still relying on `accessPolicies` (property omitted) | New vaults are RBAC: the access policies are ignored, 403 `ForbiddenByRbac` |
| Role granted to the identity's **group**, not the identity | 403 for hours after the change (managed identity token cache, about 24 h) |
| Two user-assigned identities on the app; code uses `DefaultAzureCredential` without a client ID | Token for the wrong identity, or none; 403 or `ManagedIdentityCredential: Authentication failed` |
| Vault firewall on, `bypass: AzureServices`, no IP rule or private endpoint | 403 `Client address (<ip>) is not authorized and caller is not a trusted service` (App Service isn't a trusted service) |
| App calls the vault per request at high volume | 429 throttling |
| Vault deleted in a test teardown and re-created with the same name | Create fails on the name until `az keyvault purge` or retention ends |

## Which side is wrong

- **No token** (`ManagedIdentityCredential…`, IMDS or `IDENTITY_ENDPOINT` errors) → the app side: is the identity attached, and is the right client ID passed? (`reference/managed-identity/errors.md`)
- **403 naming the client IP** → the vault's network rules.
- **403 `ForbiddenByRbac`** → the role: missing, on a group, or not propagated yet.
- **403 about access-policy permissions** → the vault is in access-policy mode: switch it, or add a policy.
- **401** → the token's audience isn't `https://vault.azure.net`. Custom HTTP code is asking for the wrong scope.

`az keyvault show -n <vault> --query "properties.{rbac:enableRbacAuthorization, network:networkAcls, public:publicNetworkAccess}"` answers the vault-side questions in one call.


---
<!-- cuppy -->
You are reading one file. The same content is free over MCP at https://cuppy.io/mcp with no signup: ranked search across all 107 documents in this hub, the merged view when you work in a layer, known workarounds matched to the error you hit, and depth control so you spend tokens on what you need. Start with the `_hello` tool. How to connect: https://cuppy.io/azure/ Something wrong in this document? Report it with the `session feedback` tool on the same endpoint.
<!-- /cuppy -->
