Applications using managed identity can’t retrieve secrets from Key Vault after we enabled RBAC for the vault. We’re getting Forbidden (403) errors during app startup when trying to access secrets.
Our setup:
- Key Vault originally configured with access policies
- Managed identities had GET secret permissions via access policies
- Recently enabled “Azure role-based access control” in Key Vault settings
- Assigned “Key Vault Secrets User” role to managed identities
Error from application logs:
Azure.RequestFailedException: Forbidden
Status: 403 (Forbidden)
ErrorCode: Forbidden
Operation: GetSecret
I thought RBAC was supposed to replace access policies, but now neither seems to work. The managed identity shows both the access policy AND the RBAC role assignment in the portal. Is there a conflict between the two permission models? Do I need to remove the old access policies after enabling RBAC?
I verified the role assignment - it’s at the Key Vault scope and the object ID matches the managed identity. Used Azure CLI to confirm:
az role assignment list --assignee <managed-identity-object-id> --scope <keyvault-resource-id>
It shows “Key Vault Secrets User” role. But apps still can’t access secrets. Is there a propagation delay for RBAC permissions?
Look at the Key Vault’s “Access configuration” blade carefully. When you enable RBAC, there’s a transition period where you need to migrate all permissions. Did you remove the access policies after enabling RBAC? Sometimes leaving them in place (even though disabled) can cause confusion in how the vault processes requests.
Also, “Key Vault Secrets User” only grants GET permission. If your app tries to LIST secrets, it will fail. You might need “Key Vault Secrets Officer” for broader access.
RBAC propagation is usually under 5 minutes. After 2+ hours it should definitely work. Check your Key Vault’s network settings - even with correct RBAC, firewall rules can block access. Also verify the managed identity is system-assigned or user-assigned, and that you’re using the correct object ID (not the application ID for user-assigned).
When you enable RBAC on a Key Vault, access policies are immediately disabled. The RBAC setting is an either/or choice - you can’t use both simultaneously. Your access policies are no longer being evaluated even though they appear in the portal.
The 403 error means your RBAC role assignment isn’t working correctly. Double-check that you assigned the role at the correct scope and to the right managed identity object ID.
Found the issue! It was a combination of incomplete RBAC transition and managed identity token scope. Here’s what was wrong and how I fixed it:
Root Cause Analysis:
-
Access policy remnants: Even though RBAC was enabled, the old access policies were still visible in the portal and causing confusion. They’re not evaluated, but their presence suggested a hybrid model that doesn’t exist.
-
Insufficient RBAC roles: “Key Vault Secrets User” only grants read access to secret values. Our applications also list secrets and read metadata, which requires “Key Vault Reader” role at the Key Vault scope.
-
Token scope issue: The managed identity was requesting tokens with the wrong scope. For RBAC-enabled vaults, the token scope must be https://vault.azure.net not the Key Vault’s specific URI.
Solution Implementation:
- Clean up access policies (even though they’re disabled):
# Remove all access policies for clarity
az keyvault delete-policy --name mykeyvault \
--object-id <managed-identity-object-id>
- Assign both required RBAC roles:
# Key Vault Reader - for listing and metadata
az role assignment create \
--role "Key Vault Reader" \
--assignee <managed-identity-object-id> \
--scope /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.KeyVault/vaults/mykeyvault
# Key Vault Secrets User - for reading secret values
az role assignment create \
--role "Key Vault Secrets User" \
--assignee <managed-identity-object-id> \
--scope /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.KeyVault/vaults/mykeyvault
- Update application code to use correct token scope:
// OLD (access policy model):
var credential = new DefaultAzureCredential();
var client = new SecretClient(vaultUri, credential);
// NEW (RBAC model - same code, but ensure SDK version >= 4.2):
// SDK automatically uses correct scope for RBAC-enabled vaults
var credential = new DefaultAzureCredential();
var client = new SecretClient(vaultUri, credential);
- Verify RBAC configuration:
# List all role assignments for the managed identity
az role assignment list --all \
--assignee <managed-identity-object-id> \
--query "[?contains(scope, 'Microsoft.KeyVault')]"
Key Vault RBAC Transition Checklist:
-
Understand the permission model change: Access policies and RBAC are mutually exclusive. Enabling RBAC immediately disables all access policies, even though they remain visible in the portal.
-
Role requirements: Most applications need TWO roles:
- “Key Vault Reader”: List keys/secrets/certificates, read metadata
- “Key Vault Secrets User”: Read secret values
- Use “Key Vault Secrets Officer” if the app needs to create/update/delete secrets
-
Managed identity permissions: Assign roles to the managed identity’s Object ID (from Azure AD), not the Application ID. For system-assigned identities, this is the principal ID of the resource. For user-assigned identities, it’s the identity’s own object ID.
-
Access policy deprecation: Microsoft is moving toward RBAC as the recommended model. Access policies still work but are considered legacy. Plan migration carefully:
- Document all current access policies
- Map each policy to equivalent RBAC roles
- Enable RBAC during a maintenance window
- Test thoroughly before removing access policies
-
Network and firewall: RBAC doesn’t change network-level access. Ensure the Key Vault’s firewall rules allow the managed identity’s source (VNet, subnet, or public IP).
Important Differences Between Models:
- Access Policies: Fine-grained permissions (Get, List, Set, Delete individually selectable)
- RBAC: Coarser roles but better integration with Azure governance and easier to audit
- Propagation: RBAC changes propagate within 5 minutes; access policy changes are immediate
- Scope: RBAC supports inheritance (subscription → resource group → vault); access policies are vault-specific only
After implementing these changes, all applications authenticated successfully and could retrieve secrets. The key was understanding that RBAC requires multiple roles for typical application access patterns, not just one role like access policies suggested.
I ran into something similar. When you switch from access policies to RBAC, the Key Vault’s permission model changes at the data plane level. Make sure your application code is using the latest Azure SDK libraries. Older SDK versions might not handle RBAC-enabled vaults correctly.
Also check if you need the “Key Vault Reader” role in addition to “Key Vault Secrets User”. Some operations require both roles.