The Short Answer
Use a Managed Identity whenever you can. Use a Service Principal when you have to.
That covers about 80% of decisions. The remaining 20% is where it gets interesting.
What They Actually Are
Both Managed Identities and Service Principals are identities in Microsoft Entra ID (formerly Azure AD) that applications use to authenticate to Azure resources. The difference is in who manages the credentials.
Managed Identity: Azure creates and manages the credentials automatically. You never see a password, certificate, or secret. The identity is tied to an Azure resource (a VM, App Service, Function App, Container App, etc.) and only that resource can use it.
Service Principal: You create an App Registration in Entra ID and generate credentials (a client secret or certificate) yourself. Your application uses those credentials to authenticate. You’re responsible for storing them securely, rotating them before they expire, and cleaning them up when they’re no longer needed.
System-Assigned vs User-Assigned Managed Identities
There are two types of Managed Identity, and the distinction matters:
System-assigned: Created and tied to a single Azure resource. When the resource is deleted, the identity is deleted. One resource, one identity.
# Enable system-assigned identity on an App Service
az webapp identity assign --name my-app --resource-group my-rg
User-assigned: Created as a standalone Azure resource. Can be attached to multiple resources. Survives if any individual resource is deleted.
# Create a user-assigned identity
az identity create --name my-shared-identity --resource-group my-rg
# Assign it to an App Service
az webapp identity assign \
--name my-app \
--resource-group my-rg \
--identities /subscriptions/{sub}/resourceGroups/my-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/my-shared-identity
Use system-assigned when the identity is unique to one resource and should be cleaned up automatically.
Use user-assigned when multiple resources need the same identity (e.g., an App Service and a Function App that both read the same Key Vault), or when you need the identity to persist across resource replacements (blue-green deployments, slot swaps).
When Managed Identity Works
Managed Identities work wherever the authentication happens from an Azure compute resource to an Azure service that supports Entra ID authentication. The common scenarios:
| From | To | Works? |
|---|---|---|
| App Service | Key Vault | Yes |
| Azure Function | SQL Database (Entra auth) | Yes |
| Container App | Storage Account | Yes |
| VM | Azure Resource Manager API | Yes |
| AKS Pod (workload identity) | Key Vault | Yes |
| Azure Data Factory | SQL, Storage, Key Vault | Yes |
The authentication flow uses the Azure Instance Metadata Service (IMDS) endpoint that runs on every Azure compute host. Your code requests a token from http://169.254.169.254/metadata/identity/oauth2/token, and the platform handles the rest. No secrets involved.
With the Azure SDK, it’s even simpler:
from azure.identity import DefaultAzureCredential
from azure.keyvault.secrets import SecretClient
credential = DefaultAzureCredential()
client = SecretClient(vault_url="https://my-vault.vault.azure.net", credential=credential)
secret = client.get_secret("my-secret")
DefaultAzureCredential automatically discovers and uses the Managed Identity when running in Azure. No configuration needed.
When You Need a Service Principal
Managed Identities don’t cover every scenario. You need a Service Principal when:
The client isn’t an Azure resource. If your code runs on-premises, in another cloud (AWS, GCP), in a CI/CD pipeline (GitHub Actions, Azure DevOps), or on a developer’s laptop, there’s no IMDS endpoint to talk to. You need explicit credentials.
Cross-tenant access. A Managed Identity lives in one Entra ID tenant. If you need to authenticate to resources in a different tenant (a partner’s subscription, a customer’s environment), you need a multi-tenant App Registration with a Service Principal.
Application permissions for Microsoft Graph. Some Graph API operations require application-level permissions (not delegated). These are granted to App Registrations, not Managed Identities.
Third-party integrations. SaaS tools that integrate with your Azure environment typically need a Service Principal with client credentials. They can’t use your Managed Identity.
Terraform and IaC pipelines. While Azure DevOps and GitHub Actions support workload identity federation (which eliminates secrets), many CI/CD setups still use Service Principal credentials for Terraform azurerm provider authentication.
The Credential Management Tax
Every Service Principal you create adds to your operational burden:
- Secret expiry: Client secrets have a maximum lifetime (configurable, often defaulting to 2 years). When they expire, the application stops working.
- Storage: The secret needs to be stored somewhere secure (Key Vault, pipeline secrets, environment variables). Each storage location is another thing to manage.
- Rotation: Secrets should be rotated well before expiry. This means generating a new secret, propagating it to all consumers, verifying, and cleaning up the old one.
- Audit: Who created the secret? Who has access to it? Is it stored in more than one place? These questions get harder to answer as the number of Service Principals grows.
This is what we call the credential management tax. Every Service Principal costs you ongoing operational time. Managed Identities eliminate this tax entirely.
A Practical Decision Flowchart
Ask these questions in order:
- Does the code run on an Azure compute resource? (App Service, Function, Container App, VM, AKS) If no, you need a Service Principal.
- Does it need to access resources in a different Entra ID tenant? If yes, you need a Service Principal.
- Does it need application-level Graph API permissions? If yes, you need a Service Principal (though check if the specific Graph endpoint supports managed identity first).
- Otherwise: Use a Managed Identity.
Workload Identity Federation: The Middle Ground
There’s a newer option that bridges the gap: workload identity federation. This lets external identity providers (GitHub Actions, AWS, GCP, Kubernetes) authenticate to Azure without client secrets.
Instead of storing a client secret in GitHub Actions, you configure a trust relationship between your App Registration and GitHub’s OIDC provider. GitHub Actions requests a token from its own OIDC endpoint, and Azure trusts it based on the federation configuration.
# Create a federated credential for GitHub Actions
az ad app federated-credential create \
--id "APP_OBJECT_ID" \
--parameters '{
"name": "github-main",
"issuer": "https://token.actions.githubusercontent.com",
"subject": "repo:myorg/myrepo:ref:refs/heads/main",
"audiences": ["api://AzureADTokenExchange"]
}'
This eliminates the client secret entirely while still using a Service Principal identity. It’s the best option for CI/CD pipelines.
Audit and Cleanup
Whether you use Managed Identities, Service Principals, or both, you need visibility:
- How many Service Principals exist in your tenant?
- Which ones have expired credentials?
- Which ones have credentials but no recent sign-in activity (potentially orphaned)?
- Which Managed Identities have overly broad RBAC assignments?
# List all App Registrations with credential expiry info
az ad app list --all --query "[].{name:displayName, appId:appId, secrets:passwordCredentials[].{end:endDateTime}}" -o table
For a handful of Service Principals, the CLI is fine. For a real enterprise environment with hundreds of App Registrations, you need automated tooling.
CertifyClouds discovers every App Registration and its credentials across your entire Entra ID tenant, flags expired and expiring secrets, maps which Azure resources depend on each one, and automates the rotation lifecycle. If you can’t eliminate a Service Principal, at least automate its credential management.
Further Reading
- Azure App Registration Secret Management: Stop the Credential Sprawl -for the Service Principals you can’t replace with Managed Identities, here’s how to manage their credentials
- Azure Key Vault Access Policies vs RBAC: Which Should You Use? -whichever identity type you use, it needs access to Key Vault
- Azure Key Vault Secret Rotation: Best Practices for 2026 -automate rotation for Service Principal credentials that can’t be eliminated