OIDC to the Cloud
OIDC to the Cloud
Every pipeline that deploys to AWS, GCP, or Azure needs cloud credentials. The traditional approach stores long-lived access keys as repository secrets — a key that exists for months or years, can be leaked, and must be rotated manually. The industry has moved decisively away from this. The modern, Big-Tech-standard approach is keyless authentication via OpenID Connect (OIDC): GitHub Actions generates a short-lived, cryptographically signed token for each workflow run, and the cloud provider exchanges that token for a scoped, time-bounded credential — no static secret ever stored.
How OIDC Keyless Auth Works
OpenID Connect is a thin identity layer on top of OAuth 2.0. GitHub acts as the Identity Provider (IdP); your cloud account is the Relying Party. The flow has four steps:
- GitHub's OIDC endpoint issues a signed JWT (JSON Web Token) containing claims about the workflow: repository, branch, environment, actor, SHA, and more.
- The runner presents this JWT to the cloud provider's STS (Security Token Service).
- The STS verifies the JWT's signature against GitHub's published JWKS (public keys) and checks the claims against a trust policy you configured.
- If claims match, STS returns short-lived credentials (typically 15-60 minutes). The workflow uses them; they expire automatically when the job ends.
Configuring OIDC on AWS (IAM Roles Anywhere / Web Identity)
AWS uses IAM Web Identity federation. You register GitHub's OIDC provider once in your AWS account, then create an IAM role with a trust policy that restricts which GitHub workflows can assume it.
The GitHub Actions Workflow Side
Your workflow needs two things: the id-token: write permission (so it can request a JWT from GitHub's OIDC endpoint) and the aws-actions/configure-aws-credentials action, which handles the entire STS exchange transparently.
sub claim in the trust policy as tightly as possible. Use repo:ORG/REPO:environment:production rather than repo:ORG/REPO:ref:refs/heads/main — the environment binding means only jobs that target your protected production environment (which requires human approval) can assume the high-privilege role. This pairs perfectly with the Environments lesson.GCP and Azure in Brief
The same OIDC standard applies to all major clouds; only the configuration surface changes.
- GCP (Workload Identity Federation): Create a Workload Identity Pool, add GitHub as an OIDC provider, bind it to a service account via an IAM condition on the
attribute.repositoryandattribute.environmentclaim mappings. Use thegoogle-github-actions/authaction withworkload_identity_providerandservice_account. - Azure (Federated Identity Credentials): Register an App Registration in Entra ID, add a federated credential with the GitHub issuer, entity type, and a subject filter (
repo:ORG/REPO:environment:production). Use theazure/loginaction withclient-id,tenant-id, andsubscription-id— no client secret.
Trust Policy Claim Reference
GitHub's JWT contains rich claims you can filter on. Knowing them lets you design fine-grained trust policies:
sub— the canonical subject string; format depends on what triggered the run (branch, tag, environment, PR).repository—org/repo— always present.environment— the job-level environment name; only present when the job declares one.ref— the git ref (refs/heads/main).actor— the GitHub user who triggered the run.job_workflow_ref— fully qualified reference to the calling workflow file; essential for restricting which reusable workflow can assume a role.
"token.actions.githubusercontent.com:sub": "repo:ORG/REPO:*" (a wildcard). This allows ANY branch, ANY environment, and ANY triggered event in that repository to assume the role — including pull requests from forks. Always constrain to a specific environment or branch. PR-triggered workflows that can assume a production deploy role are a critical supply-chain risk.Debugging OIDC Failures
OIDC misconfigurations surface as cryptic AccessDenied or InvalidIdentityToken errors. Systematic diagnosis saves hours:
- Add a step before the credential action to decode the raw token:
run: echo "$ACTIONS_ID_TOKEN_REQUEST_TOKEN" | cut -d. -f2 | base64 -d 2>/dev/null | python3 -m json.tool— this shows the exact claims GitHub is sending. - Compare every claim in the token against every condition in your trust policy — a single character mismatch causes denial.
- Confirm
id-token: writeis set at the workflow or job level; without it, the OIDC endpoint returns a 403 before any cloud call is made. - Check the thumbprint has not rotated — GitHub occasionally rotates its OIDC signing certificate. AWS now supports automatic thumbprint validation if you omit the thumbprint list (recommended for new setups).
OIDC keyless auth is now the mandatory standard for cloud deployments at scale. Removing long-lived keys eliminates an entire class of credential-leak incidents and simplifies compliance posture — no key rotation schedules, no audit trail gaps, no accidental commits of ~/.aws/credentials.