| title | Use Service Principals and Managed Identities |
|---|---|
| titleSuffix | Azure DevOps |
| description | Learn how to add and manage service principals and managed identities in your Azure DevOps organizations. |
| ms.subservice | azure-devops-security |
| ms.assetid | |
| ms.topic | how-to |
| ms.author | wonga |
| author | wonga |
| ms.date | 07/14/2025 |
| monikerRange | azure-devops |
[!INCLUDE version-eq-azure-devops]
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.
- 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.
- 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.
- 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.
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.
- 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 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.
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.
Follow these steps to implement service principals or managed identities for Azure DevOps authentication. For complete code examples, see our sample applications.
Choose the appropriate identity type based on your deployment scenario.
Service principals work well for CI/CD pipelines, cross-cloud scenarios, and applications that need flexible deployment options.
-
Register an application in the Microsoft Entra admin center.
-
Go to App registrations > New registration.
-
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.
-
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:
Managed identities provide the simplest authentication experience for Azure-hosted applications.
For system-assigned managed identity:
- Go to your Azure resource, such as App Service or an Azure Functions app.
- Go to Identity > System assigned.
- Switch the status to On.
- Select Save to save the configuration.
For user-assigned managed identity:
- Create the managed identity in the Azure portal.
- Go to Create a resource > Managed Identity.
- Configure basic settings and create the resource.
- Assign to resources as needed.
[!VIDEO https://learn-video.azurefd.net/vod/player?id=b9cf4e49-db98-4247-8770-b8707b043f17]
For more information, see the following articles:
After you create your identity in Microsoft Entra ID, add it to your Azure DevOps organization to grant access to resources.
- Project collection administrator role.
- Project administrator or team administrator role when the invite policy allows team admins to add users.
To add the identity through the Azure DevOps portal:
-
Go to Organization Settings > Users.
-
Select Add users.
-
Enter the display name of your service principal or managed identity.
-
Select the appropriate access level and project access.
-
Send the invitation.
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.
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.
[!VIDEO https://learn-video.azurefd.net/vod/player?id=e8ee6f58-3939-4170-b112-0ca1b39b0298]
Permission management options:
- Azure DevOps portal: Select Organization settings > Permissions.
- REST APIs: Use Service Principal Graph APIs for programmatic management.
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.
Get access tokens to authenticate your applications with Azure DevOps APIs and services.
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_credentialsUse 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;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: trueFor 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.
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 https://learn-video.azurefd.net/vod/player?id=8397f848-b946-4c30-8d0c-78aa4784a549]
[!VIDEO https://learn-video.azurefd.net/vod/player?id=f4a20e00-c2df-49cc-9b86-7454bd84b9ce]
- NuGet feeds: Connect with NuGet.exe or dotnet CLI.
- Marketplace publishing: Publish extensions via command line.
- Azure Pipelines: Create service connections backed by managed identities.
- Git operations: Clone repositories with the Git Credential Manager.
For complete code examples, see our sample applications.
Service principals and managed identities have different management characteristics compared to user accounts.
- 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.
- 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.
- 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.
- Must be explicitly added to organizations (no automatic materialization like users).
- Required because service principals can't sign in interactively.
Service principals and managed identities have specific limitations compared to regular users.
- ✅ 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.
- 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.)
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.
A. Service principals and managed identities have the same rate limits as users.
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.
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:
- Create a user-assigned managed identity in the resource tenant.
- Assign it to an Azure resource, such as a virtual machine or a Functions app).
- Create a key vault and generate a certificate (non-PEM format).
- Grant managed identity access to the key vault with the Get and List secret permissions.
- Download the certificate in CER format (public key only).
- Register the application in the target tenant.
- Upload the certificate to application registration.
- Add the service principal to the Azure DevOps organization.
- 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.
Solution: Ensure that the service principal has at least a Basic license. Stakeholder licenses don't provide repository access.
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:
- Go to Microsoft Entra admin center > Enterprise applications.
- Search for your application name.
- Use the object ID on the Enterprise applications pane.
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.
Solution: Use continuationToken to iterate through all pages. Service principals might appear on later pages because of API pagination behavior.
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.
