Encrypt Online
Theme

Certificates & Site Ops

Fix AADSTS70021 and AADSTS700213 Federated Credential Errors

Compare issuer, subject, and audience to debug Entra federated credential errors in GitHub Actions and AKS. Includes Azure CLI commands and mismatch examples.

Encrypt Online Editorial Team5 min read
Encrypt Online guide cover on a sand background with the headline Fix federated credentials. The established OIDC discovery glyph represents the issuer and identity configuration.

For AADSTS70021 or AADSTS700213, compare the failing run's issuer (iss), subject (sub), and audience (aud) with the federated credential on its Azure application or managed identity. For a credential with a fixed subject, the values must match exactly. A missing slash, different case, or environment subject in place of a branch subject can cause the error.

Use the external OIDC assertion that GitHub Actions or Kubernetes sent to Entra. An Azure access token issued after the exchange contains different claims. Paste the assertion, or its decoded claims JSON, and the credential export into the Entra Federated Credential Debugger to see which values differ.

Export the app or managed identity's federated credentials

A federated identity credential names an external workload the application or managed identity trusts. Compare its fields with the incoming assertion:

Assertion claim Credential field
iss issuer
sub subject
aud audiences

These comparisons are case-sensitive. Microsoft's federated credential considerations describe the matching rules.

For an app registration, export the configured credentials with:

Shell
az ad app federated-credential list \
  --id "$AZURE_CLIENT_ID" \
  --output json

Set AZURE_CLIENT_ID to the client ID used by the failing workflow. The command reads the application's credentials without changing them. See the application FIC CLI reference for accepted identifiers.

For a user-assigned managed identity, list its credentials with:

Shell
az identity federated-credential list \
  --identity-name "$IDENTITY_NAME" \
  --resource-group "$RESOURCE_GROUP" \
  --output json

Run this read-only command in the subscription containing the identity used by the workflow. You can paste the whole list into the debugger; it looks for a matching credential among the entries. See the managed identity FIC CLI reference.

GitHub Actions: environment and branch subjects

Read the failed run's actual subject. Azure/login shows federated token details in its logs, and its troubleshooting section identifies subject mismatches behind AADSTS700213 and AADSTS7002138. Azure/login troubleshooting

For a repository using the name-based subject format, a main-branch subject and a production-environment subject look like this:

Text
repo:example-org/example-app:ref:refs/heads/main
repo:example-org/example-app:environment:production

Setting the job's environment to production can change its subject from the first value to the second. A credential configured for the branch won't match the environment subject. Compare the run's emitted sub with the credential's subject before changing either setting.

GitHub supports customized subject formats. Its current documentation also describes immutable owner and repository IDs in subjects for repositories created, renamed, or transferred after July 15, 2026. An existing repository may still use a name-based subject. Use the value emitted by the run; do not remove IDs or rebuild it from an older tutorial. GitHub OIDC subject reference

Tip: Copy iss, sub, and aud from the failing run into a small JSON object like the one below. Keep the values exactly as logged, including case and any owner or repository IDs.

For the synthetic production-environment example above:

JSON
{
  "iss": "https://token.actions.githubusercontent.com",
  "sub": "repo:example-org/example-app:environment:production",
  "aud": "api://AzureADTokenExchange"
}

Replace these example values with your run's claims before comparing them.

AKS: issuer URL, namespace, and service account

Check the final / in the issuer URL. Omitting it is a documented cause of AADSTS70021 in AKS. Compare the full iss from the token with the credential's issuer, including that slash. Workload identity troubleshooting

Read the cluster's configured OIDC issuer with:

Shell
az aks show --resource-group "$RESOURCE_GROUP" \
  --name "$CLUSTER_NAME" \
  --query oidcIssuerProfile.issuerUrl --output tsv

The usual Kubernetes subject is system:serviceaccount:NAMESPACE:SERVICE_ACCOUNT. Check both names against the service account used by the failing pod. The same service-account name in another namespace won't match. Microsoft's AKS workload identity setup shows how the issuer, service account, and identity are connected.

The token exchange audience

Compare the assertion's aud with the credential's audiences. This identifies the intended token-exchange recipient. Azure federation examples commonly use api://AzureADTokenExchange; use the audience configured for your environment and issuer.

If the workload requested a token for another audience, correct the token request or the intended trust configuration and obtain a new assertion. Editing the decoded JSON won't change the signed token. A Microsoft Graph access token also isn't the external assertion Entra expects here.

Credentials with claimsMatchingExpression

Some configurations use claimsMatchingExpression instead of a fixed subject. An expression can describe several allowed subjects. Comparing the literal expression text with sub does not evaluate that rule.

The debugger compares the issuer and audience but doesn't evaluate the expression. Check the subject rule against Microsoft's flexible federated credential reference. Keep the rule limited to the workloads that need access; a broad wildcard changes which workloads the identity trusts.

Client ID, propagation, and token exchange errors

If all three values match, confirm that the request's client ID and tenant point to the identity you exported. Azure must find the credential on that identity, and recent credential changes may still be propagating. It also checks the assertion's signature and validity.

If the error changes to AADSTS90061, check external OIDC discovery and key availability. For an assertion-validity error, check the assertion's start and expiry times. If the exchange succeeds but an Azure resource returns 403, check the identity's permissions on that resource. Adding another federated credential doesn't grant resource access.