Article & Tutorial

GitHub Actions to AWS Using OIDC: Secure AWS Connectivity Without Access Keys

Learn how to securely connect GitHub Actions to AWS using OpenID Connect (OIDC), IAM roles, and AWS STS without storing long-lived AWS access keys in GitHub Secrets. Includes architecture, IAM trust policies, workflow YAML, security best practices, troubleshooting, and real deployment examples.

GitHub Actions connecting to AWS securely with OIDC and IAM roles
GitHub Actions connecting to AWS securely with OIDC and IAM roles
Contents

GitHub Actions often needs AWS access for CI/CD deployments. Traditional IAM user access keys are long-lived credentials that must be stored, rotated, audited, and protected. OpenID Connect replaces those secrets with short-lived AWS STS role credentials scoped by repository, branch, and environment.

What You Will Learn

  • What OIDC is
  • How GitHub Actions communicates with AWS STS
  • Creating the GitHub OIDC provider
  • Creating the IAM role
  • Repository and branch trust restrictions
  • GitHub Actions workflow configuration
  • Testing AWS connectivity
  • Security best practices
  • Troubleshooting

What Is OIDC?

OpenID Connect is an identity layer on top of OAuth 2.0. In this workflow, GitHub acts as the identity provider and issues a signed JWT to a GitHub Actions job.

AWS IAM trusts the GitHub OIDC provider and AWS STS validates the token during AssumeRoleWithWebIdentity. If the issuer, audience, repository, branch, or environment claim matches the IAM trust policy, STS returns temporary credentials for the role.

Traditional Access Keys vs OIDC

Traditional Access Keys

  • Credential type: IAM user access key and secret key
  • Storage in GitHub Secrets: required
  • Rotation: manual or separately automated
  • Exposure risk: long-lived credential can be reused if leaked
  • Repository restrictions: enforced outside the credential itself
  • CI/CD recommendation: avoid for production deployments when OIDC is available

OIDC

  • Credential type: short-lived AWS STS role credentials
  • Storage in GitHub Secrets: not required for AWS keys
  • Rotation: credentials expire automatically
  • Exposure risk: temporary and scoped by trust policy
  • Repository restrictions: built into IAM token claims
  • CI/CD recommendation: preferred for GitHub Actions to AWS deployments

GitHub Actions to AWS OIDC Architecture

Step 1: Create the GitHub OIDC Identity Provider in AWS

In AWS IAM, create an identity provider for GitHub Actions. The console path is IAM -> Access management -> Identity providers -> Add provider.

text
Provider URL:
https://token.actions.githubusercontent.com

Audience:
sts.amazonaws.com

Step 2: Create an IAM Role for GitHub Actions

Create a Web Identity role that GitHub Actions can assume after AWS STS validates the OIDC token. Use names that identify the application, environment, and deployment purpose.

text
aws-aurora-postgresql-infrastructure-dev-deploy-role
aws-network-infrastructure-prod-deploy-role
payments-api-dev-deploy-role

Step 3: Configure the IAM Role Trust Policy

The trust policy controls who can assume the role. Keep placeholders exactly as placeholders until you replace them in your own AWS account.

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::AWS_ACCOUNT_ID:oidc-provider/token.actions.githubusercontent.com"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
          "token.actions.githubusercontent.com:sub": "repo:YOUR_GITHUB_ORG/YOUR_REPOSITORY:ref:refs/heads/main"
        }
      }
    }
  ]
}

Allow main and develop Branches

json
{
  "Condition": {
    "StringEquals": {
      "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
    },
    "StringLike": {
      "token.actions.githubusercontent.com:sub": [
        "repo:YOUR_GITHUB_ORG/YOUR_REPOSITORY:ref:refs/heads/main",
        "repo:YOUR_GITHUB_ORG/YOUR_REPOSITORY:ref:refs/heads/develop"
      ]
    }
  }
}

Use a GitHub Environment

text
repo:YOUR_GITHUB_ORG/YOUR_REPOSITORY:environment:production

Step 4: Attach Permissions to the IAM Role

The trust policy controls who can assume the role. The permissions policy controls what that role can do after AWS STS issues credentials.

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:GetObject", "s3:ListBucket"],
      "Resource": [
        "arn:aws:s3:::my-deployment-bucket",
        "arn:aws:s3:::my-deployment-bucket/*"
      ]
    }
  ]
}

Step 5: Configure GitHub Actions

yaml
name: Deploy to AWS

on:
  push:
    branches:
      - main

permissions:
  id-token: write
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Configure AWS credentials using OIDC
        uses: aws-actions/configure-aws-credentials@v6
        with:
          role-to-assume: arn:aws:iam::123456789012:role/my-app-dev-deploy-role
          aws-region: us-east-1

      - name: Verify AWS identity
        run: aws sts get-caller-identity

What Happens During the Workflow?

  1. 1
    GitHub starts runner

  2. 2
    GitHub requests OIDC token

  3. 3
    GitHub generates JWT

  4. 4
    AWS STS receives token

  5. 5
    AWS validates issuer/audience/subject

  6. 6
    IAM trust policy is evaluated

  7. 7
    STS issues temporary credentials

  8. 8
    Workflow uses temporary credentials

Testing the Connection

Terminal
$ aws sts get-caller-identity
Expected output
{
  "UserId": "AROAXXXXXXXXXXXXX:GitHubActions",
  "Account": "123456789012",
  "Arn": "arn:aws:sts::123456789012:assumed-role/my-app-dev-deploy-role/GitHubActions"
}

Example: Deploy a CloudFormation Stack

Terminal
$ aws cloudformation deploy \ --template-file infrastructure/template.yaml \ --stack-name my-app-dev \ --capabilities CAPABILITY_NAMED_IAM \ --region us-east-1

Example: Upload to S3

Terminal
$ aws s3 cp ./dist/app.zip s3://my-deployment-bucket/releases/app.zip

Common OIDC Errors and Troubleshooting

Security Best Practices

  • Restrict OIDC subject
  • Validate audience
  • Use least privilege
  • Separate dev/stage/prod roles
  • Protect production
  • Avoid long-lived IAM user keys
  • Audit CloudTrail
  • Review GitHub Actions
  • Keep permissions minimal

OIDC vs AWS IAM Identity Center

OIDC for GitHub Actions is machine workflow authentication. AWS IAM Identity Center is for human workforce authentication and access management. Use the right model for the actor that needs access.

Frequently Asked Questions

Do I need AWS access keys?

No. With OIDC, GitHub Actions can request short-lived credentials from AWS STS without storing AWS access keys in GitHub Secrets.

Do I need an IAM user?

No IAM user is required for the GitHub Actions workflow. The workflow assumes an IAM role through the configured OIDC provider.

Do I need one OIDC provider per repository?

No. One GitHub OIDC provider can support multiple repositories. Repository scoping belongs in each role trust policy.

Can multiple repositories use OIDC?

Yes. Add the appropriate repository subjects to role trust policies, or create separate roles for clearer boundaries.

Can the same repository deploy to multiple accounts?

Yes. Configure roles in each AWS account and have the workflow assume the account-specific role for each deployment target.

Conclusion

GitHub Actions to AWS OIDC is a safer default for CI/CD because credentials are temporary, scoped, and audited through AWS STS and CloudTrail.

  • List item
text
Developer pushes code
        |
        v
GitHub Repository
        |
        v
GitHub Actions Workflow
        |
        | Requests OIDC JWT
        v
GitHub OIDC Provider
https://token.actions.githubusercontent.com
        |
        v
AWS IAM / AWS STS
        |
        | Validates audience + subject
        v
AssumeRoleWithWebIdentity
        |
        v
Temporary AWS Credentials
        |
        v
CloudFormation / S3 / ECR / ECS / Lambda / Terraform

Did this help?

Yes No

Join the discussion

0 Comments

Ask questions, add context, or share what worked.

Sign in to join the discussion

No comments yet. Start the discussion.

More from Melochip Editorial

Related articles

Stay in the loop. Get new Melochip articles

Receive Melochip article updates when new articles are available. Explicit opt-in only.

No pre-checked boxes. Unsubscribe support is part of the subscriber foundation.