When a CI OIDC login fails, check four things in order: the job may not be allowed to request a token, the audience may not match, the subject may not match the trust condition, or the trust policy may reference the wrong format. Most failures are a subject mismatch.
Step 1: can the job request a token at all?
On GitHub Actions, the job needs the id-token: write permission. GitHub's documentation says that without it the OIDC token cannot be requested. Add the token permission at the workflow or job level for the job that needs it.
Symptom: the login step reports that it could not get an ID token.
Step 2: does the audience match?
Compare the token's aud to what the provider expects. For AWS with GitHub's official action the audience is sts.amazonaws.com. For Microsoft Entra the recommended value is api://AzureADTokenExchange. For GitLab, if you did not set aud in id_tokens, it defaults to the GitLab instance domain, and GitLab calls a missing or mismatched audience a common cause of 401 errors.
Step 3: does the subject match?
This is the usual culprit. Print the claims in a throwaway test job, never in production logs, and compare the subject with the trust condition character by character.
| Trigger | Subject you should expect on GitHub |
|---|---|
| Job with an environment | repo:ORG/REPO:environment:NAME |
| Pull request, no environment | repo:ORG/REPO:pull_request |
| Branch push, no environment | repo:ORG/REPO:ref:refs/heads/BRANCH |
Common mismatches:
- The job references an environment, so the subject has the environment name and no branch, but the policy expects a branch.
- The policy was written for a pull request event, and the deploy runs on push.
- The repository was renamed or transferred. GitHub says renames and transfers after 15 July 2026 move to an immutable subject format that includes owner and repository IDs.
- The repository was created after 15 July 2026, so it uses the immutable format by default, but the policy uses the older format.
- On GitLab, the project path changed, or an old path is blocked until you switch to an ID based subject.
Microsoft adds a trap: in Entra, an incorrect subject in a federated credential is accepted at creation, and the failure shows only at token exchange, without an informative error. Wildcards are not supported there either.
Step 4: is the trust policy otherwise right?
On AWS, check that the OIDC provider exists in the account, that the role's trust policy names that provider as the principal, and that conditions use the right condition key prefix for the provider. Check the role's maximum session duration if the job requests a custom length. If the job chains roles, AWS caps the chained session at one hour and fails calls requesting more.
Step 5: look at the logs
On AWS, CloudTrail logs AssumeRoleWithWebIdentity calls, but AWS notes some invalid unauthenticated STS requests might not be logged at all. If you see nothing in CloudTrail, the request may be failing before it is trusted, which points back to audience, issuer or token format.
A short routine
- Confirm the token permission.
- Print the claims in a test job.
- Diff audience and subject against the trust condition.
- Fix the condition to an exact match, not a wildcard, even if a wildcard makes the error disappear.
- Retest from the real trigger, such as a merge, not only a manual run.
Resist the urge to widen the trust policy to get unblocked. A wildcard that fixes today's failure may let a pull request assume a production role next month.
Quick check
Why does my deploy fail only from the environment job?
The subject includes the environment name when a job references one, and the branch is absent. Update the trust condition to the environment form.
Is it safe to loosen the subject to a wildcard to unblock a release?
Avoid it. GitHub's AWS guide notes a repository wildcard lets any branch, pull request merge branch or environment assume the role.
Safeguard does not manage your cloud accounts. It scans your code and dependencies, applies pull request policies and gates, and automates compliance evidence. Free scan: gold.safeguard.sh/scan.
Sources
- GitHub Docs: OpenID Connect reference
- GitHub Docs: OIDC in Amazon Web Services
- GitLab Docs: ID token authentication
- Microsoft Learn: Create a trust relationship between an app and an external identity provider
- AWS IAM User Guide: Logging IAM and AWS STS API calls with AWS CloudTrail
Last reviewed: 19 October 2026.