Skip to content

Service Connections

ado-aw pipelines use Azure Resource Manager (ARM) service connections to mint Azure DevOps-scoped tokens at runtime. These tokens grant the pipeline controlled access to ADO APIs — separately for the agent (read) and the executor (write).

The compiled pipeline uses the AzureCLI@2 task to call az account get-access-token --resource 499b84ac-1321-427f-aa17-267ca6975798 — this mints a short-lived ADO token scoped to the service connection’s identity. This keeps credentials short-lived and auditable, and avoids storing long-lived PATs.

ConnectionUsed byPurpose
Write (optional override)Stage 3 — SafeOutputs executorOverride the default $(System.AccessToken) for cross-org writes or named-identity attribution
Read (optional)Stage 1 — AgentQuery ADO APIs (work items, repos, builds)

The write service connection overrides the default $(System.AccessToken) — use it when you need writes attributed to a named service principal, or for cross-org / cross-project safe outputs where the pipeline’s built-in token lacks sufficient scope.

  1. Go to your Azure DevOps Project → Project Settings → Service connections

  2. Click New service connection → Azure Resource Manager

  3. Choose your authentication method:

    The simplest option — Azure DevOps creates the app registration and credentials for you.

    • Select Service principal (automatic)
    • Choose an Azure subscription (the identity needs at least Reader on the subscription — this is only used for az login, not for ADO operations)
    • Scope to a resource group if preferred
    • Name the connection (e.g. ado-aw-write) — this is the value you’ll use in permissions.write
    • Click Save

    Azure DevOps creates an Entra ID app registration and configures everything automatically.

  4. Grant ADO permissions to the service principal. The identity behind the connection needs permission to perform write operations in Azure DevOps:

    • Go to Azure DevOps Organization Settings → Users
    • Add the service principal (search by its app registration name)
    • Set access level to Basic
    • Add it to a project-level group with the permissions your safe outputs need — Contributors is sufficient for most use cases (PRs, work items, branches, tags, wiki pages)
  5. Reference it in your agent front matter:

    permissions:
    write: ado-aw-write # ← name of the service connection you created

Create the read service connection (optional)

Section titled “Create the read service connection (optional)”

If your agent needs to query Azure DevOps APIs (e.g. read work items, list PRs, fetch build results), create a second connection with read-only ADO permissions.

Follow the same steps as above, but:

  • Name the connection ado-aw-read (or similar)
  • In ADO, grant the service principal Readers group access (or a custom group with only read permissions)

Then reference both in your agent file:

permissions:
read: ado-aw-read
write: ado-aw-write
ConfigurationAgent can read ADO?Safe outputs can write?
Both read + write✅ (ARM-minted identity)
Only read✅ (default System.AccessToken)
Only write✅ (ARM-minted identity)
Neither (default)✅ (default System.AccessToken)

On the first run, Azure DevOps will prompt you to authorize the pipeline to use the service connections. You can also pre-authorize:

  1. In the service connection’s settings, go to Security
  2. Under Pipeline permissions, click + and add your ado-aw pipeline (or grant access to all pipelines in the project)

To confirm your service connection can mint ADO tokens, create a test pipeline:

trigger: none
pool:
vmImage: ubuntu-latest
steps:
- task: AzureCLI@2
displayName: "Test ADO token mint"
inputs:
azureSubscription: 'ado-aw-write' # your connection name
scriptType: 'bash'
scriptLocation: 'inlineScript'
inlineScript: |
TOKEN=$(az account get-access-token \
--resource 499b84ac-1321-427f-aa17-267ca6975798 \
--query accessToken -o tsv)
if [ -n "$TOKEN" ]; then
echo "✅ Successfully minted ADO token (${#TOKEN} chars)"
else
echo "❌ Failed to mint ADO token"
exit 1
fi

If this pipeline succeeds, your connection is correctly configured for ado-aw.


SymptomLikely cause
AzureCLI@2 fails with “service connection not found”The pipeline isn’t authorized to use the connection — check pipeline permissions in the connection’s Security tab
Token mints but safe outputs return 401/403The service principal doesn’t have sufficient ADO permissions — verify its group membership in ADO Organization Settings → Users
”AADSTS700024: Client assertion is not within its valid time range”Federated credential issuer/subject mismatch — regenerate in the App Registration
Same-project safe-output writes return 403 with TF401027: ... 'PullRequestContribute'You’re on the default $(System.AccessToken) and the underlying build identity lacks PR-contribute (or has an explicit Deny) on the target repo. See the dedicated Safe-output 401/403 errors page for the diagnosis flow and three fix paths.
Cross-project safe-output writes fail with 403 even though default executor token usually worksThe pipeline setting “Limit job authorization scope to current project” is restricting $(System.AccessToken). Either disable it (broader scope) or set permissions.write to an ARM SC with explicit cross-project rights