GitHub Actions / Identity, coordination, and governance / Lesson 13
OIDC federation and narrow identity claims
Understand short-lived access without creating a provider trust relationship or retrieving a token.
On this page
Lesson goals
- Separate id-token permission, identity authentication, and provider authorization.
- Review issuer, audience, subject, and environment constraints.
Federation replaces a credential distribution pattern
A workflow that needs external access can use OIDC federation with a supporting provider instead of storing a long-lived provider secret in GitHub. GitHub supplies a signed identity token describing the job, and the provider evaluates a configured trust relationship before issuing its own short-lived access. This does not remove credentials from the system; it changes how they are obtained and how long they remain useful. Parcel’s public examples never request either token, create a role, or contact a cloud provider.
id-token: write is not blanket cloud write
The id-token permission allows an eligible job to request an OIDC identity token. It does not by itself grant permission to modify cloud resources. Provider-side trust and authorization still determine whether an exchange is accepted and what the resulting identity can do. Keep that permission on the narrow trusted job that actually needs federation. The fragment below declares identity-token capability but deliberately contains no token request, provider action, account identifier, role, or deployment. Its printed line is not authentication evidence.
permissions:
contents: read
id-token: write
steps:
- name: Explain the boundary
run: printf "%s\n" "identity permission is not target authorization"
This non-runnable job fragment does not authenticate anywhere. The provider must independently trust appropriate claims and grant narrowly scoped capabilities; adding the field alone creates neither relationship.
Match the identity you intend to trust
Review the issuer, intended audience, and subject or equivalent supported claims. Repository, ref, environment, and reusable-workflow context can affect identity information under documented behavior. A trust rule permitting every branch or repository may admit code that should never hold release authority. Do not copy a subject string from memory: derive the actual documented format for the selected environment and provider. Also review repository rename and transfer implications, token lifetime, and provider restrictions on available condition keys before treating a string match as durable policy.
Evaluate expectations after authentication
The complete local model assumes that cryptographic token authentication has already happened and checks declared synthetic claim expectations. It rejects the wrong audience even when the subject matches. It does not parse a JWT, validate a signature or expiry, fetch keys, or exchange a credential. Those are essential parts of real OIDC verification. A decoded token is only readable data until its authenticity and validity are established. Never print a real token to discover its claims in an ordinary job log.
expected = {"issuer": "ci-issuer-lab", "audience": "parcel-provider-lab", "subject": "trusted-release-job"}
def matches(claims):
return all(claims.get(k) == v for k, v in expected.items())
good = dict(expected)
bad = dict(expected, audience="other-consumer")
print(matches(good))
print(matches(bad))
True
False
The labels are not real OIDC issuer URLs, audiences, or subject syntax. This calculation provides no token security and is not a verifier.
Short lifetime still needs trustworthy execution
An attacker who controls executable inputs in a federated job can use its short-lived authority immediately. Restrict source influence, reviewed action dependencies, runner identity, and cache content just as carefully as with stored secrets. Environment approval can form one boundary, but its candidate and target must remain clear. Provider least privilege limits the damage possible within the token’s lifetime; short expiry limits persistence. Neither replaces the other. Retain redacted identity and operation evidence sufficient for diagnosis without retaining bearer tokens.
Common errors and fixes
id-token: write is assumed to grant provider resource access.
- Why it happens
- Identity-token issuance was confused with external authorization.
- How to fix it
- Review provider trust and role permissions separately.
- Prevent it next time
- Document the complete exchange and capability boundary.
A matching decoded subject is accepted without signature validation.
- Why it happens
- Readable token contents were treated as authenticated claims.
- How to fix it
- Use the provider’s supported verification and trust mechanism.
- Prevent it next time
- Separate decoding, authentication, validity, and policy checks.
Federation trusts every branch of an otherwise trusted repository.
- Why it happens
- The source trust boundary is wider than release policy.
- How to fix it
- Constrain supported claims and keep authority on trusted execution paths.
- Prevent it next time
- Review negative cases and repository lifecycle changes.
Check your understanding
1. A token expires in five minutes. Can the job safely receive broad administrative rights?
Show worked solution
No. A destructive operation can complete within seconds. Short lifetime reduces persistence while least privilege limits capability. Pair both with trusted inputs and target-specific restrictions; federation is not permission to widen authority.
2. The provider rejects an environment-bound job after a subject-format change. What should be inspected?
Show worked solution
Compare the actual documented identity format, requested audience, configured trust conditions, and intended environment. Review a bounded policy update if legitimate. Do not weaken the rule to accept every subject or print the bearer token as diagnostics.
Key takeaways
- Identity-token permission and target authorization are separate.
- Authenticate claims before evaluating a narrow trust policy.