I have configured Managed Identities for my Web App in App Services and registered this Web App using Azure App Registrations. For development purposes, I want to be able to run this app locally and use the Key Vault secrets.
I Have also created a client secret under the App Registration I have just created. Then I see the three following environment variables using the following IDs:
Env. Variable Description
AZURE_TENANT_ID The Azure Active Directory tenant(directory) ID.
AZURE_CLIENT_ID The client(application) ID of an App Registration in the tenant.
AZURE_CLIENT_SECRET A client secret that was generated for the App Registration.
When I run the Web App locally using VS2022, I get the following error:
Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProviderException: Tried to get token using Visual Studio. Access token could not be acquired. Environment variable LOCALAPPDATA not set.
Why can’t I acquired the token? I tried with the Azure CLI using RunAs=Developer; DeveloperTool=AzureCli
but it’s the same problem. I made sure that I am authenticated by doing an az login
. Here is my code:
Program.cs
#region KeyVault
var keyVaultEndpoint = builder.Configuration.GetSection("KeyVault").GetValue<string>("VaultURI");
if (!string.IsNullOrEmpty(keyVaultEndpoint))
{
var azureServiceTokenProvider = new AzureServiceTokenProvider("RunAs=Developer;DeveloperTool=VisualStudio");
var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
builder.Configuration.AddAzureKeyVault(keyVaultEndpoint, keyVaultClient, new DefaultKeyVaultSecretManager());
}
#endregion KeyVault
3
Answers
The idea is to have a web app running in Azure App Services that is using Managed Identity Service Principal. You must add this service principal in the Access Policies of your Key Vault with Read/Write access for keys and secrets. This service principal will be used by Azure App Services when the web app runs in the cloud. This is great but Managed Identities won't work when the developer is working from localhost. It will give a runtime exception.
This problem is due to the fact that you cannot use Managed Identities while running your code locally. When you run the code locally, you are running the app as yourself, or the user logged-in to Visual Studio. When your code is deployed to App Services using Managed Identity, you are running the app as the Service Principal. See existing post here: Can a "User Assigned Managed Identity" be used locally?
The error message is the following:
ManagedIdentityCredential authentication unavailable. Multiple attempts failed to obtain a token from the managed identity endpoint.
What we need to do is to create an App Registration for storing a client secret. Then we will give it access to our Key Vault using the Access Policies. Our web app running locally will match the locally-stored client secret with the one stored in the App Registration and thus give access to Key Vault with an access token.
To create the registration you can use the Azure CLI command:
Create using a custom display name:
az ad sp create-for-rbac -n MyApp
This will automatically create a client secret for your app registration and return:
Here is the newly created app registration:
Under Certificates and Secrets, here is the client secret:
Now here is the updated code:
So basically you are passing the following parameters to build the connection string for the
AzureServiceTokenProvider
to obtain a token for connecting to the Azure Key Vault:This is the Application (client) ID of the App Registration:
This is the Directory (tenant) ID:
This is the client secret of the App Registration:
Follow these steps to be able to run your web application locally (localhost) using Azure Key Vault
For storing the ClientSecret locally, I strongly suggest that you store it in the
secrets.json
file by right-clicking the Web Project in Visual Studio and selectingManage User Secrets
:That's all!
well, the ‘LOCALAPPDATA’ is a system-defined variable in windows that specifies the path to the directory that contains the user app specific data.
U can set that ‘LOCALAPPDATA’ env variable:
hope this help
You can side-step the issue by running a test double locally.
Please feel free to try Lowkey Vault if interested. You can find a .Net example here.