~/cred-visualizer

Mint OIDC token

A Forgejo Runner requests a job-scoped OIDC token from the Forgejo Actions runtime. The token is signed by Forgejo's private key — the runner never manages a long-lived credential. This signed assertion is what it will trade for GCP access in the next step.

what actually happens
  • The runner asks Forgejo for an OIDC token, naming the GCP provider as the audience.
  • Forgejo signs the token — its claims (repository, ref, repository_owner) describe exactly which workflow run it came from.
origin · what mints this
trigger
push authlab/artifacts-visualizer refs/heads/main
request
GET /api/actions/_apis/pipelines/workflows/40/idtoken ?audience=//iam.googleapis.com/…/forgejo-provider
# .forgejo/workflows/capture.yml
on: push
permissions:
  id-token: write        # lets the job request an OIDC token
jobs:
  capture:
    steps:
      - name: Mint OIDC token
        with:
          audience: //iam.googleapis.com/…/forgejo-provider

the audience you request becomes the token's aud

alg
RS256
kid
9YP06n2o17zssY1eAFAh9Hhb7SRxjlgaZcf-Gb7lfiM
typ
JWT
Claim Value
actor
erick
aud
//iam.googleapis.com/projects/1234567890/locations/global/workloadIdentityPools/authlab-pool/providers/forgejo-provider
base_ref
event_name
push
exp
1778622390
head_ref
iat
1778618790
iss
https://forgejo.authlab.app/api/actions
nbf
1778618790
ref
refs/heads/main
ref_protected
false
ref_type
branch
repository
authlab/artifacts-visualizer
repository_owner
authlab
run_attempt
1
run_id
40
run_number
16
sha
14c23450c8322e4c8e315e68d4241d184826be06
sub
repo:authlab/artifacts-visualizer:ref:refs/heads/main
workflow
capture.yml
workflow_ref
authlab/artifacts-visualizer/.forgejo/workflows/capture.yml@refs/heads/main
eyJhbGciOiJSUzI1NiIsImtpZCI6IjlZUDA2bjJvMTd6c3NZMWVBRkFoOUhoYjdTUnhqbGdhWmNmLUdiN2xmaU0iLCJ0eXAiOiJKV1QifQeyJhY3RvciI6ImVyaWNrIiwiYXVkIjoiLy9pYW0uZ29vZ2xlYXBpcy5jb20vcHJvamVjdHMvMTIzNDU2Nzg5MC9sb2NhdGlvbnMvZ2xvYmFsL3dvcmtsb2FkSWRlbnRpdHlQb29scy9hdXRobGFiLXBvb2wvcHJvdmlkZXJzL2Zvcmdlam8tcHJvdmlkZXIiLCJiYXNlX3JlZiI6IiIsImV2ZW50X25hbWUiOiJwdXNoIiwiZXhwIjoxNzc4NjIyMzkwLCJoZWFkX3JlZiI6IiIsImlhdCI6MTc3ODYxODc5MCwiaXNzIjoiaHR0cHM6Ly9mb3JnZWpvLmF1dGhsYWIuYXBwL2FwaS9hY3Rpb25zIiwibmJmIjoxNzc4NjE4NzkwLCJyZWYiOiJyZWZzL2hlYWRzL21haW4iLCJyZWZfcHJvdGVjdGVkIjoiZmFsc2UiLCJyZWZfdHlwZSI6ImJyYW5jaCIsInJlcG9zaXRvcnkiOiJhdXRobGFiL2FydGlmYWN0cy12aXN1YWxpemVyIiwicmVwb3NpdG9yeV9vd25lciI6ImF1dGhsYWIiLCJydW5fYXR0ZW1wdCI6IjEiLCJydW5faWQiOiI0MCIsInJ1bl9udW1iZXIiOiIxNiIsInNoYSI6IjE0YzIzNDUwYzgzMjJlNGM4ZTMxNWU2OGQ0MjQxZDE4NDgyNmJlMDYiLCJzdWIiOiJyZXBvOmF1dGhsYWIvYXJ0aWZhY3RzLXZpc3VhbGl6ZXI6cmVmOnJlZnMvaGVhZHMvbWFpbiIsIndvcmtmbG93IjoiY2FwdHVyZS55bWwiLCJ3b3JrZmxvd19yZWYiOiJhdXRobGFiL2FydGlmYWN0cy12aXN1YWxpemVyLy5mb3JnZWpvL3dvcmtmbG93cy9jYXB0dXJlLnltbEByZWZzL2hlYWRzL21haW4ifQanonymized-signature-not-valid-for-cryptographic-use

What must match

STS checks these before anything else. Hover a claim for why.

aud
token.aud WIF provider URI
iss
token.iss provider issuer URI

IAM binding

The principalSet authorizes only tokens whose claims match. Hover a claim for why.

repository
token.repository attribute.repository

IAM binding — principalSet

principalSet://iam.googleapis.com/
projects/1234567890/
locations/global/
workloadIdentityPools/authlab-pool/
attribute.repository/authlab/artifacts-visualizer
matches JWT repository claim — also encoded in sub

Only tokens from this repo, this pool match. Step 3 shows how to loosen or tighten the scope.