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.
- The runner calls
generateAccessTokenon the target SA, authenticating with the federated token from step 2. - IAM checks the binding — the caller's
principalSetmust holdroles/iam.workloadIdentityUseronci-deployer@authlab-lab.iam.gserviceaccount.com. - IAM returns a normal SA access token — from here on, GCP sees an ordinary service account.
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.
step 2 · IAM returns · sa access token
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 The binding IAM evaluates
principalSet://iam.googleapis.com/ projects/1234567890/ locations/global/ workloadIdentityPools/authlab-pool/ attribute.repository/authlab/artifacts-visualizer 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.