---
cuppy_hub: azure
cuppy_path: reference/keyvault/access-and-errors.md
cuppy_section: docs
cuppy_doc: 94B6-102S
cuppy_doc_uuid: 144e095e-c9c8-44bc-9283-cb8c8d8555f1
cuppy_permalink: https://cuppy.io/azure/d/94B6-102S
cuppy_version: 1
cuppy_updated: 2026-10-23T16:16:52.575Z
cuppy_canonical: https://cuppy.io/azure/docs/reference/keyvault/access-and-errors
cuppy_mcp: https://cuppy.io/mcp
cuppy_body_sha256: 478351f7651787d729e92f65a03a3b45f0d852a32442d94c5d0055a64132d5e6
# cuppy_body_sha256 is over the document body ALONE, excluding both generated blocks.
---


# Key Vault access — permission models, network, soft delete and errors

**A Key Vault request passes three gates: a valid token for `https://vault.azure.net`, the vault's network rules, and the vault's permission model.** The permission model is either **Azure RBAC** (role assignments, the default for new vaults) or legacy **access policies** (set on the vault). A vault uses exactly one: when RBAC is on, access policies are ignored.

## The 2026 default flip

- **API version 2026-02-01 and later:** `enableRbacAuthorization` defaults to **true**. In 2025-05-01 and earlier it defaulted to **false**. `az keyvault create` (CLI 2.91) also enables RBAC by default.
- The default applies to **create** only. Existing vaults keep their model when updated with a newer API version; vaults with `enableRbacAuthorization: null` (made with older versions) keep using access policies.
- So a Bicep or ARM template **pinned to an older API version creates an access-policy vault**, and the same template moved to 2026-02-01 creates an RBAC vault whose `accessPolicies` are ignored. **Set `enableRbacAuthorization` explicitly** in every template.
- **All Key Vault control-plane API versions before 2026-02-01 retire on February 27, 2027**, after which their use is suspended. Move templates and tools now: Azure CLI 2.90.0+, Azure PowerShell 16.3.0+.
- **The creator of an RBAC vault has no data access.** Creating it needs control-plane rights only. Reading or writing secrets afterwards needs a data role, for example Key Vault Secrets Officer for yourself. The CLI only adds default permissions for the creator when RBAC is set to false.

## Roles (RBAC vaults)

| Need | Role |
|---|---|
| Read secret values (apps) | Key Vault Secrets User |
| Manage secrets (pipelines, people) | Key Vault Secrets Officer |
| Everything in the data plane | Key Vault Administrator |
| Use keys for crypto | Key Vault Crypto User (Crypto Officer to manage) |
| Certificates | Key Vault Certificates Officer / Certificate User |
| Read metadata only | Key Vault Reader |
| Manage the vault resource | Key Vault Contributor: **control plane only** |

**On an access-policy vault, Contributor is enough to grant yourself data access** (by writing an access policy). One more reason to use RBAC.

## Errors

| Status / message | Cause → fix | Check |
|---|---|---|
| 401 | No `Authorization` header, an expired token, or a token for another audience. The scope is `https://vault.azure.net/.default`. (One Microsoft page says `vault.keyvault.net`; its own examples and the SDK use `vault.azure.net`.) | Decode the token: `aud` must be `https://vault.azure.net` |
| 403 `Caller is not authorized to perform action on resource.` with inner error `ForbiddenByRbac` | RBAC vault, and the caller has no data role at the vault (or above) | `az role assignment list --assignee <object-id> --scope $(az keyvault show -n <kv> --query id -o tsv) --include-inherited` |
| 403 `The user, group or application '…' does not have secrets get permission on key vault '…'` (field wording) | Access-policy vault without a policy for this object ID. Often the app runs as a **different** identity than the one in the policy | `az keyvault show -n <kv> --query "properties.accessPolicies[].objectId"` vs the caller's object ID |
| 403 `Client address (<ip>) is not authorized and caller is not a trusted service` | The vault firewall blocks the caller. App Service is **not** a trusted service: add its outbound IPs or a private endpoint | `az keyvault network-rule list -n <kv>`; `az keyvault show -n <kv> --query properties.networkAcls` |
| 403 right after adding the policy or role | Propagation: allow several minutes and retry; managed identities in Entra **groups** can take hours | Retry later |
| Access policy shows **Unknown Policy** | The principal was deleted, or the policy was added with the *application* object ID instead of the service principal's | `az ad sp show --id <id>` |
| 429 | Throttled. Cache secrets in the app, back off exponentially, and spread load across vaults. Read the limits on the Key Vault service limits page | Request rate in your logs |
| Vault name conflicts on create | A **soft-deleted** vault with that name still exists. Recover it (`az keyvault recover --name <kv>`) or, without purge protection, purge it (`az keyvault purge --name <kv>`) | `az keyvault list-deleted` |
| Secret name conflicts on set | A deleted secret with that name is in the recoverable state | `az keyvault secret` `list-deleted --vault-name <kv>`, then `az keyvault secret recover` or `purge` |
| Purge refused | Purge protection is on: nothing can be purged until the retention period ends | `az keyvault show -n <kv> --query properties.enablePurgeProtection` |

## Soft delete and purge protection

Soft delete is on for every new vault and can't be turned off. Retention is 7–90 days (default 90) and is fixed at creation. Purge protection is off by default; once on, deleted vaults and objects can't be purged before retention ends. Plan names accordingly: a vault deleted in a test teardown blocks its name until purged or expired.

## When none of these fits

Check the three gates in order: the token's `aud` and identity, then `networkAcls` and private endpoints (networking family), then `enableRbacAuthorization` and the matching role or policy. To switch an access-policy vault to RBAC, `az keyvault update -n <kv> --enable-rbac-authorization true` needs `Microsoft.Authorization/roleAssignments/write` and `Microsoft.KeyVault/vaults/write`. Create every role assignment **first** (Microsoft's migration order): once RBAC is on, access policies are ignored.

To see who read or changed secrets, send the vault's `AuditEvent` logs to a workspace with a diagnostic setting: `reference/monitor/diagnostic-settings-and-data-collection.md`.


---
<!-- 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 -->
