Edit

Share via


Use service principals and managed identities in Azure DevOps

Azure DevOps Services

Service principals and managed identities provide secure, scalable authentication for Azure DevOps automation workflows. These Microsoft Entra identity types offer enhanced security over traditional personal access tokens (PATs). They use automatic credential management, shorter token lifespans, and enterprise-grade access controls.

Benefits of service principals and managed identities

Enhanced security

  • Short-lived tokens: Microsoft Entra tokens expire every hour, which reduces exposure risk compared to PATs (which can last up to one year).
  • Automatic rotation: Managed identities handle credential rotation automatically.
  • No stored secrets: The need to store long-lived credentials in code or configuration is eliminated.

Operational excellence

  • Centralized management: Control access through Microsoft Entra ID policies and Azure DevOps permissions.
  • Audit capabilities: Track authentication and access patterns through comprehensive logging.
  • Scale efficiently: Support enterprise automation scenarios without individual user dependencies.

Modern authentication

  • Standards based: Uses OAuth 2.0 and OpenID Connect protocols.
  • Multifactor authentication support: Inherits organizational security policies.
  • Conditional access: Applies advanced security policies based on context.

Understand service principals and managed identities

Service principals

Service principals are Microsoft Entra objects that represent applications within a tenant. They define what an application can do, which resources it can access, and who can use it. Service principals are created automatically when you register an application in Microsoft Entra ID and provide a secure way for applications to authenticate and access resources.

Key characteristics

  • Are created through application registration in Microsoft Entra ID.
  • Support multitenant scenarios.
  • Require explicit credential management (certificates or client secrets).
  • Are ideal for applications that need to authenticate across different environments.

Managed identities

Managed identities are a special type of service principal that Azure manages automatically. They eliminate the need for developers to manage credentials by providing an automatically managed identity in Microsoft Entra ID for Azure resources.

Types of managed identities

System-assigned managed identity:

  • Automatically created and tied to a specific Azure resource.
  • Lifecycle managed by Azure (deleted when the resource is deleted).
  • One-to-one relationship with the Azure resource.
  • Best for applications deployed on a single Azure resource.

User-assigned managed identity:

  • Created as a standalone Azure resource.
  • Can be assigned to multiple Azure resources.
  • Lifecycle managed independently of associated resources.
  • Best for applications that run on multiple resources or need shared identity.

When to use each type:

  • Service principals: Cross-cloud deployments, continuous integration and continuous delivery (CI/CD) pipelines, applications outside Azure.
  • System-assigned managed identities: Single Azure resource applications (Azure Functions, Azure App Service).
  • User-assigned managed identities: Multi-resource applications, shared identity scenarios.

Implementation guide

Follow these steps to implement service principals or managed identities for Azure DevOps authentication. For complete code examples, see our sample applications.

Step 1: Create your identity

Choose the appropriate identity type based on your deployment scenario.

Option A: Create a service principal (application registration)

Service principals work well for CI/CD pipelines, cross-cloud scenarios, and applications that need flexible deployment options.

  1. Register an application in the Microsoft Entra admin center.

  2. Go to App registrations > New registration.

  3. Configure the application:

    • Name: Use a descriptive name for your application.
    • Account types: Select appropriate tenant support.
    • Redirect URI: Leave blank for service-to-service scenarios.
  4. Create authentication credentials:

    • Recommended: Upload a certificate for enhanced security.
    • Alternative: Create a client secret (requires regular rotation).

Important

When you register an application, Azure creates both an application object and a service principal object. Use the service principal's object ID (found on the Enterprise applications pane) when you add it to Azure DevOps, not the application's object ID.

For more information, see the following articles:

Option B: Create a managed identity

Managed identities provide the simplest authentication experience for Azure-hosted applications.

For system-assigned managed identity:

  1. Go to your Azure resource, such as App Service or an Azure Functions app.
  2. Go to Identity > System assigned.
  3. Switch the status to On.
  4. Select Save to save the configuration.

For user-assigned managed identity:

  1. Create the managed identity in the Azure portal.
  2. Go to Create a resource > Managed Identity.
  3. Configure basic settings and create the resource.
  4. Assign to resources as needed.

For more information, see the following articles:

Step 2: Add the identity to Azure DevOps

After you create your identity in Microsoft Entra ID, add it to your Azure DevOps organization to grant access to resources.

Prerequisites

  • Project collection administrator role.
  • Project administrator or team administrator role when the invite policy allows team admins to add users.

Add the identity

To add the identity through the Azure DevOps portal:

  1. Go to Organization Settings > Users.

  2. Select Add users.

  3. Enter the display name of your service principal or managed identity.

  4. Select the appropriate access level and project access.

  5. Send the invitation.

    Screenshot that shows service principals and managed identities in the Users Hub.

Add the identity programmatically:

Use the ServicePrincipalEntitlements REST API to automate the process.

Other considerations:

  • Find the correct ID: Use the service principal's object ID on the Enterprise applications pane in the Microsoft Entra admin center, not the application registration's object ID.
  • Tenant restrictions: You can add identities only from the same tenant to which your Azure DevOps organization is connected. For cross-tenant scenarios, see the FAQ workaround.

Step 3: Configure permissions

Configure granular permissions for your service principal or managed identity within Azure DevOps. Unlike other Azure services, Azure DevOps uses its own permission model rather than Microsoft Entra application permissions.

Permission options:

  • Direct assignment: Assign permissions directly to the identity.
  • Group membership: Add to Azure DevOps or Microsoft Entra security groups.
  • Access levels: Assign the appropriate license level (Basic, Basic + Test Plans, or Visual Studio subscriber).

Best practices:

  • Apply least privilege: Grant only the minimum permissions needed.
  • Use groups: Manage permissions through groups for easier maintenance.
  • Regular reviews: Audit permissions periodically.

Permission management options:

Important

Azure DevOps versus Microsoft Entra permissions: Azure DevOps doesn't use Microsoft Entra ID application permissions. All access control is managed through the Azure DevOps permission system, which allows for granular project and resource-level permissions.

Step 4: Get Microsoft Entra ID tokens

Get access tokens to authenticate your applications with Azure DevOps APIs and services.

For service principals

Use client credentials flow:

POST https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded

client_id={client-id}
&scope=https://app.vssps.visualstudio.com/.default
&client_secret={client-secret}
&grant_type=client_credentials

Use certificate authentication (recommended):

using Microsoft.Identity.Client;

var app = ConfidentialClientApplicationBuilder
    .Create(clientId)
    .WithCertificate(certificate)
    .WithAuthority(new Uri($"https://login.microsoftonline.com/{tenantId}"))
    .Build();

var result = await app
    .AcquireTokenForClient(new[] { "https://app.vssps.visualstudio.com/.default" })
    .ExecuteAsync();

string accessToken = result.AccessToken;

For managed identities

From Azure resources:

using Azure.Identity;
using Azure.Core;

var credential = new ManagedIdentityCredential();
var tokenRequest = new TokenRequestContext(new[] { "https://app.vssps.visualstudio.com/.default" });
var token = await credential.GetTokenAsync(tokenRequest);

string accessToken = token.Token;

Use Azure Instance Metadata Service:

GET http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://app.vssps.visualstudio.com/
Metadata: true

Azure CLI for ad hoc operations

For one-time operations or testing, use the Azure CLI:

# For service principal
az login --service-principal --username {client-id} --password {client-secret} --tenant {tenant-id}
az account get-access-token --resource https://app.vssps.visualstudio.com/

# For managed identity (from Azure resource)
az login --identity
az account get-access-token --resource https://app.vssps.visualstudio.com/

For more information, see Acquire Microsoft Entra tokens.

Step 5: Use tokens with Azure DevOps

Use your acquired tokens to authenticate REST API calls and other Azure DevOps operations.

Make authenticated API calls:

using System.Net.Http;
using System.Net.Http.Headers;

var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = 
    new AuthenticationHeaderValue("Bearer", accessToken);

var response = await client.GetAsync(
    "https://dev.azure.com/{organization}/_apis/projects?api-version=7.1");

Video examples

Common integration scenarios

For complete code examples, see our sample applications.

Management considerations

Service principals and managed identities have different management characteristics compared to user accounts.

Licensing

  • Each identity requires a license in every organization it joins.
  • Multi-organization billing doesn't apply to service principals.
  • Group-based licensing rules don't automatically apply. You must assign licenses directly.

Identity management

  • Email addresses aren't used, so there are no invitations via email.
  • Display names or avatars aren't modified in Azure DevOps.
  • Display names are inherited from Microsoft Entra ID.

Group membership

  • Can be added to Microsoft Entra groups and Azure DevOps groups.
  • Has a technical limitation that prevents display in Microsoft Entra group member lists (UI limitation only).
  • Can still inherit permissions from Microsoft Entra groups to which they belong.

Materialization

  • Must be explicitly added to organizations (no automatic materialization like users).
  • Required because service principals can't sign in interactively.

Key differences from user accounts

Service principals and managed identities have specific limitations compared to regular users.

Capabilities

  • ✅ Generate Microsoft Entra tokens for API access.
  • ✅ Access Azure DevOps resources with proper permissions.
  • ✅ Join security groups and teams.
  • ❌ Create PATs or Secure Shell keys.
  • ❌ Sign in interactively or access via a web UI.
  • ❌ Create or own organizations.
  • ❌ Support Azure DevOps OAuth flows.

Billing

  • Counted as a separate license in each organization. (There's no multi-organization discount.)
  • Must assign access level directly. (Group rules don't apply automatically.)

Frequently asked questions

Q. Why should I use a service principal or managed identity instead of a PAT?

A. Service principals and managed identities offer significant security advantages over PATs.

Security benefits:

  • Shorter lifespan: Microsoft Entra tokens expire hourly compared to PATs, which can last up to a year.
  • Automatic rotation: Managed identities rotate credentials automatically.
  • No shared secrets: The risk of storing or accidentally exposing long-lived tokens is eliminated.
  • Centralized control: Managed through Microsoft Entra ID with enterprise security policies.

Operational benefits:

  • Audit trail: Logs authentication and access patterns completely.
  • Conditional access: Applies policies based on location, device, and risk factors.
  • No service accounts: Eliminates dependency on individual user accounts for automation.

For migration examples, see Replace PATs with Microsoft Entra tokens.

Q. What are the rate limits on service principals and managed identities?

A. Service principals and managed identities have the same rate limits as users.

Q. Will using this feature cost more?

A. Service principals and managed identities are priced like users based on access level. Key differences are:

  • No multi-organization billing discount: Each identity counts as a separate license in every organization.
  • License assignment: Access levels must be assigned directly. (Group rules don't apply automatically.)
  • Same pricing tiers: Basic, Basic + Test Plans, and Visual Studio subscriber rates apply.

Q. Can I add a managed identity from a different tenant to my organization?

A. You can add identities directly from your organization's connected tenant only. For cross-tenant scenarios, use this workaround.

To set up a cross-tenant managed identity:

  1. Create a user-assigned managed identity in the resource tenant.
  2. Assign it to an Azure resource, such as a virtual machine or a Functions app).
  3. Create a key vault and generate a certificate (non-PEM format).
  4. Grant managed identity access to the key vault with the Get and List secret permissions.
  5. Download the certificate in CER format (public key only).
  6. Register the application in the target tenant.
  7. Upload the certificate to application registration.
  8. Add the service principal to the Azure DevOps organization.
  9. Configure authentication by using the certificate from the key vault.
// Example: Acquire token using managed identity certificate
public static async Task<string> GetSecret(string keyVaultName, string secretName)
{
    var keyVaultUri = new Uri($"https://{keyVaultName}.vault.azure.net");
    var client = new SecretClient(keyVaultUri, new ManagedIdentityCredential());
    var keyVaultSecret = await client.GetSecretAsync(secretName);
    return keyVaultSecret.Value.Value;
}

private static async Task<AuthenticationResult> GetAppRegistrationAADAccessToken(
    string applicationClientID, string appTenantId)
{
    byte[] privateKeyBytes = Convert.FromBase64String(await GetSecret(keyVaultName, secretName));
    var certificate = new X509Certificate2(privateKeyBytes, (string)null, X509KeyStorageFlags.MachineKeySet);

    var app = ConfidentialClientApplicationBuilder.Create(applicationClientID)
        .WithCertificate(certificate)
        .WithAuthority(new Uri($"https://login.microsoftonline.com/{appTenantId}"))
        .Build();

    var result = await app.AcquireTokenForClient(
        new[] { "499b84ac-1321-427f-aa17-267ca6975798/.default" })
        .ExecuteAsync();

    return result;
}

Important

Rotate certificates regularly for security best practices.

Common errors and solutions

The Git repository with name or identifier doesn't exist or you don't have permissions

Solution: Ensure that the service principal has at least a Basic license. Stakeholder licenses don't provide repository access.

Failed to create service principal with object ID

Solution: Verify that you're using the service principal's object ID from the Enterprise applications pane, not the application registration's object ID.

To find the correct ID:

  1. Go to Microsoft Entra admin center > Enterprise applications.
  2. Search for your application name.
  3. Use the object ID on the Enterprise applications pane.

Access denied: Needs permissions to add users

Possible causes and solutions:

  • Insufficient role: Must be a project collection administrator (PCA) or a project or team administrator with invite permissions enabled.
  • Policy restriction: Check if the Allow team and project administrators to invite new users policy is enabled.
  • License assignment: Project admins can't assign licenses during invitation. Contact the PCA for license changes.

Azure DevOps Graphs List API returns empty list

Solution: Use continuationToken to iterate through all pages. Service principals might appear on later pages because of API pagination behavior.

TF401444: Sign-in required error

Solution: Ensure that the service principal is added properly to the organization with required permissions. This error indicates that the identity isn't recognized in the organization.