Introduction

Azure Key Vault uses either Access Policies or Azure RBAC to control access to secrets. A 403 Forbidden error from the SecretClient means the authenticated identity does not have the required permissions. This is a common issue when deploying to Azure App Service, AKS, or Azure Functions where managed identity setup is complex and permissions must be explicitly granted.

Symptoms

  • Azure.RequestFailedException: Status 403 (Forbidden)
  • Access denied when calling client.GetSecretAsync()
  • Works locally with Azure CLI credentials but fails in Azure
  • DefaultAzureCredential authenticates but Key Vault rejects
  • Error: The user, group or application does not have secrets get permission

Example error: ``` Azure.RequestFailedException: Forbidden Status: 403 (Forbidden) ErrorCode: Forbidden

Content: {"error":{"code":"Forbidden","message":"Access denied.\r\nCaller is not authorized to perform action on resource.\r\nIf role assignments, deny assignments or role definitions were changed recently, please observe propagation time."}} ```

Common Causes

  • Managed identity not enabled on the Azure resource
  • Access policy or RBAC role not assigned to the identity
  • Wrong Key Vault permission model (Access Policy vs Azure RBAC)
  • Managed identity object ID changed after recreation
  • Tenant ID mismatch in DefaultAzureCredential

Step-by-Step Fix

  1. 1.Verify the identity being used:
  2. 2.```csharp
  3. 3.// Add this to diagnose which credential is being used
  4. 4.var credential = new DefaultAzureCredential(
  5. 5.new DefaultAzureCredentialOptions
  6. 6.{
  7. 7.Diagnostics =
  8. 8.{
  9. 9.IsAccountIdentifierLoggingEnabled = true,
  10. 10.IsLoggingContentEnabled = true
  11. 11.}
  12. 12.});

var token = await credential.GetTokenAsync( new TokenRequestContext(new[] { "https://vault.azure.net/.default" }));

Console.WriteLine($"Using token from: {token}"); Console.WriteLine($"Token expires: {token.ExpiresOn}"); ```

  1. 1.Grant access via Azure CLI:
  2. 2.```bash
  3. 3.# Get the managed identity principal ID
  4. 4.az webapp identity show --resource-group MyResourceGroup --name MyAppName
  5. 5.# Output: { "principalId": "abc123-def456-..." }

# Grant Key Vault Secrets User role (RBAC model) az role assignment create \ --role "Key Vault Secrets User" \ --assignee "abc123-def456-..." \ --scope "/subscriptions/{sub-id}/resourceGroups/{rg}/providers/Microsoft.KeyVault/vaults/{vault-name}"

# Or for Access Policy model: az keyvault set-policy \ --name my-keyvault \ --object-id "abc123-def456-..." \ --secret-permissions get list ```

  1. 1.Configure DefaultAzureCredential correctly:
  2. 2.```csharp
  3. 3.var credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions
  4. 4.{
  5. 5.// Specify the managed identity client ID if using user-assigned identity
  6. 6.ManagedIdentityClientId = builder.Configuration["Azure:ManagedIdentityClientId"],

// Specify the tenant ID VisualStudioTenantId = builder.Configuration["Azure:TenantId"], VisualStudioCodeTenantId = builder.Configuration["Azure:TenantId"],

// Exclude credential types you do not use ExcludeEnvironmentCredential = true, ExcludeWorkloadIdentityCredential = true, ExcludeInteractiveBrowserCredential = true, });

var client = new SecretClient( new Uri($"https://{vaultName}.vault.azure.net/"), credential);

var secret = await client.GetSecretAsync("MySecretName"); ```

  1. 1.Use Azure Key Vault configuration provider:
  2. 2.```csharp
  3. 3.builder.Configuration.AddAzureKeyVault(
  4. 4.new Uri($"https://{vaultName}.vault.azure.net/"),
  5. 5.new DefaultAzureCredential());

// Access secrets like regular configuration var connectionString = builder.Configuration["DatabaseConnectionString"]; ```

Prevention

  • Use Azure RBAC (Key Vault Secrets User) instead of Access Policies for new vaults
  • Add the identity assignment to your Infrastructure as Code (Bicep/Terraform)
  • Test locally with az login before deploying
  • Use az keyvault show to verify the permission model in use
  • Add startup health check that verifies Key Vault access
  • Monitor 403 errors in Azure Monitor for early detection of permission issues