How to authenticate .NET apps to Azure services using the Azure Identity library
When an app needs to access an Azure resource, the app must be authenticated to Azure. This is true for all apps, whether deployed to Azure, deployed on-premises, or under development on a local developer workstation. This article describes the recommended approaches to authenticate an app to Azure when using the Azure SDK client libraries.
Recommended app authentication approach
It's recommended that apps use token-based authentication rather than connection strings when authenticating to Azure resources. The Azure Identity library provides classes that support token-based authentication and allow apps to seamlessly authenticate to Azure resources whether the app is in local development, deployed to Azure, or deployed to an on-premises server.
The specific type of token-based authentication an app should use to authenticate to Azure resources depends on where the app runs and is shown in the following diagram:
When an app is:
- Running locally during development, the app can authenticate to Azure using either an application service principal for local development or by using the developer's Azure credentials. Each option is discussed in more detail at authentication during local development.
- Hosted on Azure, the app should authenticate to Azure resources using a managed identity. This option is discussed in more detail at authentication in server environments.
- Hosted and deployed on-premises, the app should authenticate to Azure resources using an application service principal. This option is discussed in more detail at authentication in server environments.
DefaultAzureCredential
The DefaultAzureCredential class provided by the Azure Identity library allows apps to use different authentication methods depending on the environment in which they're run. This allows apps to be promoted from local development to test environments to production without code changes. You configure the appropriate authentication method for each environment, and DefaultAzureCredential
will automatically detect and use that authentication method. The use of DefaultAzureCredential
should be preferred over manually coding conditional logic or feature flags to use different authentication methods in different environments.
Details about using DefaultAzureCredential
are covered at Use DefaultAzureCredential
in an application.
Advantages of token-based authentication
Token-based authentication offers the following advantages over authenticating with connection strings:
- The token-based authentication methods described below allows you to establish the specific permissions needed by the app on the Azure resource. This follows the principle of least privilege. In contrast, a connection string grants full rights to the Azure resource.
- Whereas anyone or any app with a connection string can connect to an Azure resource, token-based authentication methods scope access to the resource to only the app(s) intended to access the resource.
- In the case of a managed identity, there's no application secret to store. This makes the app more secure because there's no connection string or application secret that can be compromised.
- The Azure.Identity package acquires and manages Microsoft Entra tokens for you. This makes using token-based authentication as easy to use as a connection string.
Use of connection strings should be limited to initial proof-of-concept apps or development prototypes that don't access production or sensitive data. Otherwise, the token-based authentication classes available in the Azure Identity library should always be preferred when authenticating to Azure resources.
Authentication in server environments
When hosting in a server environment, each app should be assigned a unique application identity per environment in which the app is run. In Azure, an application identity is represented by a service principal, a special type of security principal intended to identify and authenticate apps to Azure. The type of service principal to use for your app depends on where your app is running.
Authentication method | Description |
---|---|
Apps hosted in Azure | Apps hosted in Azure should use a Managed Identity service principal. Managed identities are designed to represent the identity of an app hosted in Azure and can only be used with Azure hosted apps. For example, a .NET web app hosted in Azure App Service would be assigned a Managed Identity. The Managed Identity assigned to the app would then be used to authenticate the app to other Azure services. |
Apps hosted outside of Azure (for example, on-premises apps) |
Apps hosted outside of Azure (for example on-premises apps) that need to connect to Azure services should use an Application service principal. An Application service principal represents the identity of the app in Azure and is created through the application registration process. For example, consider a .NET web app hosted on-premises that makes use of Azure Blob Storage. You would create an Application service principal for the app using the App registration process. The AZURE_CLIENT_ID , AZURE_TENANT_ID , and AZURE_CLIENT_SECRET would all be stored as environment variables to be read by the application at runtime and allow the app to authenticate to Azure using the Application service principal. |
Authentication during local development
When an app is run on a developer's workstation during local development, it must still authenticate to any Azure services used by the app. The two main strategies for authenticating apps to Azure during local development are:
Authentication method | Description |
---|---|
Create dedicated application service principal objects to be used during local development | In this method, dedicated application service principal objects are set up using the App registration process for use during local development. The identity of the service principal is then stored as environment variables to be accessed by the app when it is run in local development. This method allows you to assign the specific resource permissions needed by the app to the service principal objects used by developers during local development. This makes sure the application only has access to the specific resources it needs and replicates the permissions the app will have in production. The downside of this approach is the need to create separate service principal objects for each developer that works on an application. |
Authenticate the app to Azure using the developer's credentials during local development | In this method, a developer must be signed in to Azure from either Visual Studio, the Azure Tools extension for VS Code, the Azure CLI, or Azure PowerShell on their local workstation. The application can then access the developer's credentials from the credential store and use those credentials to access Azure resources from the app. This method has the advantage of easier setup since a developer only needs to log in to their Azure account from Visual Studio, VS Code, or the Azure CLI. The disadvantage of this approach is that the developer's account likely has more permissions than required by the application. Therefore, this approach doesn't accurately replicate the permissions the app will run with in production. |
Use DefaultAzureCredential in an application
DefaultAzureCredential is an opinionated, ordered sequence of mechanisms for authenticating to Microsoft Entra ID. Each authentication mechanism is a class derived from the TokenCredential class and is known as a credential. At runtime, DefaultAzureCredential
attempts to authenticate using the first credential. If that credential fails to acquire an access token, the next credential in the sequence is attempted, and so on, until an access token is successfully obtained. In this way, your app can use different credentials in different environments without writing environment-specific code.
To use DefaultAzureCredential
, add the Azure.Identity and optionally the Microsoft.Extensions.Azure packages to your application:
In a terminal of your choice, navigate to the application project directory and run the following commands:
dotnet add package Azure.Identity
dotnet add package Microsoft.Extensions.Azure
Azure services are accessed using specialized client classes from the various Azure SDK client libraries. These classes and your own custom services should be registered so they can be accessed via dependency injection throughout your app. In Program.cs
, complete the following steps to register a client class and DefaultAzureCredential
:
- Include the
Azure.Identity
andMicrosoft.Extensions.Azure
namespaces viausing
directives. - Register the Azure service client using the corresponding
Add
-prefixed extension method. - Pass an instance of
DefaultAzureCredential
to theUseCredential
method.
For example:
using Microsoft.Extensions.Azure;
using Azure.Identity;
builder.Services.AddAzureClients(clientBuilder =>
{
clientBuilder.AddBlobServiceClient(
new Uri("https://<account-name>.blob.core.windows.net"));
clientBuilder.UseCredential(new DefaultAzureCredential());
});
An alternative to UseCredential
is to instantiate DefaultAzureCredential
directly:
using Azure.Identity;
builder.Services.AddSingleton<BlobServiceClient>(_ =>
new BlobServiceClient(
new Uri("https://<account-name>.blob.core.windows.net"),
new DefaultAzureCredential()));
When the preceding code runs on your local development workstation, it looks in the environment variables for an application service principal or at locally installed developer tools, such as Visual Studio, for a set of developer credentials. Either approach can be used to authenticate the app to Azure resources during local development.
When deployed to Azure, this same code can also authenticate your app to other Azure resources. DefaultAzureCredential
can retrieve environment settings and managed identity configurations to authenticate to other services automatically.