~/cred-visualizer

Impersonate the service account

The federated token proves GCP recognizes the identity — but it carries no roles. To do real work, the runner asks the IAM Credentials API to mint an access token as the target service account. IAM grants that only if the federated principal holds roles/iam.workloadIdentityUser on that SA — the authorization hinge of the whole pattern.

what actually happens
  • The runner calls generateAccessToken on the target SA, authenticating with the federated token from step 2.
  • IAM checks the binding — the caller's principalSet must hold roles/iam.workloadIdentityUser on ci-deployer@authlab-lab.iam.gserviceaccount.com.
  • IAM returns a normal SA access token — from here on, GCP sees an ordinary service account.
input · from step 2
federated token ya29.c.REDACTED-federated-access-token-not-valid-for-use minted in step 2 →

Call sequence

One call: the federated identity asks IAM to mint a token as the SA. The authorization check happens server-side, against the binding on the right.

runner forgejo ci IAM iamcredentials 1 generateAccessToken 2 200 · sa token

step 2 · IAM returns · sa access token

ya29.c.SYNTHETIC-sa-access-token-not-valid-for-use
token_type: Bearer expires: 2026-05-12T21:46:34Z opaque — not a JWT indistinguishable from any other SA credential

What IAM checks

Not a token-content check this time — an authorization check: the token's repository must match the attribute the binding pins. Hover repository for the comparison.

repository
token.repository attribute.repository

The binding IAM evaluates

principalSet://iam.googleapis.com/
projects/1234567890/
locations/global/
workloadIdentityPools/authlab-pool/
attribute.repository/authlab/artifacts-visualizer
≡ token repository — the binding pins this repo (any ref)
$ gcloud iam service-accounts add-iam-policy-binding \
    ci-deployer@authlab-lab.iam.gserviceaccount.com \
    --role="roles/iam.workloadIdentityUser" \
    --member="principalSet://iam.googleapis.com/projects/1234567890/locations/global/workloadIdentityPools/authlab-pool/attribute.repository/authlab/artifacts-visualizer"

run once, by an operator — not part of the runtime flow

No binding that names this repository → 403. authN proved who; this binding authorizes what they may impersonate.