skip to Main Content

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.

enter image description here
enter image description here

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


  1. Chosen as BEST ANSWER

    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:

    {
      "clientId": "3f297241-beca-4818-8899-3cd520dd9d6c",
      "clientSecret": "cII8Q~15IOB9mQOpUVnJ-LN5eWIIHEZI3xXRDbwC",
      "subscriptionId": "c6521472-a4ca-4f9a-ae74-97c31bcf2bd6",
      "tenantId": "e50ebc84-76f2-4636-b550-c3f7abc924af",
      "activeDirectoryEndpointUrl": "https://login.microsoftonline.com",
      "resourceManagerEndpointUrl": "https://management.azure.com/",
      "activeDirectoryGraphResourceId": "https://graph.windows.net/",
      "sqlManagementEndpointUrl": "https://management.core.windows.net:8443/",
      "galleryEndpointUrl": "https://gallery.azure.com/",
      "managementEndpointUrl": "https://management.core.windows.net/"
    }
    

    Here is the newly created app registration:

    enter image description here

    Under Certificates and Secrets, here is the client secret:

    enter image description here

    Now here is the updated code:

    #region KeyVault Configuration
    
    var keyVaultEndpoint = builder.Configuration.GetSection("KeyVault").GetValue<string>("VaultURI");
    var clientId = builder.Configuration.GetSection("KeyVault").GetValue<string>("ClientId");
    var tenantId = builder.Configuration.GetSection("KeyVault").GetValue<string>("TenantId");
    var clientSecret = builder.Configuration.GetValue<string>("ClientSecret");
    
    if (!string.IsNullOrEmpty(keyVaultEndpoint))
    {
        var azureServiceTokenProvider = builder.Environment.IsDevelopment() ?
            new AzureServiceTokenProvider($"RunAs=App;AppId={clientId};TenantId={tenantId};AppKey={clientSecret}") : new AzureServiceTokenProvider();
        var keyVault = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
        builder.Configuration.AddAzureKeyVault(keyVaultEndpoint, keyVault, new DefaultKeyVaultSecretManager());
    }
    
    #endregion KeyVault Configuration
    

    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:

    • AppId=3f297241-beca-4818-8899-3cd520dd9d6c

    This is the Directory (tenant) ID:

    • TenantId=e50ebc84-76f2-4636-b550-c3f7abc924af

    This is the client secret of the App Registration:

    • AppKey=cII8Q~15IOB9mQOpUVnJ-LN5eWIIHEZI3xXRDbwC

    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 selecting Manage User Secrets:

    enter image description here

    That's all!


  2. 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:

    1. open the start and search "Environment Variables"
    2. click "Edit the system env variable"
    3. then click "Environment variables" button
    4. in "user var’ section, click ‘New’
    5. enter ‘LOCALAPPDATA’ as the variable name
    6. enter the path to the dir that you want to use

    hope this help

    Login or Signup to reply.
  3. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search