GitHub Actions OIDC Failure¶
Symptom¶
GitHub Actions deployment jobs fail during Azure sign-in or before the Container Apps deployment step runs. The workflow often reports AADSTS70021: No matching federated identity record found for presented assertion. and the job never obtains an Azure access token.
flowchart TD
A[GitHub Actions job requests OIDC token] --> B[Azure validates issuer audience and subject]
B --> C{Federated credential matches exactly?}
C -->|No| D[AADSTS70021 returned]
C -->|Yes| E[Azure issues access token]
E --> F[Workflow deploys Container App]
D --> G[Check issuer audience subject and propagation] Possible Causes¶
- The federated credential subject does not exactly match the repository and branch pattern used by the workflow.
- The issuer is not
https://token.actions.githubusercontent.com. - The audience is not
api://AzureADTokenExchangefor the public Azure cloud scenario documented by Microsoft Learn. - The workflow references the wrong Microsoft Entra application or service principal.
- The federated credential was just created and directory replication has not completed yet.
Diagnosis Steps¶
- Confirm the workflow is using OpenID Connect instead of a client secret.
- Inspect the Entra application and list its federated identity credentials.
- Compare the configured
issuer,audiences, andsubjectwith the workflow branch and repository. - Retry once after a short wait if the credential was recently created.
az ad app show \
--id "<app-id>"
az ad app federated-credential list \
--id "<app-id>"
az rest \
--method GET \
--uri "https://graph.microsoft.com/v1.0/applications(appId='<app-id>')/federatedIdentityCredentials"
| Command | Why it is used |
|---|---|
az ad app show --id "<app-id>" | Confirms the target application object used for federation. |
az ad app federated-credential list --id "<app-id>" | Lists federated credentials so you can inspect issuer, audience, and subject values. |
az rest --method GET --uri "https://graph.microsoft.com/v1.0/applications(appId='<app-id>')/federatedIdentityCredentials" | Retrieves the raw Microsoft Graph representation when you need exact claim details. |
Use this matching rule for a branch-based workflow:
issuer: https://token.actions.githubusercontent.com
audience: api://AzureADTokenExchange
subject: repo:<ORG>/<REPO>:ref:refs/heads/<BRANCH>
Resolution¶
- Update the federated identity credential so the subject exactly matches the GitHub repository and ref used by the deployment workflow.
- Confirm the issuer and audience follow the Microsoft Learn guidance for GitHub Actions OIDC.
- If the credential was created moments ago, wait briefly and rerun the workflow.
- Keep branch-specific and environment-specific credentials explicit instead of relying on guessed patterns.
Example credential payload:
{
"name": "github-main",
"issuer": "https://token.actions.githubusercontent.com",
"subject": "repo:contoso/aca-guide:ref:refs/heads/main",
"audiences": [
"api://AzureADTokenExchange"
]
}
| Command | Why it is used |
|---|---|
az ad app federated-credential create --id "<app-id>" --parameters "credential.json" | Creates or re-creates the federated credential with an exact JSON payload instead of relying on a partial manual configuration. |
Prevention¶
- Treat the federated credential subject as an exact string contract, not a fuzzy pattern.
- Keep GitHub branch names, protected environments, and Entra credential definitions aligned in IaC or scripted provisioning.
- Add a pre-deploy validation step that lists the app's federated credentials before changing the pipeline.
- After creating or updating the credential, allow for propagation before declaring the pipeline broken.
See Also¶
- GitHub Actions OIDC Failure Lab
- Managed Identity Authentication Failure
- Revision Provisioning Failure