In my work, I still see developers struggling with authentication and authorization, that’s why I want to create some posts to explain how simple this can be in the azure cloud, within the same tenant.

We can use managed identities and they have multiple advantages.

  • no secrets
  • automatic lifecycle management with a system managed identity
  • almost no knowledge needed of Entra ID
  • easy to understand RBAC roles

This post will show, how you can use managed identities to connect to a azure service called key vault from a web app. One of the most basic things most developers will have to deal with.

simple diagram that shows how the web app will communicate with key vault

Before showing the code, I want to give a shout out to the public bicep repository, this repo is perfect for learning bicep and quickly implementing IaC.

When creating the infra, we need 3 modules:
Optional: Create a user managed identity that will get the role assignments

module managedIdentity 'br/public:avm/res/managed-identity/user-assigned-identity:0.4.0' = {
  name: 'name'
  params: {
    ...
  }
}

Create the key vault

module vault 'br/public:avm/res/key-vault/vault:0.12.1' = {
  name: 'name'
  params: {
    roleAssignments: [
      { // Give managed identity a role to read the secrets
        principalId: managedIdentity.outputs.principalId
        principalType: 'ServicePrincipal'
        roleDefinitionIdOrName: 'Key Vault Secrets User'
      }
    ]
    ...
  }
}

Create a webapp

module App 'br/public:avm/res/web/site:0.15.1' = {
  name: 'name'
  params: {
    kind: 'app'
    managedIdentities: { //assigning a managed identity to the web app to access the key vault secrets
      systemAssigned: false //set to true and remove line below if you only want this
      userAssignedResourceIds: [managedIdentity.outputs.resourceId]
    }
    ...
  }
}

And a simple implementation within the .net web app

using Azure.Identity;

var credentials = new ChainedTokenCredential(!builder.Environment.IsDevelopment() 
    ? new ManagedIdentityCredential(userManagedIdentityClientId) 
    : new VisualStudioCredential(), new AzureCliCredential(), new InteractiveBrowserCredential());

builder.Configuration.AddAzureKeyVault(new Uri($"https://{builder.Configuration["KeyVaultName"]}.vault.azure.net/"), credentials);

After this, you only need to deploy the infra and your web app and everything should work in the cloud!

For testing locally, you need to add an extra role assignment to the keyvault, for your personal identity or a group that you are in.

The bicep for keyvault would look something like this

module vault 'br/public:avm/res/key-vault/vault:0.12.1' = {
  name: 'name'
  params: {
    roleAssignments: [
      { // Give managed identity a role to read the secrets
        principalId: managedIdentity.outputs.principalId
        principalType: 'ServicePrincipal'
        roleDefinitionIdOrName: 'Key Vault Secrets User'
      }
      { // Give dev group a role to read the secrets for local testing
        principalId: 'GUID'
        principalType: 'Group'
        roleDefinitionIdOrName: 'Key Vault Secrets User'
      }
    ]
    ...
  }
}

I hope this helps my fellow developers to easily use azure resources in your applications in a safe way.