5

Microsoft provides several ways to gain secure access to Azure Key Vault secrets, particularly using Managed Identity or Service Principals as identity providers. However, these methods are explicitly designed to work with Azure-based resources such as web apps and microservices. They do NOT work with UWP/WinUI desktop applications.

The only method I've discovered so far to allow a UWP/WinUI desktop application access to Key Vault is to load the app's Azure registration info (TenentId, ClientId and ClientSecret -- secrets, themselves!) into environment variables that get picked up by the DefaultAzureCredential() method when creating a new SecretClient object (Azure.Security.KeyVault.Secrets).

But that means I'd need to store THESE secrets either in code or in a configuration file to be read in at run-time. Definitely NOT a best practice! I must be missing something.

What are the best practices in 2020 for UWP/WinUI desktop applications to SECURELY access Key Vault secrets -- without exposing other secrets in the process?

FactoryOptimizr
  • 306
  • 3
  • 13
  • The most common method is to force the client to authenticate using AAD and then access KV that way. – MichaelHoward-MSFT Jul 19 '20 at 03:58
  • 1
    @MichaelHoward-MSFT, are you suggesting to have the user log in via AAD, then use their credential info along with the app's client ID to access Key Vault? If so, would this work in a multi-tenant situation where the user's tenant is different than the app's tenant (where the Key Vault resides)? – FactoryOptimizr Jul 20 '20 at 23:28

2 Answers2

1

At the end of the day, your app has to store a secret of SOME sort - as it needs to provide that secret to your Key Vault instance to prove that that app is, indeed, allowed to access the secrets stored in that Vault. It's similar to retrieving a value from a database - you have to store and provide a connection string before you can get values out.

Without knowing the particular use case of how you intend to deploy your application, it's impossible to advise what you should or should not be doing. In our case, we have a WinForms app that's explicitly installed by our support team onto our clients' machines, which means that the old, gold standard of client certificates is what we've been using until now - with a custom verification step, obviously.

Thankfully, Key Vault explicitly supports client certificates (below steps reproduced from linked MSDN):

  1. Create a PKCS#12 archive (.pfx) certificate. Options for creating certificates include MakeCert on Windows and OpenSSL.
  2. Install the certificate into the current user's personal certificate store. Marking the key as exportable is optional. Note the certificate's thumbprint, which is used later in this process.
  3. Export the PKCS#12 archive (.pfx) certificate as a DER-encoded certificate (.cer).
  4. Register the app with Azure AD (App registrations).
  5. Upload the DER-encoded certificate (.cer) to Azure AD:
    a. Select the app in Azure AD.
    b. Navigate to Certificates & secrets.
    c. Select Upload certificate to upload the certificate, which contains the public key. A .cer, .pem, or .crt certificate is acceptable.
  6. Store the key vault name, Application ID, and certificate thumbprint in the app's appsettings.json file.
  7. Navigate to Key vaults in the Azure portal.
  8. Select the key vault that you created in the Secret storage in the Production environment with Azure Key Vault section.
  9. Select Access policies.
  10. Select Add Access Policy.
  11. Open Secret permissions and provide the app with Get and List permissions.
  12. Select Select principal and select the registered app by name. Select the Select button.
  13. Select OK.
  14. Select Save.
  15. Deploy the app.

We're currently replacing our custom client certificate validator with Key Vault, as it's just going to make everything so much easier - managing certificates and revocations from within Azure Portal instead of our custom admin app.

Ian Kemp
  • 28,293
  • 19
  • 112
  • 138
  • Except you can't use a client certificate in a UWP app as it is denied by the Azure.Security.KeyVault.Secrets classes, in particular GetSecret. This doesn't work with mobile (and UWP) and Mac apps (so says the error). – Guy Lowe Mar 17 '22 at 05:21
-1

I'd need to store THESE secrets either in code or in a configuration file to be read in at run-time

You could set Azure registration info (TenentId, ClientId and ClientSecret) into Secret manager and read the value instead of exposing the secrets.

Please refer to the following steps:

1.Enable Security Manager. You need to use init keyword by running on project directory.

dotnet user-secrets init

This will create Guid for UserSecretId in the project .csproj file.

enter image description here

2.Set Secrets. You can set a secrets by using set keywords

dotnet user-secrets set tenantId "xxxxxxxxxxxx"

enter image description here

3.Read from secret manager in code.

private readonly IConfiguration _configuration;

public WeatherForecastController( IConfiguration configuration)
{
    _configuration = configuration;
}
string keyVaultUrl = "https://xxxx.vault.azure.net";
TokenCredential credential = new DefaultAzureCredential();
credential = new ClientSecretCredential(_configuration["tenantId"], _configuration["clientId"], _configuration["clientSecret"]);

var secretClient = new SecretClient(new Uri(keyVaultUrl), credential);
KeyVaultSecret secret = secretClient.GetSecret("xxxx");
var secretvalue = secret.Value;

The working output is as below:

enter image description here

For more details about secret manager, you could refer to this article.

Joey Cai
  • 18,968
  • 1
  • 20
  • 30
  • 1
    Thanks for the info about Secrets Manager, @Joey Cai. However, it only works locally. It's terrific for development but won't work for a desktop app deployed from the Store. – FactoryOptimizr Jul 20 '20 at 23:22
  • No, it seems that for desktop on store, you have to show the tenantid on appsetting.json file. – Joey Cai Jul 21 '20 at 09:35