Use managed identities for App Service and Azure Functions

This article shows you how to create a managed identity for Azure App Service and Azure Functions applications, and how to use it to access other resources.

Note

Starting June 1, 2024, newly created App Service apps can generate a unique default hostname that uses the naming convention <app-name>-<random-hash>.<region>.chinacloudsites.cn. Existing app names remain unchanged. For example:

myapp-ds27dh7271aah175.chinanorth3-01.chinacloudsites.cn

A managed identity from Azure Active Directory (Azure AD) allows your app to easily access other Azure AD-protected resources such as Azure Key Vault. The identity is managed by the Azure platform and does not require you to provision or rotate any secrets. For more about managed identities in Azure AD, see Managed identities for Azure resources.

Your application can be granted two types of identities:

  • A system-assigned identity is tied to your application and is deleted if your app is deleted. An app can only have one system-assigned identity.
  • A user-assigned identity is a standalone Azure resource that can be assigned to your app. An app can have multiple user-assigned identities.

The managed identity configuration is specific to the slot. To configure a managed identity for a deployment slot in the portal, go to the slot first. To find the managed identity for your web app or deployment slot in your Microsoft Entra tenant from the Azure portal, search for it directly from the Overview page of your tenant. Usually, the slot name is similar to <app-name>/slots/<slot-name>.

Prerequisites

To perform the steps in this article, you must have a minimum set of permissions over your Azure resources. The specific permissions that you need vary based on your scenario. The following table summarizes the most common scenarios:

Scenario Required permission Example built-in roles
Create a system-assigned identity Microsoft.Web/sites/write over the app, or Microsoft.Web/sites/slots/write over the slot Website Contributor
Create a user-assigned identity Microsoft.ManagedIdentity/userAssignedIdentities/write over the resource group in which to create the identity Managed Identity Contributor
Assign a user-assigned identity to your app Microsoft.Web/sites/write over the app, Microsoft.Web/sites/slots/write over the slot, or
Microsoft.ManagedIdentity/userAssignedIdentities/*/assign/action over the identity
Website Contributor and Managed Identity Operator
Create Azure role assignments Microsoft.Authorization/roleAssignments/write over the target resource scope Role Based Access Control Administrator or User Access Administrator

Add a system-assigned identity

To enable a system-assigned managed identity, use the following instructions.

You can use an Azure Resource Manager template to automate deployment of your Azure resources. To learn more, see Automate resource deployment in App Service and Automate resource deployment in Azure Functions.

You can create any resource of type Microsoft.Web/sites with an identity by including the following property in the resource definition:

"identity": {
    "type": "SystemAssigned"
}

Adding the system-assigned type tells Azure to create and manage the identity for your application.

For example, a web app's template might look like the following JSON:

{
    "apiVersion": "2022-03-01",
    "type": "Microsoft.Web/sites",
    "name": "[variables('appName')]",
    "location": "[resourceGroup().location]",
    "identity": {
        "type": "SystemAssigned"
    },
    "properties": {
        "name": "[variables('appName')]",
        "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
        "hostingEnvironment": "",
        "clientAffinityEnabled": false,
        "alwaysOn": true
    },
    "dependsOn": [
        "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]"
    ]
}

When the site is created, it includes the following properties:

"identity": {
    "type": "SystemAssigned",
    "tenantId": "<tenant-id>",
    "principalId": "<principal-id>"
}

The tenantId property identifies what Microsoft Entra tenant the identity belongs to. The principalId property is a unique identifier for the application's new identity. In Microsoft Entra ID, the service principal has the same name that you gave to your App Service or Azure Functions instance.

If you need to refer to these properties in a later stage in the template, use the reference() template function with the 'Full' option, as in this example:

{
    "tenantId": "[reference(resourceId('Microsoft.Web/sites', variables('appName')), '2018-02-01', 'Full').identity.tenantId]",
    "objectId": "[reference(resourceId('Microsoft.Web/sites', variables('appName')), '2018-02-01', 'Full').identity.principalId]",
}

Add a user-assigned identity

To create an app with a user-assigned identity, create the identity and then add its resource identifier to your app configuration.

You can use an Azure Resource Manager template to automate deployment of your Azure resources. To learn more, see Automate resource deployment in App Service and Automate resource deployment in Azure Functions.

You can create any resource of type Microsoft.Web/sites with an identity by including the following block in the resource definition. Replace <resource-id> with the resource ID of the desired identity.

"identity": {
    "type": "UserAssigned",
    "userAssignedIdentities": {
        "<resource-id>": {}
    }
}

Note

An application can have both system-assigned and user-assigned identities at the same time. In that case, the type property is SystemAssigned,UserAssigned.

Adding the user-assigned type tells Azure to use the user-assigned identity that you specified for your application.

For example, a web app's template might look like the following JSON:

{
    "apiVersion": "2022-03-01",
    "type": "Microsoft.Web/sites",
    "name": "[variables('appName')]",
    "location": "[resourceGroup().location]",
    "identity": {
        "type": "UserAssigned",
        "userAssignedIdentities": {
            "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('identityName'))]": {}
        }
    },
    "properties": {
        "name": "[variables('appName')]",
        "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
        "hostingEnvironment": "",
        "clientAffinityEnabled": false,
        "alwaysOn": true
    },
    "dependsOn": [
        "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
        "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('identityName'))]"
    ]
}

When the site is created, it includes the following properties:

"identity": {
    "type": "UserAssigned",
    "userAssignedIdentities": {
        "<resource-id>": {
            "principalId": "<principal-id>",
            "clientId": "<client-id>"
        }
    }
}

The principalId property is a unique identifier for the identity that's used for Microsoft Entra administration. The clientId property is a unique identifier for the application's new identity. You use it to specify which identity to use during runtime calls.

Configure the target resource

You need to configure the target resource to allow access from your app. For most Azure services, you configure the target resource by creating a role assignment.

Some services use mechanisms other than Azure role-based access control. To understand how to configure access by using an identity, refer to the documentation for each target resource. To learn more about which resources support Microsoft Entra tokens, see Azure services that support Microsoft Entra authentication.

For example, if you request a token to access a secret in Azure Key Vault, you must also create a role assignment that allows the managed identity to work with secrets in the target vault. Otherwise, Key Vault rejects your calls even if you use a valid token. The same is true for Azure SQL Database and other services.

Important

The back-end services for managed identities maintain a cache per resource URI for around 24 hours. It can take several hours for changes to a managed identity's group or role membership to take effect. It's currently not possible to force a managed identity's token to be refreshed before its expiration. If you change a managed identity's group or role membership to add or remove permissions, you might need to wait several hours for the Azure resource that's using the identity to have the correct access.

For alternatives to groups or role memberships, see Limitation of using managed identities for authorization.

Connect to Azure services in app code

With its managed identity, an app can get tokens for Azure resources that Microsoft Entra ID helps protect, such as Azure SQL Database, Azure Key Vault, and Azure Storage. These tokens represent the application that accesses the resource, and not any specific user of the application.

App Service and Azure Functions provide an internally accessible REST endpoint for token retrieval. You can access the REST endpoint from within the app by using a standard HTTP GET request. You can implement the request with a generic HTTP client in every language.

For .NET, JavaScript, Java, and Python, the Azure Identity client library provides an abstraction over this REST endpoint and simplifies the development experience. Connecting to other Azure services is as simple as adding a credential object to the service-specific client.

A raw HTTP GET request uses the two supplied environment variables and looks like the following example:

GET /MSI/token?resource=https://vault.azure.cn&api-version=2019-08-01 HTTP/1.1
Host: <ip-address-:-port-in-IDENTITY_ENDPOINT>
X-IDENTITY-HEADER: <value-of-IDENTITY_HEADER>

A sample response might look like the following example:

HTTP/1.1 200 OK
Content-Type: application/json

{
    "access_token": "eyJ0eXAi…",
    "expires_on": "1586984735",
    "resource": "https://vault.azure.cn",
    "token_type": "Bearer",
    "client_id": "00001111-aaaa-2222-bbbb-3333cccc4444"
}

This response is the same as the response for the Microsoft Entra service-to-service access token request. To access Key Vault, add the value of access_token to a client connection with the vault.

For more information on the REST endpoint, see REST endpoint reference later in this article.

Remove an identity

When you remove a system-assigned identity, it's deleted from Microsoft Entra ID. System-assigned identities are also automatically removed from Microsoft Entra ID when you delete the app resource itself.

To remove all identities in an ARM template, use this code:

"identity": {
    "type": "None"
}

Note

You can also set an application setting that disables only the local token service: WEBSITE_DISABLE_MSI. However, it leaves the identity in place. Tooling still shows the managed identity as on or enabled. As a result, we don't recommend that you use this setting.

REST endpoint reference

An app with a managed identity makes this endpoint available by defining two environment variables:

  • IDENTITY_ENDPOINT: The URL to the local token service.
  • IDENTITY_HEADER: A header that can help mitigate server-side request forgery (SSRF) attacks. The platform rotates the value.

The IDENTITY_ENDPOINT variable is a local URL from which your app can request tokens. To get a token for a resource, make an HTTP GET request to this endpoint. Include the following parameters:

Parameter name In Description
resource Query The Microsoft Entra resource URI of the resource for which a token should be obtained. This resource could be one of the Azure services that support Microsoft Entra authentication or any other resource URI.
api-version Query The version of the token API to be used. Use 2019-08-01.
X-IDENTITY-HEADER Header The value of the IDENTITY_HEADER environment variable. This header is used to help mitigate SSRF attacks.
client_id Query (Optional) The client ID of the user-assigned identity to be used. It can't be used on a request that includes principal_id, mi_res_id, or object_id. If all ID parameters (client_id, principal_id, object_id, and mi_res_id) are omitted, the system-assigned identity is used.
principal_id Query (Optional) The principal ID of the user-assigned identity to be used. The object_id parameter is an alias that can be used instead. It can't be used on a request that includes client_id, mi_res_id, or object_id. If all ID parameters (client_id, principal_id, object_id, and mi_res_id) are omitted, the system-assigned identity is used.
mi_res_id Query (Optional) The Azure resource ID of the user-assigned identity to be used. It can't be used on a request that includes principal_id, client_id, or object_id. If all ID parameters (client_id, principal_id, object_id, and mi_res_id) are omitted, the system-assigned identity is used.

Important

If you're trying to get tokens for user-assigned identities, include one of the optional properties. Otherwise, the token service tries to get a token for a system-assigned identity, which might or might not exist.

Consider the following tutorials:

Note: The author created this article with assistance from AI. Learn more