Implement Managed Identities

Learn to implement managed identities for services in Azure. This hands-on tutorial covers the core concepts, step-by-step setup, troubleshooting, and best practices to securely authenticate your services without managing credentials.

Focus: implement managed identities for services

Sponsored

You’re staring at a connection string in your code, a secret that can leak from a repo, a log, or a teammate’s laptop. Managing credentials for every service—rotating keys, updating app settings, granting access—is a constant drain on your time and a security risk you can’t afford. This lesson shows you how to implement managed identities for services in Azure, eliminating the need to store and manage credentials entirely. You’ll go from a mental model to a working hands-on exercise, so you can authenticate your services securely and focus on building features, not babysitting secrets.

The problem this lesson solves

Every Azure service that needs to talk to another—say, a web app reading from Blob Storage or a function querying a database—needs to prove who it is. Traditional approaches rely on service principals and client secrets. That means:

  • You create a secret, store it in Key Vault or app settings, and rotate it on a schedule.
  • You risk exposing secrets in source code, deployment logs, or chat messages.
  • You need to manage permissions for each principal, and revoke them when the app changes.

This is not just a nuisance; it’s a security liability. A single leaked secret can give an attacker access to your data. You’ve probably spent hours debugging a missing access policy or a rotated secret that broke your pipeline.

Managed identities solve this by giving your Azure resource—like a VM, an App Service, or a function—an automatic identity that Azure manages for you. You don’t store any credentials; Azure handles the authentication behind the scenes. This lesson teaches you how to implement managed identities for services, so you can authenticate without secret management.

Core concept / mental model

Think of a managed identity as a digital badge that Azure pins to your resource. Your service wears this badge and shows it to other Azure services to prove who it is. No passwords, no keys—just the badge, which Azure validates automatically.

There are two types of managed identities in Azure:

  • System-assigned: Created with the resource and deleted with it. The identity is tied directly to that resource—like a permanently attached badge. Use this when you have a single resource that needs an identity.
  • User-assigned: A standalone identity resource that you create and assign to one or more Azure resources. It has its own lifecycle, separate from any resource. Use this when you have multiple resources that need the same identity, or you need to decouple the identity from the resource.

Behind the scenes, Azure uses Azure AD (now Microsoft Entra ID) and Azure Instance Metadata Service (IMDS) to issue and validate tokens. When your service needs to access another resource, it requests a token from IMDS, gets a valid OAuth 2.0 token, and sends it to the target service. No secret is ever stored in your code or configuration.

Here’s a mental diagram to visualize the flow:

Your Azure service (App Service, VM, Function)
        |
        | (1) Requests token from IMDS (endpoint: 169.254.169.254)
        v
Azure Instance Metadata Service
        |
        | (2) Verifies identity with Azure AD, returns an access token
        v
Your service uses token to authenticate to (3) Blob Storage, Key Vault, SQL DB, etc.
        |
        v
Access granted! No credentials in your code.

How it works step by step

Implementing a managed identity for a service follows a predictable pattern. Here’s the logical sequence:

  1. Enable the managed identity on your resource (App Service, VM, or Function).
  2. Grant permissions to the identity so it can access the target resource (e.g., Blob Storage or Key Vault).
  3. Update your application code to use the identity to obtain a token (via SDKs that handle this automatically).
  4. Test your app to confirm it can access the resource without any secrets.

Each step matters—if you skip granting permissions, your app will get an AuthorizationFailed error. If you don’t update the code to use the identity, it’ll fall back to connection strings or service principals.

Hands-on walkthrough

Let’s implement a system-assigned managed identity on an Azure App Service, and use it to read a blob from Azure Storage. You’ll need the Azure CLI installed and an existing App Service and Storage account.

Step 1: Enable the managed identity

Use the Azure CLI to enable a system-assigned identity on your web app:

az webapp identity assign --name my-webapp --resource-group my-rg

Expected output snippet:

{
  "principalId": "a1b2c3d4-...",
  "tenantId": "...",
  "type": "SystemAssigned"
}

Take note of the principalId—you’ll use it in the next step.

Step 2: Grant permissions

Allow the identity to read blobs in your storage account:

az role assignment create --assignee <principalId> --role "Storage Blob Data Reader" --scope /subscriptions/<sub-id>/resourceGroups/my-rg/providers/Microsoft.Storage/storageAccounts/my-storage

Verify the role assignment (optional):

az role assignment list --assignee <principalId> --output table

You’ll see a row with your role and scope. If it’s empty, you might have used the wrong principal ID or scope.

Step 3: Update your application code

In your Python web app, use the Azure SDK to connect with the managed identity. Install the needed package:

pip install azure-identity azure-storage-blob

Now write the code to authenticate and list blobs:

from azure.identity import DefaultAzureCredential
from azure.storage.blob import BlobServiceClient

# When deployed to Azure App Service with managed identity enabled,
# DefaultAzureCredential will automatically use the managed identity.
credential = DefaultAzureCredential()

account_url = "https://my-storage.blob.core.windows.net"
blob_service_client = BlobServiceClient(account_url, credential=credential)

# List containers and blobs to prove access
for container in blob_service_client.list_containers():
    print(f"Container: {container.name}")
    container_client = blob_service_client.get_container_client(container.name)
    for blob in container_client.list_blobs():
        print(f"  Blob: {blob.name}")

Expected output (if you have blobs):

Container: my-container
  Blob: data.csv

Step 4: Deploy and test

Deploy your app to App Service. Set environment variables for the storage account URL (but not any secrets—the managed identity handles that). Then hit your app’s endpoint. You should see the container and blob names without any connection strings.

Pro tip: Use the DefaultAzureCredential from the Azure Identity SDK. When running locally, it will fall back to your Azure CLI login, so you can test without deploying. This makes the same code work in development and production.

Compare options / when to choose what

You have two main options for implementing managed identities—system-assigned and user-assigned. Here’s a comparison to help you decide:

Feature System-assigned User-assigned
Lifecycle Tied to the resource Independent of any resource
Management Automatic on resource creation/deletion Manual creation and assignment
Use case Single resource that needs an identity Multiple resources sharing the same identity, or when you need the identity to outlive the resource
Setup effort Minimal—just enable Extra step to create and assign
Security isolation Each resource has its own identity All resources share one identity—ensure you only assign to trusted resources

When to choose what: Use system-assigned for simplicity when you have a single service. Use user-assigned when you have multiple services that need the same permissions (e.g., a group of functions accessing the same database) or when you need to pre-provision the identity before the resource exists.

Alternatives: You could also use a service principal with certificates, but that means managing certificate lifecycle. Or you could use Key Vault to store secrets, but that still requires a secret to access Key Vault—managed identities break that cycle. For most scenarios, managed identities are the modern best practice in Azure.

Troubleshooting & edge cases

  • AuthorizationFailed when accessing storage: You haven’t granted the correct role. Double-check the assignee ID (the principalId) and the scope. Use the CLI to list role assignments.
  • DefaultAzureCredential not working locally: When running outside Azure, it falls back to your local credentials. Make sure you’re logged in with az login. If it still fails, set the environment variable AZURE_CLIENT_ID to the managed identity’s client ID (for user-assigned) to force it.
  • User-assigned identity not found: You must assign the identity to the resource before the resource can use it. Check the resource’s identity list in the portal or via CLI.
  • Token acquisition fails intermittently: Ensure your resource has network access to the IMDS endpoint (for VMs, it’s 169.254.169.254). If you’re behind a proxy or firewall, allow traffic to this endpoint.
  • Resource deleted and recreated: For system-assigned, the identity is deleted with the resource. You need to re-enable it and re-grant permissions.

What you learned & what's next

You now understand the core concept of managed identities—how they replace secrets with an automatic identity managed by Azure. You’ve completed a hands-on exercise that enabled a system-assigned identity on an App Service, granted it permissions to Blob Storage, and used it from Python code. You’ve also compared system vs. user-assigned and learned how to troubleshoot common issues.

With this foundation, you’re ready to move to the next lesson in the Azure track, where you’ll apply managed identities to secure connections to other Azure services like Key Vault and databases. Remember these takeaways:

  • Managed identities eliminate secret management for Azure-to-Azure communication.
  • System-assigned ties identity to a resource; user-assigned is a standalone identity you can share.
  • Always grant least-privilege roles to identities.
  • Use DefaultAzureCredential in your code for seamless local-to-cloud transitions.

You’re on your way to building secure, credential-free solutions in Azure.

Practice recap

Now it’s your turn: enable a system-assigned managed identity on an existing App Service and grant it Reader access to a storage account. Modify your app to list containers using DefaultAzureCredential and deploy. If you get any errors, revisit the troubleshooting section. This mini-exercise will solidify the concept before you move on to the next lesson.

Common mistakes

  • Forgetting to grant the role to the managed identity — you’ll get an AuthorizationFailed error even though the identity exists.
  • Using the wrong principalId: For user-assigned identities, use the identity’s principal ID, not the resource’s. Check with az identity show.
  • Not using DefaultAzureCredential when combining local and cloud code — you’ll end up writing separate auth logic.
  • Deleting a resource with a system-assigned identity loses that identity permanently — you must re-enable and re-grant permissions if you recreate the resource.

Variations

  1. use user-assigned identity instead of system-assigned for shared access across multiple resources
  2. use Azure SDK in other languages (e.g., Java, Node.js) that support DefaultAzureCredential pattern
  3. Use managed identities for Key Vault access, not just storage: assign Key Vault Reader role to the identity.

Real-world use cases

  • A Python web app on App Service reads CSV files from Blob Storage for data processing, authenticating with a managed identity instead of connection strings.
  • A microservices architecture on Azure Functions uses user-assigned managed identity to share access to a central SQL database without per-function secrets.
  • A CI/CD pipeline deploying infrastructure uses a managed identity on a VM to access Key Vault for storing deployment secrets, minimizing manual secret handling.

Key takeaways

  • Managed identities remove the need to manage credentials for Azure service-to-service authentication.
  • System-assigned identities are tied to a resource, while user-assigned identities are standalone and can be reused.
  • You must assign the appropriate Azure RBAC role to the identity to allow access to target resources.
  • Use DefaultAzureCredential in your code to seamlessly authenticate with managed identity in Azure and fall back to local credentials during development.
  • Troubleshoot authorization failures by checking role assignments and identity configuration before diving into code.
  • Managed identities are a best practice for securing Azure workloads—adopt them over service principals and secrets whenever possible.

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.