Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

README.md

GitHub STS

Exchange a workflow's GitHub OIDC token for a short-lived limited-permission GitHub App token.

The caller must grant id-token: write. The action does not require stored credentials: the STS verifies the signed GitHub OIDC token and authorizes it against the trust policy in the target repository.

The action sends token exchanges with POST /sts/exchange; legacy action versions that use GET remain compatible during the coordinated rollout.

Inputs

Name Description Required Default
scope Repository (org/repo) or organization whose trust policy to use No Current repository
policy Trust policy name (fetches file in .github/sts/<policy>.sts.yaml within scope repo) Yes
ttl Requested maximum lifetime (30s, 5m, or 1h) No Service/policy maximum
host GitHub STS hostname, without a scheme, port, or path No gh-sts.tempoxyz.net
retry-timeout Total OIDC/exchange request and retry budget in seconds (1–3600) No 90

Outputs

Name Description
token Short-lived GitHub App installation token
expires-at Token expiration timestamp

Production usage

permissions:
  contents: read
  id-token: write

steps:
  - name: Fetch GitHub token via STS
    id: sts
    uses: tempoxyz/gh-actions/actions/github-sts@d39baa2b43f5eba5d261c047521a4fbd56101129 # 2026-09-23T04-31-11Z-d39baa2b
    with:
      policy: deploy # Uses .github/sts/deploy.sts.yaml as the permissions policy
      ttl: 15m

  - name: Use the token
    env:
      GH_TOKEN: ${{ steps.sts.outputs.token }}
    run: gh api "repos/${GITHUB_REPOSITORY}"

ttl is parsed and enforced by the STS. It must be a positive integer followed by s, m, or h, resolve to no more than one hour, and cannot exceed the policy's optional max_ttl. The effective lifetime is the shortest of the requested TTL, the policy maximum, and GitHub's one-hour installation-token limit. The expires-at output reports that effective deadline.

The action delegates caller authorization to the STS, which verifies the signed GitHub OIDC token, checks its immutable numeric repository owner ID against the server's allowlist, and enforces the target repository's trust policy. Rejected exchanges fail the action. There is no action-side organization list to update when onboarding an organization; callers already using this version need no action repin for subsequent server-side authorization changes.

The minted installation token is revoked through STS when the job finishes, so its provider credential and STS ownership-ledger row are cleared together, including after a failed or cancelled job. Direct GitHub revocation remains a fail-safe if STS cleanup is unavailable. If the STS exchange is rejected, the action prints the HTTP status and the server's safe error message (for example, trust policy: subject did not match) to make policy and configuration problems easier to diagnose.

OIDC requests, STS worker exchanges, and token revocations retry transient network errors and HTTP 408, 425, 429, or 5xx responses up to five times after the initial attempt, with exponential backoff (1, 2, 4, 8, and 16 seconds). Other failures are returned immediately.

OIDC and exchange retries honor Retry-After (seconds or HTTP date) and x-ratelimit-reset when x-ratelimit-remaining is zero. These delays are minimums: the action never shortens them to fit its budget. A 429 without a usable deadline waits at least 60 seconds. If the next retry would exceed retry-timeout, the action fails with the next permitted retry time instead of retrying early. Individual requests remain bounded to at most 10 seconds.

After a confirmed 429, the action requests a fresh OIDC assertion after the wait. Network errors and 5xx retries reuse the original assertion, preserving STS replay protection when a token may already have been minted. This does not change post-job revocation retries. Deploy the STS Retry-After response support before repinning callers; older STS versions use the 60-second 429 fallback.