GitLab CI id_tokens for AWS and Azure: the sub claim and the trust policy that matches it
GitLab CI/CD does not hand a job an OIDC token by default. You ask for one with the id_tokens keyword, and what your AWS role, Azure federated credential or Google Cloud pool sees is whatever the sub and aud in that token say. This page lists what GitLab's documentation (read on 13 Oct 2026) says the token contains, the one trap that breaks merge request pipelines, and how to write a trust policy that matches.
What GitLab puts in the token
| Field | Default | Can you change it? |
|---|---|---|
Issuer (iss) | The domain of the GitLab instance: https://gitlab.com on GitLab.com, your own domain on self-managed | No |
Audience (aud) | The domain of the GitLab instance | Yes: set aud per token under id_tokens in the job |
Subject (sub) | project_path:{group}/{project}:ref_type:{type}:ref:{branch_name} | Yes: configurable per project through the projects API |
| Lifetime | The job's timeout if one is set, otherwise 5 minutes | Through the job timeout |
| Signing | RS256, keys at https://gitlab.com/oauth/discovery/keys | No |
Example subject from GitLab's page: project_path:my-group/my-project:ref_type:branch:ref:feature-branch-1. For GitLab 18.7 and later the docs add that the sub "can include additional fields such as ref_protected" and, for jobs with an environment, environment_protected and deployment_tier. If your instance is on 18.7 or later, print a real token before you write the policy, because a pattern written from the older example may stop at the first extra field.
Asking for a token
Add id_tokens to the job, name the variable, and set the audience your cloud expects. The names below are ours, not GitLab's:
deploy:
id_tokens:
CLOUD_TOKEN:
aud: sts.amazonaws.com
script:
- echo "use $CLOUD_TOKEN with your cloud's token exchange"
Do not print the token in a shared log. It is short lived, but it is a bearer credential while it is valid. For debugging, copy one into the OIDC token debugger, which decodes it in your browser and sends nothing anywhere.
The AWS trust policy
With the GitLab.com issuer registered as an IAM OIDC provider, a role that only the main branch of one project may assume looks like this (our example; replace the group and project, and make the audience equal the one in the job):
"Condition": {
"StringEquals": {
"gitlab.com:aud": "sts.amazonaws.com",
"gitlab.com:sub": "project_path:my-group/my-project:ref_type:branch:ref:main"
}
}
AWS documents StringEquals as "Exact matching, case sensitive", and StringLike as case-sensitive matching where the value "can include multi-character match wildcards (*) and single-character match wildcards (?) anywhere in the string". To allow every branch of the project, use StringLike with project_path:my-group/my-project:ref_type:branch:ref:*. Never use a bare * for the project part: every project on the same GitLab would match.
Trap 1: merge request pipelines have a different project and ref
GitLab's claim table says that in a merge request pipeline project_path is "the path of the source project". So a policy pinned to ref_type:branch:ref:main in the target project does not match a job running in an MR pipeline, whose subject describes the source project and source branch. If MR pipelines need cloud access, decide deliberately which source branches may have it; do not widen the pattern to * to make the error go away.
Trap 2: self-managed GitLab has only sub on AWS
GitLab's page says claims such as namespace_id and project_id are not available as AWS condition keys "for GitLab Self-Managed or GitLab Dedicated, where only the sub claim is supported as an AWS condition key". If you copied a tutorial that conditions on gitlab.com:project_id, it works on GitLab.com and not on your own instance. Put the project into the sub condition instead.
Azure and Google Cloud
- Microsoft Entra. A standard federated credential compares issuer, subject and audience exactly and case-sensitively, and "wildcard characters aren't supported in any federated identity credential property value". Create one credential per subject, or use a flexible federated identity credential (a preview feature), which Microsoft says supports GitLab-issued tokens and lets one credential match many branches with an expression. The subject field is limited to 600 characters, which matters if you customise the
sub. The recommended audience isapi://AzureADTokenExchange, so set the job'saudto that. - Google Cloud. Map
google.subjectto a claim that is unique and cannot change; Google limits mapped attributes to 127 bytes, so a long customsubcan be too big to map.
Check a policy before you deploy
Paste the token and the sub from your trust policy into the debugger. It names GitLab from iss, splits the subject into its parts, and reports the first character where your pattern and the token differ. If the job already fails, work through the six-step checklist for "Not authorized to perform sts:AssumeRoleWithWebIdentity". The free MIT token decoder does the matching offline, and the CI OIDC Atlas ($12) puts GitLab next to ten other CI platforms with the vendor sentence behind every cell, for teams that run more than one.
Sources read 13 Oct 2026: GitLab Docs, "Use ID tokens to authenticate with third-party services"; AWS IAM documentation, condition operators; Microsoft Entra documentation on federated credentials and flexible federated identity credentials; Google Cloud, workload identity federation with other providers. Formats change between GitLab versions; re-read the current page before relying on a detail.