Managed identities vs service principals: which should your workload use?
Both let code authenticate to Azure and Microsoft Graph. One needs you to manage secrets; the other doesn't. A simple guide to choosing.
On this page
Every automation, app and pipeline that talks to Azure needs an identity. There are two common choices, and picking the right one removes a whole class of outages and security risks.
Service principals
An app registration with a service principal authenticates using a client secret or certificate. It works from anywhere: your laptop, another cloud, a SaaS product. The cost is credential management: secrets expire, get pasted into scripts and leak.
Managed identities
A managed identity is a service principal that Azure manages for you. There are no credentials to store or rotate. The Azure resource gets tokens directly from the platform.
- System-assigned: tied to one resource and deleted with it. Good for a single app with its own permissions.
- User-assigned: a standalone resource you can attach to several resources. Good when multiple resources need the same access, or when you want the identity to outlive the resource.
System-assigned
- Created with the resource
- Deleted with the resource
- One identity per resource
User-assigned
- A standalone Azure resource
- Can be shared by several resources
- Survives redeployments
How to choose
- Code running in Azure (Functions, App Service, VMs, Automation, Container Apps): use a managed identity.
- Code running outside Azure that supports OpenID Connect, such as GitHub Actions or another cloud: use workload identity federation, which also needs no secrets.
- Only when neither is possible: a service principal with a certificate, stored in Key Vault, with a short lifetime and a named owner.
# Give a Function App's system-assigned identity read access to a storage account
$principalId = az functionapp identity assign -g rg-app -n func-app --query principalId -o tsv
az role assignment create --assignee $principalId \
--role "Storage Blob Data Reader" \
--scope "/subscriptions/<sub-id>/resourceGroups/rg-data/providers/Microsoft.Storage/storageAccounts/stdata"How a managed identity gets a token
In code you rarely call the endpoint directly. The Azure SDKs' DefaultAzureCredential picks up the managed identity automatically, and in PowerShell it's Connect-AzAccount -Identity or Connect-MgGraph -Identity.
Gotchas
- Role assignments can take a few minutes to apply. Retry before assuming the setup is wrong.
- Managed identities can be granted Microsoft Graph application permissions, but not through the portal's API permissions blade; use PowerShell or the Graph API.
- Deleting a resource deletes its system-assigned identity and its role assignments with it.
This post was last checked against Microsoft's documentation over six months ago. The approach should still hold, but check the linked sources for anything that has changed before you act on it.
Next in Automating Entra and Azure safely · part 2 of 5Unattended Graph PowerShell scripts with certificate authentication →