Key Vault access — permission models, network, soft delete and errors
Why a Key Vault call is refused and how to fix it — Azure RBAC vs legacy access policies, the 2026-02-01 default flip and the February 27, 2027 retirement of older control-plane API versions, data roles, why the creator of a new vault can't read it, the token audience, firewall and trusted services, 429 throttling, soft delete and purge protection name conflicts — each error with cause, check and fix.
markdownreferencev194B6-102Sstage: operatetrust: officialtrust: fieldservice: keyvaultinterface: anyKey Vault 403ForbiddenByRbacCaller is not authorized to perform action on resourcedoes not have secrets get permissionClient address is not authorized and caller is not a trusted serviceKey Vault 401Key Vault 429enableRbacAuthorization default 2026-02-01access policy vs RBACKey Vault Secrets UserKey Vault AdministratorKey Vault Contributoraz keyvault create rbac defaultsoft deletepurge protectionvault name in deleted stateaz keyvault purgeaz keyvault recoverUnknown Policyhttps://vault.azure.net/.default
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:
enableRbacAuthorizationdefaults 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
accessPoliciesare ignored. SetenableRbacAuthorizationexplicitly 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.