Skip to main content
emnode
Compliance Medium severity MCSB IM-3

Microsoft Defender for Cloud · Azure App Service

Managed identity should be used in API apps

Written and reviewed by Emnode · Last reviewed

What does the recommendation "Managed identity should be used in API apps" check?

Flags any API app on Azure App Service that has no managed identity configured, so its code authenticates to other Azure services using secrets such as connection strings, client secrets or SAS tokens held in app settings. It looks only at whether an identity exists on the resource: it does not check that the identity is system-assigned rather than user-assigned, that role assignments are scoped tightly, or that the app actually uses the identity instead of a stored secret. The original 'Managed identity should be used in your API App' policy is deprecated; the live equivalent is the built-in 'App Service apps should use managed identity', which covers web, function and API apps together and runs in AuditIfNotExists mode.

Why does "Managed identity should be used in API apps" matter?

Without a managed identity, an API app reaches Key Vault, Storage or SQL using long-lived credentials baked into its configuration. Those secrets get copied into pipelines, logged in error traces and shared between environments, and they rarely get rotated, so a single leaked app setting hands an attacker a working key to your backend data. A managed identity removes the secret entirely: Microsoft Entra ID issues and rotates the token, and you grant the identity only the roles it needs. The business consequence of skipping it is a wider blast radius and a slower, messier incident response when a credential does escape, because there is no central place to revoke it.

How do I fix "Managed identity should be used in API apps"?

  1. Enable a system-assigned managed identity on the API app: 'az webapp identity assign --resource-group <rg> --name <app>', or in Bicep set 'identity: { type: 'SystemAssigned' }' on the 'Microsoft.Web/sites' resource.
  2. Grant the identity least-privilege access to each downstream resource via RBAC, for example a 'Key Vault Secrets User' role assignment on the specific vault, then update the app code to use DefaultAzureCredential so it requests tokens from the identity instead of reading a stored secret.
  3. Remove the now-unused connection strings, client secrets and SAS tokens from the app settings and Key Vault, and assign the built-in policy to keep it enforced: pid=$(az policy definition list --query "[?displayName=='App Service apps should use managed identity'].name" -o tsv); az policy assignment create --name require-appservice-mi --policy "$pid" --scope <scope>.

Remediation script · bash

# 1. Give the app its own identity and capture the principal ID.
principalId=$(az webapp identity assign \
  --resource-group payments-rg \
  --name payments-api-prod \
  --query principalId -o tsv)

# 2. Grant least privilege on the exact resource it uses (not the subscription).
az role assignment create \
  --assignee-object-id "$principalId" \
  --assignee-principal-type ServicePrincipal \
  --role "Storage Blob Data Contributor" \
  --scope "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/payments-rg/providers/Microsoft.Storage/storageAccounts/paymentsdata"

# 3. Only after the code uses DefaultAzureCredential and the new path is verified,
#    delete the stored secret so there is nothing left to leak.
az webapp config appsettings delete \
  --resource-group payments-rg --name payments-api-prod \
  --setting-names StorageConnectionString

# 4. Ratchet it shut: audit any future app created without a managed identity.
az policy assignment create \
  --name audit-webapp-managed-identity \
  --policy 2b9ad585-36bc-4615-b300-fd4435808332 \
  --scope "/subscriptions/00000000-0000-0000-0000-000000000000"

Full walkthrough (console steps, edge cases and verification) in the lesson Use managed identities instead of stored secrets.

Is "Managed identity should be used in API apps" a false positive?

An API app that genuinely needs no Azure resource access, for example a stateless service that only returns computed responses and talks to no Key Vault, Storage or database, can run safely without a managed identity. The control still flags it because it cannot tell that the app has nothing to authenticate to, so this is a deliberate, documented exception rather than a fix to apply.