An Azure Resource Manager service connection that authenticates with a client secret or certificate is a standing credential: it expires on its own schedule, breaks pipelines when it does, and works for anyone who copies it until then. Workload identity federation removes the secret. Azure Pipelines presents a short-lived token for the job, and Microsoft Entra ID exchanges it for an Azure access token only if the token's issuer and subject match a federated credential on an app registration or user-assigned managed identity. This page is the hands-on procedure: inventory the connections you have, create new federated connections (automatic and manual), convert existing ones, prove the change works, roll back, and tighten access afterwards. It is for Azure DevOps administrators and platform engineers deploying to Azure public cloud. The governance view of PATs and service connections is in the Azure DevOps PATs and service connections security guide; this page is the step-by-step that sits under it.
This is an independent guide from NHI Mgmt Group, based on Microsoft's public Azure DevOps and Microsoft Entra documentation as of November 2026. It is not sponsored or reviewed by Microsoft. Product behaviour changes, so confirm labels and dates against the current Microsoft Learn pages listed at the end.
Key takeaways
- Use the Microsoft Entra issuer. New federated connections use
https://login.microsoftonline.com/<tenant id>/v2.0. Connections on the Azure DevOps issuerhttps://vstoken.dev.azure.comare deprecated and, as announced by Microsoft, retire on 1 July 2027 for single-tenant apps and managed identities in Azure public cloud. - Convert before you rebuild. Connections that Azure DevOps created automatically and that only one project uses can be converted in place with the Convert button, and reverted within seven days. Manual and cross-project connections need a new connection.
- The subject is generated, not chosen. Azure DevOps shows the Issuer and Subject identifier when you create a manual connection. Paste both into an "Other issuer" federated credential with an explicit subject identifier; a typo only shows up as an AADSTS700213 error at run time.
- Federation removes the secret, not the blast radius. The identity still holds whatever Azure role you gave it. Scope roles to resource groups, authorise pipelines one by one and add branch control on production connections.
- Check task support first. Most current Azure tasks work, but older versions such as
AzureFileCopy@5andKubernetes@0must be upgraded, and a few tasks do not support federation at all.
When you need this
- Pipelines fail with AADSTS7000215 "Invalid client secret provided". Microsoft's troubleshooting guidance for this error is to convert the connection to workload identity federation rather than to issue another secret.
- You still have "Service principal (manual)" connections. These hold a Service Principal Key or Certificate entered by a person, usually with no recorded owner or expiry plan.
- You run connections on the Azure DevOps issuer. They keep working until the retirement date, but every one is migration work you should schedule, not discover in 2027.
- You have had a DevOps credential exposure before. The LastPass breach shows what follows when secrets held for DevOps work are stolen: they unlocked the cloud storage holding customer vault backups, far from any pipeline. A federated connection has no stored secret to steal.
Do not use this procedure for Azure US Government, Azure Stack or other non-public clouds, or for multi-tenant app registrations: Microsoft states these stay on the Azure DevOps issuer, and some sovereign clouds reject federation with AADSTS900382.
Before you start
| Requirement | Detail |
|---|---|
| Azure DevOps rights | Permission to create and manage service connections in the project (Project Administrator or service connection Administrator) |
| Automatic app registration | Owner role on the target subscription, so Azure DevOps can create the app registration and the role assignment for you |
| Managed identity route | Managed Identity Contributor (or higher) to create a user-assigned managed identity, plus rights to assign roles at the target scope |
| Manual app registration route | App ownership, or Application Administrator where the tenant setting "Users can register applications" is No |
| Agents | Azure CLI 2.30 or later on self-hosted agents; older versions fail with unrecognized arguments: --federated-token |
| Tasks | Current task versions (see the task table below); marketplace tasks only if the publisher has added federation support |
| Tenant policy | No Entra policy blocking federated credentials for your organisation's issuer; otherwise you see AADSTS700223 or AADSTS700238 |
Choosing the identity type
| Option | Choose it when | Trade-off |
|---|---|---|
| App registration (automatic) | You hold Owner on the subscription and want Azure DevOps to create the identity, credential and role assignment | Fastest, but the default role it assigns is broad; you must right-size it afterwards |
| Managed identity (existing user-assigned identity) | You cannot create app registrations, or the identity should live in a resource group with the workload | You create the identity and role assignment yourself; it cannot be used for Microsoft Graph or multi-tenant work |
| App registration or managed identity (manual) | Automatic creation failed, the identity already exists, or you manage identities as code | Most steps; Microsoft advises using it only after the automatic option fails |
Two Entra limits shape the design: a maximum of 20 federated identity credentials per application or user-assigned managed identity, and no wildcards in any federated credential value. One identity per environment (for example dev, test and prod connections each on their own identity) keeps you far below the limit and keeps role assignments separate.
Step-by-step
Step 1 is read-only. Steps 2 to 4 add federated connections alongside the existing ones. Step 5 is reversible for seven days. Step 6 removes the old secret and is the point of no easy return.
- Inventory existing Azure Resource Manager connections. In each project, open Project settings > Service connections and record name, authentication scheme, identity, scope and whether it is shared. To do this at scale, call the Service Endpoints REST API per project:
For each result, recordGET https://dev.azure.com/{organization}/{project}/_apis/serviceendpoint/endpoints?type=azurerm&api-version=7.1authorization.scheme(ServicePrincipalmeans a secret or certificate;WorkloadIdentityFederationmeans federated),isSharedandserviceEndpointProjectReferences(cross-project use blocks in-place conversion),createdByandisReady. Microsoft's bulk conversion script obtains an Azure DevOps token withaz login --allow-no-subscriptions --scope 499b84ac-1321-427f-aa17-267ca6975798/.default, which avoids creating a PAT. - Sort every connection into a route. Automatically created, single-project, secret-based: convert (step 5). Manually created, shared across projects, or cross-tenant: rebuild with a new manual federated connection (step 3 or 4). Federated but on the Azure DevOps issuer: edit and save the connection so it moves to the Entra issuer; for identities Azure DevOps created, Microsoft says the issuer updates automatically, otherwise update the federated credential yourself.
- Create a new connection with automatic app registration. Project settings > Service connections > New service connection > Azure Resource Manager > Next. Choose App registration (automatic) with credential Workload identity federation, set Scope level to Subscription and pick a Resource group (optional, but it narrows the role assignment), enter the name, leave Grant access permission to all pipelines cleared, and Save.
- Or create a manual connection on a managed identity. This follows Microsoft's documented order:
- In the Azure portal, create a user-assigned managed identity under Managed Identities > Create, then copy its Client ID, Subscription ID and the Tenant Id from Settings > Properties.
- In Azure DevOps, create a new Azure Resource Manager connection with App registration or Managed identity (manual) and Workload identity federation. Under Basics enter the name and Directory (tenant) ID. On the next page copy the generated Issuer and Subject identifier, set the scope, enter the identity's Client ID under Application (client) ID, and select Keep as draft.
- On the managed identity, open Settings > Federated credentials > Add credentials, choose Other issuer, paste the Issuer and Subject identifier, select Explicit subject identifier, name it and Add. As code, the same credential is:
For an app registration, useaz identity federated-credential create \ --name ado-prod-deploy \ --identity-name id-ado-prod-deploy \ --resource-group rg-pipeline-identities \ --issuer "<Issuer copied from Azure DevOps>" \ --subject "<Subject identifier copied from Azure DevOps>" \ --audiences api://AzureADTokenExchangeaz ad app federated-credential create --id <appId> --parameters credential.jsonwithname,issuer,subjectandaudiencesin the JSON. - On the target resource group, Access control (IAM) > Add role assignment, and assign the narrowest role that the pipeline needs.
- Back in Azure DevOps, open the draft, select Finish setup, then Verify and save.
- Convert eligible existing connections. Select the connection, then Convert, and confirm. Conversion takes a few minutes. For many connections, Microsoft publishes a PowerShell 7.3 script that lists automatic, secret-based
azurermconnections and callsPUT .../_apis/serviceendpoint/endpoints/{id}?operation=ConvertAuthenticationScheme&api-version=7.1with the scheme set toWorkloadIdentityFederation. Run it per project, starting with a non-production one. - Remove the old credential. Once every dependent pipeline has run on the federated connection, delete the client secret or certificate from the app registration (and delete any rebuilt connection's predecessor). Until you do, the secret still works from anywhere.
Pipeline changes
Most YAML needs no change: tasks reference the connection by name in azureSubscription. Scripts that log in themselves do need attention. With AzureCLI@2, setting addSpnToEnvironment: true exposes servicePrincipalId, tenantId and, for federated connections, idToken instead of servicePrincipalKey. Any script that read $servicePrincipalKey to call az login or Terraform must switch to the token. Only enable addSpnToEnvironment where a tool genuinely needs it, because it puts a usable token in the script's environment.
| Task status | Examples (from Microsoft's troubleshooting page) | Action |
|---|---|---|
| Supported | AzureCLI@2, AzurePowerShell@5, AzureKeyVault@2, AzureFunctionApp@2, AzureFileCopy@6, Docker@2, KubernetesManifest@1 | None |
| Upgrade required | AzureFileCopy@1 to @5 (use @6), Kubernetes@0 (use @1), KubernetesManifest@0 (use @1), AzureCloudPowerShellDeployment@1 (use @2), AzureMonitor@0 (use @1) | Change the task version in YAML before converting |
| Not supported | AzureNLBManagement@1, ServiceFabricDeploy@1, ServiceFabricComposeDeploy@0 | Keep a documented exception or replace the step |
| Marketplace tasks | Third-party extensions | Ask the publisher; errors such as "Identity not found" or "Could not fetch access token for Azure" indicate no support |
Verify it worked
- Connection state: the connection shows Workload identity federation, and the REST call returns
authorization.schemeofWorkloadIdentityFederation. - Pipeline run: a run that uses the connection completes every Azure step. Check the Usage history tab of the connection to confirm which pipelines used it.
- Entra sign-ins: sign-ins for the identity appear in the Entra sign-in logs under service principal or managed identity sign-ins, with no client secret or certificate credential type for that app after cut-over.
Rollback and common errors
For a converted connection, select Revert conversion to the original scheme and confirm within seven days of conversion; after that you would have to create a new secret manually. For a rebuilt connection, rollback is pointing the pipeline back at the old connection, which is only possible while its secret exists, so delete secrets last.
| Error | Meaning | Fix |
|---|---|---|
| AADSTS700213: no matching federated identity record for presented assertion subject | Subject on the credential does not match | Re-copy the Subject identifier from the connection; renaming an organisation, project or connection changes old-format subjects |
| AADSTS700211: no matching record for presented assertion issuer | Issuer wrong or missing | Edit and save the connection; update the issuer on identities Azure DevOps did not create |
| AADSTS70021: no matching federated identity record | Wrong issuer or subject, or replication delay after creation | Wait several minutes, then check both values |
| AADSTS70025: no configured federated identity credentials | Credential never created | Add the federated credential to the app or managed identity |
| AADSTS700016: application not found | Identity deleted or wrong client ID | Correct the Application (client) ID |
| AADSTS700024: client assertion not within its valid time range | Long-running job used the token after it expired | Request tokens early in the script; for jobs over about an hour, use a managed identity connection |
| AADSTS70052: identity must be a managed identity, a single tenant app or a service account | Multi-tenant app registration | Use signInAudience: AzureADMyOrg and one connection per tenant |
| AADSTS700223 or AADSTS700238 | Tenant policy restricts federation | Ask the Entra administrator to allow federation for your Azure DevOps organisation |
Issuer and subject formats differ between the two issuers, which matters when you maintain credentials as code:
| Azure DevOps issuer (deprecated) | Microsoft Entra issuer | |
|---|---|---|
| Issuer | https://vstoken.dev.azure.com/<organization id> | https://login.microsoftonline.com/<tenant id>/v2.0 |
| Subject | sc://<org>/<project>/<service connection name> | <entra prefix>/sc/<organization id>/<service connection id> |
| Rename sensitivity | Breaks when organisation, project or connection is renamed | Built from IDs, so renames do not change it |
Hardening afterwards
- Right-size the role: automatic creation and Microsoft's examples use Contributor. Replace it with the narrowest built-in or custom role at resource group or resource scope. See How to find over-privileged Azure managed identities.
- Authorise pipelines individually: keep Grant access permission to all pipelines off and approve each pipeline with Permit when it first requests the connection.
- Add checks on production connections: on the Approvals and checks tab add Branch control with fully qualified branches such as
refs/heads/mainand require branch protection, plus Approvals for production stages. Checks are set in the web UI and cannot be bypassed from YAML. This is the main control against a poisoned pipeline using a trusted connection; see the OWASP CI/CD Top 10 CICD-SEC-4 Poisoned Pipeline Execution Guide. - Separate identities per environment: dev and prod connections should never share an identity, so a compromised dev pipeline cannot reach prod roles.
- Control who edits federated credentials: anyone who can add a credential to the identity can point it at another issuer. Restrict app ownership and Managed Identity Contributor rights, and alert on credential changes.
Small estate or large organisation
A single team with a few projects can convert in the portal: inventory by hand, convert, run each pipeline, delete secrets. A large organisation should script the inventory, give each connection an owner, convert with Microsoft's bulk script in waves (non-production first), manage federated credentials and role assignments as code reviewed in pull requests, and keep a register of exceptions for unsupported tasks and sovereign clouds, each with a review date.
Detection and measurement
Watch both sides of the trust. In Azure DevOps, stream the audit log to your SIEM and review service connection creation, sharing, permission changes and enable or disable events (the audit log records disable and enable). In Entra, alert on new or changed federated credentials and client secrets on pipeline identities, and on sign-ins by those identities that do not come from your pipelines. See the Workload Identity Federation Guide for the wider model.
- Federation coverage: percentage of Azure Resource Manager connections with scheme
WorkloadIdentityFederation(target 100% outside documented exceptions). - Issuer migration: number of federated connections still on
vstoken.dev.azure.com(target zero well before 1 July 2027). - Residual secrets: client secrets and certificates still present on pipeline app registrations (target zero).
- Open connections: connections with access granted to all pipelines (target zero).
- Protected production: production connections with branch control and approvals (target 100%).
Common failure patterns
- Converting but never deleting the secret. The connection is federated, but the old client secret on the app registration still authenticates from anywhere until it expires.
- Keeping the automatic Contributor role. The secret is gone, yet a compromised pipeline still has write access to the whole subscription.
- Leaving "Grant access permission to all pipelines" on. Any pipeline in the project, including one built from a feature branch, can use the production identity.
- Missing the revert window. Teams convert, find a broken legacy task weeks later, and discover that the seven-day revert has passed. Upgrade task versions before converting.
- Scripts still reading
servicePrincipalKey. Terraform or custom login steps fail after conversion, and someone "fixes" it by adding a new secret to a variable group.
Framework mapping
| Framework | Reference | How this procedure supports it |
|---|---|---|
| NIST SP 800-53 Rev 5 | IA-5, IA-5(7) | Removes static secrets from pipeline configuration and replaces them with short-lived tokens |
| NIST SP 800-53 Rev 5 | AC-6, CM-3 | Narrow roles per environment; changes to connections and credentials through change control |
| NIST CSF 2.0 | PR.AA-01, PR.AA-05 | Pipeline identities and credentials are managed; access is least privilege and reviewed |
| CIS Controls v8.1 | Control 5 (Account Management), Control 6 (Access Control Management) | Inventory of service accounts and their access |
| ISO/IEC 27001:2022 Annex A | 5.17 Authentication information, 8.2 Privileged access rights | Authentication information is managed and privileged rights restricted |
| MITRE ATT&CK v20 | T1552.001, T1078.004, T1098.001 | Removes credentials in files to steal, limits valid cloud account abuse, and monitoring catches added cloud credentials |
Practitioner checklist
- Inventory every
azurermconnection per project with scheme, issuer, identity, scope and sharing. - Upgrade task versions that need it before converting anything.
- Convert eligible connections in a non-production project first and run every dependent pipeline.
- Rebuild manual and cross-project connections on a managed identity or app registration with workload identity federation.
- Move remaining federated connections from the Azure DevOps issuer to the Entra issuer well before 1 July 2027.
- Delete old client secrets and certificates after cut-over, and remove any copies in variable groups.
- Replace Contributor with the narrowest role at resource group scope.
- Turn off access for all pipelines; add branch control and approvals on production connections.
- Alert on federated credential and secret changes on pipeline identities, and stream Azure DevOps audit events to the SIEM.
Standards and references
- Microsoft Learn: Connect to Azure with an Azure Resource Manager service connection
- Microsoft Learn: Manually set an Azure Resource Manager workload identity service connection
- Microsoft Learn: Troubleshoot Azure Resource Manager workload identity service connections
- Microsoft Learn: Important considerations and restrictions for federated identity credentials
- Microsoft Learn: AzureCLI@2 task reference
- Microsoft Learn: Define approvals and checks
- Microsoft Learn: Service Endpoints REST API, Get Service Endpoints
- Microsoft Learn: az identity federated-credential
Related NHI Mgmt Group resources: Azure DevOps PATs and service connections security, How to replace Azure app secrets with federated credentials, Azure Managed Identities Security Guide, CI/CD Pipeline Identity Security Guide, Azure DevOps Security Guide.