skip to content

Why must a cloud workload identity pool pin the audience of a CI OIDC token to its own value?

level: middleimportance: should knowfreq 44%

answer

  1. who is the token addressed to
  2. bearer tokens travel with whoever holds them
  3. a signature does not name a recipient
  4. same default value, many recipients
  5. distinct audience per relying party

basics

~20 s

The audience claim is the only thing naming who may consume a bearer identity token. If the pool accepts a generic default that other relying parties also accept, any of them can replay a token the build handed them.

solid answer

~50 s

An OIDC identity token names its intended recipient in the `aud` claim, and a relying party is supposed to reject any token that does not name it. If a workload identity pool validates the issuer and subject but leaves the audience at a generic default, it will honour any token from that build - including one the build legitimately minted for somebody else. That is the realistic attack: a pipeline authenticates to a third-party managed service with a federated token; that service is compromised, or simply logs the token; the operator now holds a signed assertion that your cloud accepts, and can assume the role and reach the data store behind it. Fix it by minting a distinct audience per relying party, requiring exact equality on it, and keeping token lifetimes short so a captured assertion is useful for minutes rather than the whole day.

go deeper

for a junior

Know that the audience claim says who a token was minted for, and that a recipient is expected to refuse tokens not addressed to it. Recognising it as one of the values a trust configuration pins is enough here.

for a middle

Explain replay concretely: why a signature and a correct subject do not stop a second recipient reusing the assertion, and why a distinct audience per relying party plus a short lifetime does.

for a senior

Reason about the token's whole path. Enumerate every party a build hands an identity token to, treat each as capable of impersonating the build, and set audiences to match the trust boundaries you actually have.

for a principal

Make it a rule for onboarding any federated integration: a named audience per relying party, exact matching, and a review question about what each recipient could do with the token it receives.

## The claim nobody reads Of the three claims a federated trust decision rests on, the audience is the one most often left at whatever value the tooling suggested. It is also the one that fails silently: an over-broad audience never breaks a build, never shows up in a scan of permissions, and only matters on the day a token reaches somewhere you did not intend. `aud` names the intended recipient of an identity token. The rule in the underlying token spec is blunt: if the recipient does not identify itself in the audience, it must reject the token. That single rule is what turns a signed description of a workload into something addressed to *one* party rather than a general-purpose credential. ## Why signature and subject do not cover it It helps to see exactly what the other two claims do not do. - **The signature** proves the issuer minted the claims. It says nothing about who was supposed to receive them. A valid signature is exactly as valid in the hands of a thief. - **The subject** proves which workload the token describes - the right repository, the right environment. It is *still* the right repository when somebody else presents the token. Subject answers *who is this about*, never *who may consume this*. So audience is not a third redundant check; it is the only anti-replay property in the set apart from expiry. ## The realistic scenario Modern builds hand identity tokens to more than one party. A deployment job federates into the cloud tenant. The same job also authenticates to a managed service - an external test environment, an analytics or data-processing vendor, a partner API - that has adopted the same federated pattern precisely because nobody wants to exchange static keys any more. Each of those is a relying party. Now suppose the cloud pool accepts a generic default audience value. The build requests one token and reuses it for both hops, or requests two tokens that both carry that default value. The vendor now holds a signed assertion that your cloud will accept. Nothing has to be *attacked* for this to go wrong: an over-retentive log, a support bundle, or an ordinary compromise of that vendor is enough. The holder presents the assertion to your identity pool, satisfies issuer and subject conditions, and receives credentials for the role - along with everything behind it. The attacker here is not an anonymous internet stranger and the asset is not a web session; it is a legitimate token recipient turning into an impersonator of your build, and the asset is your cloud credentials and the data store they reach. The symmetric case is worth naming too: if *your* cloud is one of several recipients that all accept the same default, you are on the other side of that trade for someone else. ## Doing it properly 1. **One audience per relying party.** Give the cloud tenant an audience value that is meaningful and specific to it, and configure a different one for every other consumer. The value itself is not secret - its job is to be distinct. 2. **Exact equality.** Match the audience exactly. A pattern or prefix match reintroduces the problem in a form that looks configured. 3. **A token per hop.** The build should request a fresh token for each recipient rather than caching one and reusing it. This is the operational cost of the control, and it is small. 4. **Short lifetimes.** Audience limits *where* a captured assertion works; expiry limits *when*. Together they make a leaked token close to worthless. 5. **Treat every recipient as a potential impersonator.** Before adding a new relying party, ask what it would mean if that party could present its token to each of your others. If the answer is "it could deploy", the audiences are wrong. ## What it does not fix Audience pinning does not narrow *which* workloads may assume the role - that is the subject condition's job - and it does not limit what the role can do once assumed. It also does not help if the same audience is shared across environments: a token minted for a staging relying party with the production audience value is production's problem. Keep the audience aligned with the trust boundary you actually care about, and check it in the same review that checks the subject.

  • If the subject is already pinned to exactly one repository and environment, why does the audience still matter?
    Because the subject describes the workload, not the permitted consumer. A token that truthfully says "this is the payments repository, production environment" says the same thing when a third party replays it. The audience condition is the only claim that asks whether this recipient was meant to see the assertion at all.
  • What is the operational cost of a distinct audience per recipient?
    The job has to request a separate token for each hop instead of minting one and reusing it, and someone has to keep the audience values documented so a new integration does not quietly reuse an existing one. That is a small, one-time cost per integration, which is why reusing a single default is a habit rather than a constraint.
  • Is the audience value a secret?
    No. It is an identifier, not a credential - it appears in configuration on both sides and in the token itself. Its security value comes from being distinct and exactly matched, so a token addressed to one party is inert everywhere else. Treating it as a secret is a sign someone has misunderstood what it does.

saying these in an interview costs you the question

  • Treats the audience claim as cosmetic metadata
  • Thinks a validly signed token is safe to present anywhere
  • Says pinning the subject makes the audience redundant
  • Assumes only the cloud provider ever receives the token
  • Calls the audience value a secret that must be rotated

context