Since fall 2023, it has been possible to use Workload Identity Federation for Azure service connections (public preview started in September 2023). Besides a short introduction to workload identity federation, this post shows how to automatically create service connections with authentication method Workload Identity Federation using terraform.
Let’s dive right into the topic.
What is Workload Identity Federation
In supported scenarios, workload identity federation allows you to access Microsoft Entra protected resources without having to care about secret management. It’s an OpenID Connect (OIDC) implementation which in context of Azure DevOps allows you to use short-lived credential free authentication to Azure.
Why should I use it?
To avoid the following error message and because it’s the recommended authentication method.
[error]Could not fetch access token for Azure. Verify if the Service Principal used is valid and not expired. For more information refer https://aka.ms/azureappservicedeploytsg
How does it work?
It’s about creating a trust relationship between an external Identity Provider (IdP) and a user-assigned managed identity or application (app registration) in Microsoft Entra ID.
A federated identity credential can either be configured on a user-assigned managed identity or on an app registration. The federated identity credential is used to specify which token from the external IdP should be trusted by your application or managed identity.
For more details see here.
Restrictions / Limitations
In context of Azure DevOps service connections be aware of the following restrictions / limitations.
- Not all pipeline tasks support authentication method
Workload Identity Federation
i.e.Synapse workspace deployment@2doesn’t - Azure DevOps extensions that changed the owner before authentication method
Workload Identity Federationgot generally available may need to be replaced
i.e.Azure Pipelines Terraform Tasks
If you face any problems, see Troubleshoot an Azure Resource Manager workload identity service connection
Existing Azure DevOps Service Connections
Existing Azure DevOps Service connections of type Azure Resource Manager can easily be converted to use authentication method Workload Identity Federation.


Create Azure DevOps Service Connections using terraform
Instead of creating service connections in Azure DevOps manually by clicking around in wizards, they can also be created automatically using terraform. The following example uses different terraform providers to create a private Azure DevOps project ExampleProject with Git version control, an app registration with name ExampleAppReg and federated identity credential in Azure and a service connection with authentication method Workload Identity Federation in Az DevOps.
terraform {
required_version = "~> 1.6.6"
required_providers {
azuread = {
source = "hashicorp/azuread"
version = "~> 2.48.0"
}
azuredevops = {
source = "microsoft/azuredevops"
version = ">= 1.0.1"
}
}
}
variable "organization_url" {
type = string
description = "URL of Azure DevOps organization"
}
variable "personal_access_token" {
type = string
description = "Azure DevOps personal access token with scopes Project and Team 'Read, write & manage'; Code 'Read, write & manage'; Service Connections 'Read, query, & manage'"
}
variable "subscription_name" {
type = string
description = "Azure subscription name"
}
variable "subscription_id" {
type = string
description = "Azure subscription ID"
}
variable "tenant_id" {
type = string
description = "Microsoft Entra ID tenant ID"
}
provider "azuread" {
tenant_id = var.tenant_id
}
# IMPORTANT NOTE: try to use service principal authentication for azuredevops provider instead of Personal Access Token (PAT)!
# If you still use PAT authentication, make sure you don't hardcode the PAT and don't commit it to your source code repository!
provider "azuredevops" {
org_service_url = var.organization_url
personal_access_token = var.personal_access_token
}
resource "azuredevops_project" "example_project" {
name = "ExampleProject"
visibility = "private"
version_control = "Git"
work_item_template = "Agile"
description = "Managed by Terraform"
}
resource "azuread_application" "example_appreg" {
display_name = "ExampleAppReg"
}
resource "azuredevops_serviceendpoint_azurerm" "example_service_connection" {
project_id = azuredevops_project.example_project.id
service_endpoint_name = "example-federated-sc"
description = "Managed by Terraform"
service_endpoint_authentication_scheme = "WorkloadIdentityFederation"
credentials {
serviceprincipalid = azuread_application.example_appreg.client_id
}
azurerm_spn_tenantid = var.tenant_id
azurerm_subscription_id = var.subscription_id
azurerm_subscription_name = var.subscription_name
}
resource "azuread_application_federated_identity_credential" "example_federated_identity_cred" {
display_name = "example-federated-identity-credential"
application_id = azuread_application.example_appreg.id
audiences = ["api://AzureADTokenExchange"]
issuer = azuredevops_serviceendpoint_azurerm.example_service_connection.workload_identity_federation_issuer
subject = azuredevops_serviceendpoint_azurerm.example_service_connection.workload_identity_federation_subject
}
Inspired by How to configure Workload identity federation using the Azure DevOps Terraform provider
The above example terraform code can be executed as follows.
terraform init terraform plan -var tenant_id="TENANT_ID" -var subscription_id="SUBSCRIPTION_ID" -var subscription_name="SUBSCRIPTION_NAME" -var organization_url="https://dev.azure.com/ORGANIZATION_NAME/" -var personal_access_token="PERSONAL_ACCESS_TOKEN" terraform apply -var tenant_id="TENANT_ID" -var subscription_id="SUBSCRIPTION_ID" -var subscription_name="SUBSCRIPTION_NAME" -var organization_url="https://dev.azure.com/ORGANIZATION_NAME/" -var personal_access_token="PERSONAL_ACCESS_TOKEN"
The properly modularized source code can be found on GitHub.

