GitHub Actions to Azure (OIDC handoff)

The handoff from a GitHub Actions job to Azure Resource Manager through workload identity federation — what each side must hold (id-token permission, client and tenant IDs, a federated credential matching issuer, subject and audience, a role at the deployment scope), the known-good configuration, the known-bad ones with their exact symptoms (including 2026 immutable subjects and pull-request jobs), and how to tell which side is wrong.

markdownpatternv1T2VF-VW2Xstage: buildtrust: officialservice: entraservice: rbacservice: managed-identityinterface: ciinterface: cliGitHub Actions Azure handoffOIDC GitHub to Entrafederated credential known-goodAADSTS700213 GitHub environmentpull_request subjectimmutable subject repository renamedid-token write missingContributor cannot assign roles pipelineazure/login v3deployment identity least privilegewhich side is wrong GitHub Azure

Created 21 Oct 2026 · Modified 23 Oct 2026 · 1 version

GitHub side: the job may request an OIDC token (id-token: write) and sends a token whose sub describes the job. Entra side: a federated credential on the identity matches that token exactly, and the identity holds a role at the scope the job deploys to. A failure is always one of those four facts.

Known-good

  • Identity: a user-assigned managed identity gh-deploy, one per repository and environment group.
  • Federated credential: issuer https://token.actions.githubusercontent.com, audience api://AzureADTokenExchange, subject repo:<org>/<repo>:environment:production (copied from a run's Federated token details).
  • Roles: Contributor on the target resource group. Plus, only if the job deploys role assignments, Role Based Access Control Administrator on the same group with a condition listing the role IDs it may assign.
  • Workflow: permissions: id-token: write, contents: read; the deploying job declares environment: production; azure/login@v3 with client-id, tenant-id, subscription-id from vars.*.

Known-bad

ConfigurationSymptom
No id-token: write (or set only on another job)Failed to fetch federated token from GitHub. Please make sure to give write permissions to id-token in the workflow.
Credential subject is …:ref:refs/heads/main, but the job declares environment: productionAADSTS700213 … presented assertion subject 'repo:<org>/<repo>:environment:production'
Only a branch credential exists, and the workflow also runs on pull_requestPR runs fail with AADSTS700213 for subject repo:<org>/<repo>:pull-request; pushes work
Repository created or renamed after July 15, 2026; credential uses the name-based subjectAADSTS700213 quoting repo:<org>@<id>/<repo>@<id>:…
Credential made in the portal with owner/repo IDs filled in; repository never opted in to immutable subjectsAADSTS700213 quoting the name-based subject
My-Org in GitHub, my-org in the credentialAADSTS7002138 … matches with case-insensitive comparison, but not with case-sensitive comparison.
First run seconds after creating the credentialAADSTS70021; passes on a re-run minutes later
client-id is the app's object ID, or another app's client IDAADSTS70021 or AADSTS700016
Identity has Contributor; the Bicep file contains roleAssignmentsLogin succeeds; deployment fails with AuthorizationFailed on Microsoft.Authorization/roleAssignments/write
Role on the resource group; the job also creates a new resource groupAuthorizationFailed on Microsoft.Resources/subscriptions/resourceGroups/write
No subscription-id and no allow-no-subscriptionsEnsure 'subscription-id' is supplied or 'allow-no-subscriptions' is 'true'.

Which side is wrong

  • The failure happens in the azure/login step:
  • Failed to fetch federated token… → GitHub side (permissions).
  • An AADSTS code → the federated credential, or the client ID the job sends. Compare Federated token details with az identity federated-credential list (reference/entra/federated-credential-errors.md).
  • Login succeeds, then a later step fails:
  • AuthorizationFailed → the role or its scope (reference/rbac/errors.md).
  • RequestDisallowedByPolicy → policy, not the pipeline (reference/policy/effects-and-errors.md).
  • Works on main, fails on PRs or tags → each trigger presents its own subject; add a credential per subject, or route deployments through an environment.

Read this document as markdown — the same bytes an agent receives.