We will create an instance of the Azure Key vault. As the second step, we insert the value `supersecurevalue` as a secret with the key `mylittlesecret`. This all is done with the help of Azure CLI.
- az keyvault create --location westeurope --name azureidentityvault --resource-group identitytest
- az keyvault secret set --name mylittlesecret --value supersecurevalue --vault-name azureidentityvault
DefaultAzureCredential
There are various identities we want to use for our application during different stages of the development cycle. For example, one for development, one for integration testing, and one for production. For sure we don’t want to have a separate code section for each environment. Azure.Identity NuGet package makes retrieving identity unified. The following example retrieves our secret from the created Key vault (uses C# 9 and top-level statements).
- using System;
- using Azure.Identity;
- using Azure.Security.KeyVault.Secrets;
-
- const string keyvaultName = "azureidentityvault";
- const string secretKey = "mylittlesecret";
-
- var credential = new DefaultAzureCredential();
-
- var client = new SecretClient(new Uri($"https://{keyvaultName}.vault.azure.net/"), credential);
- KeyVaultSecret secret = client.GetSecret(secretKey);
- Console.WriteLine(secret.Value);
DefaultAzureCredential combines some classes, that are used to retrieve AAD identity. It tries to initialize them one by one (in this order). The first successfully initialized credential is used:
- EnvironmentCredential
- ManagedIdentityCredential
- SharedTokenCacheCredential
- VisualStudioCredential
- VisualStudioCodeCredential
- AzureCliCredential
- InteractiveBrowserCredential
When your application runs in a production environment your identity will be probably retrieved with one of first three classes. When you debug your application locally, on the other hand, managed identity or environment variables could not be available. We will talk about each of these types of credentials from bottom to the top in the following sections.
InteractiveBrowserCredential
This type of credentials opens the default browser and lets the user do an interactive sign in. If you enter the credentials of the account that created the key vault, you should see the secret. Retrieve credentials using this code:
- var credential = new InteractiveBrowserCredential();
Keep in mind, that DefaultAzureCredential excludes interactive login by default. If you want to use it, you have to initialize it with the includeInteractiveCredentials option set to true.
- var credential = new DefaultAzureCredential(includeInteractiveCredentials: true);
AzureCliCredential
- var credential = new AzureCliCredential();
If you are in the terminal environment, you can log to Azure CLI using the az login command. An application running in the same terminal will use the identity provided during login.
VisualStudioCodeCredential
- var credential = new new VisualStudioCodeCredential();
Azure Visual studio extensions required you to be logged in to show your Azure resources. You need an Azure account extension for this purpose. It providers various commands on how to perform sign-in. Just hit F1 and start typing "Azure Sign In". VisualStudioCodeCredential takes this identity and uses it for the identity of our application during runtime.
VisualStudioCredential
- var credential = new new VisualStudioCredential();
This option is very similar to the previous one. It differs only in the IDE and the way of providing credentials to it. In the "big" Visual studio you find the login form in Tools > Options > Azure service authentication.
SharedTokenCacheCredential
- var credential = new new SharedTokenCacheCredential();
Many Microsoft applications use Azure single sign-on. This class uses identity, that was already stored in the local cache by one of them.
ManagedIdentityCredential
- var credential = new ManagedIdentityCredential();
Managed identity is a great way how to secure your service in production. The application will receive an identity managed by Azure itself. You do not even have access to credentials.
In this case, administrators can use role-based access control to set up permissions for other resources.
We can demonstrate this by creating a simple HTTP-based Azure function. First, create storage and the function app itself.
- az storage account create --name identityfunctionstorage --resource-group identitytest
- az functionapp create --name identityfunctiondemo --resource-group identitytest --storage-account identityfunctionstorage --consumption-plan-location westeurope
Then we command Azure to assign managed identity for our Azure function (response is just for illustration).
- az functionapp identity assign --name identityfunctiondemo --resource-group mirotest
-
- {
- "principalId": "3fedf722-7c5d-426f-9d35-d985d3eb59bc",
- "tenantId": "8d099a24-312e-4bb5-8fe4-aed67b7c4921",
- "type": "SystemAssigned",
- "userAssignedIdentities": null
- }
Our application now has Azure identity with ID
3fedf722-7c5d-426f-9d35-d985d3eb59bc. The last configuration step is to add permission for our newly created application to be able to retrieve secrets from our Key vault.
- az keyvault set-policy --name azureidentityvault --object-id 3fedf722-7c5d-426f-9d35-d985d3eb59bc --secret-permission get
The code of the function app is in folder Azure.Identity.Demo.Function of this repository. After successful deployment, you will see the Invoke URL. Enter it in the browser and you will see the value of the secret as a response.
cd Azure.Identity.Demo.Fumction
- func azure functionapp publish identityfunctiondemo
-
- Microsoft (R) Build Engine version 16.8.0+126527ff1 for .NET
- Copyright (C) Microsoft Corporation. All rights reserved.
-
- Determining projects to restore...
- All projects are up-to-date for restore.
- Azure_Identity_Demo_Function -> D:\working\Azure.Identity.Demo.Function\bin\publish\bin\Azure_Identity_Demo_Function.dll
-
- Build succeeded.
- 0 Warning(s)
- 0 Error(s)
-
- Time Elapsed 00:00:02.22
-
-
- Getting site publishing info...
- Creating archive for current directory...
- Uploading 4,06 MB [###############################################################################]
- Upload completed successfully.
- Deployment completed successfully.
- Syncing triggers...
- Functions in identityfunctiondemo:
- IdentityHttpFunction - [httpTrigger]
- Invoke url: https:
EnvironmentCredential
- var credential = new EnvironmentCredential();
The most universal way of providing an Azure identity for your application is to use system environment variables. You can configure them in your virtual machine, in your build server, in your cloud hosting, pass them into your docker image, and many other places. You can choose between using a regular user account or an application credential secured by a secret or certificate.
- 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.
- AZURE_CLIENT_CERTIFICATE_PATH - A path to the certificate and private key pair in PEM or PFX format, which can authenticate the App Registration.
- AZURE_USERNAME - The username, also known as upn, of an Azure Active Directory user account.
- AZURE_PASSWORD - The password of the Azure Active Directory user account. Note this does not support accounts with MFA enabled.
Conclusion
DefaultAzureCredential class makes the everyday life of developers much easier. By typing a single line of code, we can provide a unified solution for providing identity. It adapts well to various environments starting from local debugging in IDE, continuing with build runners, and ending up in production cloud hosting.