AWS Builder Center
I Stopped Using AWS Access Keys in GitHub Actions: Moving to OIDC

I Stopped Using AWS Access Keys in GitHub Actions: Moving to OIDC

how I used AWS OIDC with GitHub Actions to authenticate securely without storing long-lived AWS access keys, while controlling exactly which repositories and branches can access AWS resources.

From AWS Access Keys to OIDC

When I first started connecting GitHub Actions to AWS, the obvious approach was to create an AWS access key and secret key, store them as GitHub Secrets, and let the workflow use those credentials.
It works, but there was something I didn't really like about it: I was giving my CI/CD pipeline long-lived AWS credentials.
While learning more about AWS IAM, I came across OpenID Connect (OIDC) and decided to try it instead.
The basic idea is pretty interesting.
GitHub Actions can generate a short-lived OIDC token for a workflow. AWS trusts GitHub's OIDC provider and uses that identity to allow the workflow to assume a specific IAM role. The workflow then receives temporary AWS credentials rather than using a permanent access key and secret key.
So instead of:
GitHub Actions → AWS Access Key + Secret → AWS
the flow becomes:
GitHub Actions → OIDC Token → IAM Role → Temporary AWS Credentials → AWS
That already felt like a much cleaner approach to me.
The part I found most useful: controlling who can assume the role
The interesting part wasn't just removing the access keys.
The IAM role's trust policy can be configured to decide which GitHub Actions workflows are actually allowed to assume it.
For example, I can restrict a role to a specific repository and even a specific branch.
So instead of allowing any workflow from my GitHub account to access AWS, I can have a policy that effectively says:
Only workflows from this repository's main branch can assume this role.
AWS specifically supports using GitHub's sub claim in the trust policy to restrict access to an organization, repository, branch, or environment.

Different workflows can have different roles

Another thing I found useful is that I don't have to give every workflow the same IAM role.
For example, I could have one role for a Terraform workflow:
GitHub → OIDC → Terraform IAM Role → Infrastructure permissions
and another for an application deployment workflow:
GitHub → OIDC → Deployment IAM Role → Application deployment permissions
Each role can have its own permissions and trust policy.
This means I can follow the principle of least privilege more closely instead of creating one large IAM role that can do everything.
For a larger project, I could imagine having separate roles for infrastructure changes, development deployments, and production deployments.

What changed in my GitHub Actions workflow?

The workflow itself isn't dramatically different.
One important change is giving the job permission to request an OIDC token:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
permissions:
contents: read
id-token: write

Jobs:
deploy:
needs: Build_and_Test
runs-on: ubuntu-latest
steps:
- name: Configure AWS Credentials for region audience
uses: aws-actions/configure-aws-credentials@v6.3.0
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: ap-southeast-1
Then the AWS credentials action exchanges the GitHub OIDC token for temporary AWS credentials using the IAM role I configured. Importantly, id-token: write doesn't itself give the workflow AWS permissions; it only allows the workflow to request the identity token. No secret keys or access keys needed. just the IAM role
After authentication, Terraform can work with AWS normally.
That means my CI/CD pipeline can essentially go from:
Push code → GitHub Actions → Authenticate with AWS → Terraform plan/apply → Infrastructure updated
without storing a long-lived AWS access key and secret in GitHub.
I always had a uncomfortable feeling on back of my head when adding my access keys and secret keys into repository secretes for CI\CD. OIDC offers a better alternative
CI/CD doesn't need to carry permanent AWS credentials around. GitHub can prove its identity to AWS, and AWS can decide exactly what that particular workflow is allowed to access
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article