
Table of Contents
By Khimananda Oli | Last reviewed: August 2026
Managing long-lived access keys is a security liability that most teams can no longer afford. When you deploy to AWS from GitHub Actions with OIDC (No Keys), you replace static credentials with ephemeral, session-based tokens tied directly to your repository and branch. This approach eliminates key rotation headaches and significantly reduces the blast radius of compromised secrets. For teams building automated CI/CD pipelines, adopting OpenID Connect is now the baseline standard for production-grade infrastructure.
aws-actions/configure-aws-credentials action with the role-to-assume parameter instead of access keys.How do you configure AWS IAM for GitHub Actions OIDC?
The foundation of this architecture is the IAM Identity Provider. Unlike traditional federation which requires complex SAML setup, GitHub’s OIDC endpoint is public and standardized. You must define this provider exactly once per AWS account. In practice, I manage this via Terraform to ensure the URL and thumbprint are immutable and version-controlled, aligning with infrastructure as code best practices.
Create the OIDC Identity Provider
You need to register GitHub’s token issuer with AWS. The thumbprint is critical; it validates that the token actually came from GitHub. As of 2026, the stable thumbprint remains consistent, but always verify against official documentation before applying.
resource "aws_iam_openid_connect_provider" "github_actions" {
url = "https://token.actions.githubusercontent.com"
client_id_list = ["sts.amazonaws.com"]
thumbprint_list = ["6938fd4d98bab03faadb97b34396831e3780aea1"]
tags = {
Name = "GitHubActionsOIDC"
Environment = "Production"
ManagedBy = "Terraform"
}
} Define a Least-Privilege Trust Policy
This is where most security failures occur. Never use a wildcard (*) for the sub claim. Always scope access to a specific repository, environment, or branch. This ensures that even if another repo in your organization is compromised, it cannot assume this role.
data "aws_iam_policy_document" "github_assume_role" {
statement {
effect = "Allow"
actions = ["sts:AssumeRoleWithWebIdentity"]
principals {
type = "Federated"
identifiers = [aws_iam_openid_connect_provider.github_actions.arn]
}
condition {
test = "StringEquals"
variable = "token.actions.githubusercontent.com:aud"
values = ["sts.amazonaws.com"]
}
# CRITICAL: Restrict to specific repo and environment
condition {
test = "StringLike"
variable = "token.actions.githubusercontent.com:sub"
values = ["repo:khimananda/my-app:environment:production"]
}
}
} What is the correct GitHub Actions workflow syntax for OIDC?
Your workflow file must explicitly request the id-token: write permission. Without this, GitHub will not generate the OIDC token, and the authentication step will fail silently or throw a cryptic 403 error. This permission grants the workflow run the ability to mint a signed JWT for the current execution context.
Minimal Secure Workflow Configuration
Below is a battle-tested snippet. Note that we never reference AWS_ACCESS_KEY_ID. The configure-aws-credentials action handles the entire STS handshake internally when provided with a role ARN.
name: Deploy to AWS
on:
push:
branches: [main]
permissions:
id-token: write # REQUIRED for OIDC
contents: read # Needed to checkout code
jobs:
deploy:
runs-on: ubuntu-latest
environment: production # Matches IAM trust policy condition
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsDeployRole
aws-region: ap-south-1
# Optional: Reduce session duration for tighter security
role-duration-seconds: 900
- name: Verify Identity
run: aws sts get-caller-identity How does OIDC compare to long-lived access keys for CI/CD?
If you are still debating whether to migrate, consider the operational overhead. Long-lived keys require manual rotation, secure storage in secrets managers, and immediate revocation procedures upon staff departure. OIDC shifts this burden to cryptographic verification. For teams managing AWS IAM least privilege access, OIDC is not just safer; it is operationally superior.
| Criteria | Long-Lived Access Keys | OIDC Federation (Recommended) |
|---|---|---|
| Credential Lifespan | Indefinite (until rotated) | Ephemeral (15m – 1hr default) |
| Rotation Requirement | Manual / Scheduled (90 days max) | Automatic per workflow run |
| Blast Radius | High (keys often shared/reused) | Low (scoped to repo/branch/env) |
| Audit Trail | Generic IAM user activity | Specific workflow run ID + commit SHA |
| Secret Storage | Required (GitHub Secrets/Vault) | None (Zero secrets stored) |
| Compliance (SOC2/ISO) | Harder to justify | Preferred control for automated access |
How do you troubleshoot common OIDC authentication failures?
Even with perfect configuration, OIDC can fail due to subtle mismatches. In my experience supporting teams across Nepal and globally, 90% of issues stem from three specific areas. Debugging requires checking both the GitHub runner logs and AWS CloudTrail simultaneously.
- Missing
id-token: writePermission: This is the most frequent error. If your job uses a matrix strategy or reusable workflows, permissions defined at the top level do not automatically cascade. You must explicitly declarepermissionsin every job block that calls the AWS credential action. - Trust Policy Condition Mismatch: The
subclaim is case-sensitive and format-specific. A common mistake is usingrepo:org/repo:*when the actual token containsref:refs/heads/main. Use the GitHub OIDC debugger or inspect the raw token payload in a test step to see the exact claims being issued. - Environment Protection Rules: If your IAM role trusts
environment:production, but your workflow job doesn't specifyenvironment: production, authentication fails. The environment name in YAML must match the IAM condition string exactly.
Verify Token Claims Before Deploying
Add this diagnostic step temporarily to print the token claims without exposing sensitive data. It helps confirm what AWS will actually receive.
- name: Debug OIDC Claims (Safe)
run: |
curl -sS \
-H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
"$ACTIONS_ID_TOKEN_REQUEST_URL&audience=sts.amazonaws.com" \
| jq '.value | split(".")[1] | @base64d | fromjson' \
| grep -E '"(sub|aud|repository)"' Next Steps for Secure AWS Deployments
Migrating to deploy to AWS from GitHub Actions with OIDC (No Keys) is a definitive step toward mature, audit-ready DevOps. Once implemented, rotate and delete all existing long-lived keys immediately. Pair this with centralized secrets management for application-level credentials that OIDC cannot address. If your team needs assistance designing compliant CI/CD architectures or hardening existing AWS environments, reach out to discuss your infrastructure. Security is not a feature you add later; it is the foundation everything else rests on.