GitHub Actions Tutorial — OIDC Tokens

2 minute read

OIDC Tokens

OpenID Connect (OIDC) lets your workflows authenticate with cloud providers without storing long-lived credentials. Instead of API keys or access keys stored as secrets, the workflow requests a short-lived token directly from the cloud provider.


Why OIDC?

Traditional (secrets) OIDC (tokens)
Store AWS access keys as secrets No stored credentials
Keys are long-lived Tokens expire in minutes
Must rotate manually Auto-rotated every run
Risk of key exposure No keys to expose
Works everywhere Requires cloud provider setup

How OIDC Works

1. Workflow requests OIDC token from GitHub
    ↓
2. GitHub issues a JWT with claims:
   - repository, branch, workflow, actor
    ↓
3. Workflow sends JWT to cloud provider
    ↓
4. Cloud provider validates JWT against GitHub's OIDC endpoint
    ↓
5. Cloud provider issues short-lived credentials
    ↓
6. Workflow uses credentials to access resources

AWS — OIDC Authentication

Setup (one-time)

  1. Create an OIDC identity provider in AWS IAM
  2. Create an IAM role that trusts the GitHub OIDC provider
  3. Scope the trust policy to your repo/branch

Workflow


permissions:
  id-token: write       # required for OIDC
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/github-actions-role
          aws-region: us-east-1

      - name: Deploy
        run: aws s3 sync ./dist s3://my-bucket

No AWS_ACCESS_KEY_ID or AWS_SECRET_ACCESS_KEY stored anywhere.


Azure — OIDC Authentication

Setup (one-time)

  1. Register an app in Azure AD
  2. Add federated credentials for your GitHub repo
  3. Assign roles to the app

Workflow


permissions:
  id-token: write
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Azure login
        uses: azure/login@v2
        with:
          client-id: ${{ secrets.AZURE_CLIENT_ID }}
          tenant-id: ${{ secrets.AZURE_TENANT_ID }}
          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

      - name: Deploy
        run: az webapp deploy --name myapp --src-path ./dist


GCP — OIDC Authentication

Workflow


permissions:
  id-token: write
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Authenticate to GCP
        uses: google-github-actions/auth@v2
        with:
          workload_identity_provider: 'projects/123/locations/global/workloadIdentityPools/my-pool/providers/my-provider'
          service_account: 'my-sa@my-project.iam.gserviceaccount.com'

      - name: Deploy
        run: gcloud app deploy


OIDC Token Claims

The JWT token GitHub issues contains claims that cloud providers use to authorize access:

Claim Example Use
sub repo:owner/repo:ref:refs/heads/main Restrict by repo + branch
repository owner/repo Restrict by repository
ref refs/heads/main Restrict by branch/tag
environment production Restrict by environment
actor octocat Restrict by user
workflow deploy.yml Restrict by workflow

Trust Policy Example (AWS)

{
  "Condition": {
    "StringEquals": {
      "token.actions.githubusercontent.com:sub": "repo:my-org/my-repo:ref:refs/heads/main"
    }
  }
}

This only allows tokens from the main branch of my-org/my-repo.


Common Mistakes

Mistake Fix
Missing id-token: write permission Add permissions: id-token: write to the workflow or job
Trust policy too broad Scope to specific repo + branch, not repo:*
Token rejected by cloud provider Check the trust policy matches the token’s claims exactly
OIDC not working in fork PRs Fork PRs can’t request OIDC tokens (security)

Quick Reference

Cloud Action Key Input
AWS aws-actions/configure-aws-credentials@v4 role-to-assume:
Azure azure/login@v2 client-id:, tenant-id:
GCP google-github-actions/auth@v2 workload_identity_provider:
Required permission id-token: write Always needed for OIDC

← Previous: Environments

Next: Practice Exercises →

Updated: