Authenticate to Azure resources from .NET apps hosted on-premises
Apps hosted outside of Azure (for example on-premises or at a third-party data center) should use an application service principal to authenticate to Azure when accessing Azure resources. Application service principal objects are created using the app registration process in Azure. When an application service principal is created, a client ID and client secret will be generated for your app. The client ID, client secret, and your tenant ID are then stored in environment variables so they can be used by the Azure SDK for .NET to authenticate your app to Azure at runtime.
A different app registration should be created for each environment the app is hosted in. This allows environment specific resource permissions to be configured for each service principal and make sure an app deployed to one environment does not talk to Azure resources that are part of another environment.
1 - Register the application in Azure
An app can be registered with Azure using either the Azure portal or the Azure CLI.
Sign in to the Azure portal and follow these steps.
2 - Assign roles to the application service principal
Next, you need to determine what roles (permissions) your app needs on what resources and assign those roles to your app. Roles can be assigned a role at a resource, resource group, or subscription scope. This example will show how to assign roles for the service principal at the resource group scope since most applications group all their Azure resources into a single resource group.
3 - Configure environment variables for application
The DefaultAzureCredential
object will look for service principal credentials in a set of environment variables at runtime. There are multiple ways to configure environment variables when working with .NET depending on your tooling and environment.
Regardless of which approach you choose, you will need to configure the following environment variables when working with a service principal.
AZURE_CLIENT_ID
→ The app ID value.AZURE_TENANT_ID
→ The tenant ID value.AZURE_CLIENT_SECRET
→ The password/credential generated for the app.
If your app is hosted in IIS it is recommended that you set environment variables per app pool to isolate settings between applications.
appcmd.exe set config -section:system.applicationHost/applicationPools /+"[name='Contoso'].environmentVariables.[name='ASPNETCORE_ENVIRONMENT',value='Production']" /commit:apphost
appcmd.exe set config -section:system.applicationHost/applicationPools /+"[name='Contoso'].environmentVariables.[name='AZURE_CLIENT_ID',value='00000000-0000-0000-0000-000000000000']" /commit:apphost
appcmd.exe set config -section:system.applicationHost/applicationPools /+"[name='Contoso'].environmentVariables.[name='AZURE_TENANT_ID',value='11111111-1111-1111-1111-111111111111']" /commit:apphost
appcmd.exe set config -section:system.applicationHost/applicationPools /+"[name='Contoso'].environmentVariables.[name='AZURE_CLIENT_SECRET',value='=abcdefghijklmnopqrstuvwxyz']" /commit:apphost
You can also configure these settings directly using the applicationPools
element inside of the applicationHost.config
file.
<applicationPools>
<add name="CorePool" managedRuntimeVersion="v4.0" managedPipelineMode="Classic">
<environmentVariables>
<add name="ASPNETCORE_ENVIRONMENT" value="Development" />
<add name="AZURE_CLIENT_ID" value="00000000-0000-0000-0000-000000000000" />
<add name="AZURE_TENANT_ID" value="11111111-1111-1111-1111-111111111111" />
<add name="AZURE_CLIENT_SECRET" value="=abcdefghijklmnopqrstuvwxyz" />
</environmentVariables>
</add>
</applicationPools>
4 - Implement DefaultAzureCredential in application
DefaultAzureCredential
supports multiple authentication methods and determines the authentication method being used at runtime. In this way, your app can use different authentication methods in different environments without implementing environment specific code.
The order and locations in which DefaultAzureCredential
looks for credentials is found at DefaultAzureCredential.
To implement DefaultAzureCredential
, first add the Azure.Identity
and optionally the Microsoft.Extensions.Azure
packages to your application. You can do this using either the command line or the NuGet Package Manager.
Open a terminal environment of your choice in the application project directory and enter the command below.
dotnet add package Azure.Identity
dotnet add package Microsoft.Extensions.Azure
Azure services are generally accessed using corresponding client classes from the SDK. These classes and your own custom services should be registered in the Program.cs
file so they can be accessed via dependency injection throughout your app. Inside of Program.cs
, follow the steps below to correctly setup your service and DefaultAzureCredential
.
- Include the
Azure.Identity
andMicrosoft.Extensions.Azure
namespaces with a using statement. - Register the Azure service using relevant helper methods.
- Pass an instance of the
DefaultAzureCredential
object to theUseCredential
method.
An example of this is shown in the following code segment.
using Microsoft.Extensions.Azure;
using Azure.Identity;
// Inside of Program.cs
builder.Services.AddAzureClients(x =>
{
x.AddBlobServiceClient(new Uri("https://<account-name>.blob.core.windows.net"));
x.UseCredential(new DefaultAzureCredential());
});
Alternatively, you can also utilize DefaultAzureCredential
in your services more directly without the help of additional Azure registration methods, as seen below.
using Azure.Identity;
// Inside of Program.cs
builder.Services.AddSingleton<BlobServiceClient>(x =>
new BlobServiceClient(
new Uri("https://<account-name>.blob.core.windows.net"),
new DefaultAzureCredential()));
When the above code is run on your local workstation during local development, it will look in the environment variables for an application service principal or at Visual Studio, VS Code, the Azure CLI, or Azure PowerShell for a set of developer credentials, either of which 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.
Feedback
Submit and view feedback for