Skip to content

Auth Flow

trupu implements the OpenSSF Trusted Publishers pattern for Docker registries, similar to how npm, PyPI, and RubyGems handle trusted publishing.

The workflow uses the id-token: write permission to request a short-lived JWT from GitHub’s OIDC provider (https://token.actions.githubusercontent.com).

The token contains claims like:

{
"iss": "https://token.actions.githubusercontent.com",
"aud": "https://registry.example.com",
"repository": "my-org/my-app",
"ref": "refs/heads/main",
"job_workflow_ref": "my-org/my-app/.github/workflows/publish.yml@refs/heads/main"
}

The workflow passes the OIDC token as the password in docker login. Docker encodes it as Basic auth (oauth2:<token>) and sends it with every push request.

Traefik’s ForwardAuth middleware intercepts every request to /v2/* and sends a GET to http://trupu:3000/auth with the original headers.

trupu:

  1. Extracts the token from the Authorization header (supports both Basic and Bearer)
  2. Verifies the JWT signature against GitHub’s JWKS (https://token.actions.githubusercontent.com/.well-known/jwks)
  3. Validates the iss (issuer) and aud (audience) claims
  4. Extracts repository and workflow from the token claims
  5. Checks if repository:workflow matches an entry in ALLOWED_PUBLISHERS
  6. Optionally checks the ref claim against ALLOWED_REFS
  • 200 — auth succeeded, Traefik proxies the request to the Docker registry
  • 401 — no credentials provided, returns Www-Authenticate: Basic realm="trupu"
  • 403 — token invalid or publisher not trusted

On successful authentication, trupu sets these headers (forwarded by Traefik to the registry):

HeaderExampleDescription
X-Trupu-Repositorymy-org/my-appThe GitHub repository
X-Trupu-Workflowpublish.ymlThe workflow filename
X-Trupu-Refrefs/heads/mainThe git ref