GitHub Actions can authenticate to AWS with OpenID Connect, so you store no long-lived AWS keys as secrets. GitHub issues a token for each job, AWS exchanges it for temporary credentials for a role you choose, and a condition on the role's trust policy decides which repositories may assume it.
The flow
According to GitHub's documentation, the pieces are:
- In IAM, add GitHub's OIDC provider,
token.actions.githubusercontent.com, withsts.amazonaws.comas the audience. - Create an IAM role that trusts that provider.
- In the workflow, the
aws-actions/configure-aws-credentialsaction sends the job's token to AWS and receives temporary credentials for the role named inrole-to-assume.
No access key or secret key is saved in GitHub. The credentials exist for the length of the job.
Workflow permissions
The job needs id-token: write so it can request the OIDC token. GitHub points out that this does not give write access to any resources. It only lets the workflow request and use the token. Permissions like contents: read for checkout are set separately.
permissions:
id-token: write
contents: read
The condition you must not skip
The role's trust policy should check the sub claim, using the key token.actions.githubusercontent.com:sub. GitHub says you must define at least one condition so untrusted repositories cannot request tokens for your cloud resources.
A condition can match:
- A single branch, in the form
repo:octo-org/octo-repo:ref:refs/heads/octo-branch. - A single environment, in the form
repo:octo-org/octo-repo:environment:prod.
Using StringLike with wildcards is broader and permits more sources. Keep wildcards narrow and know exactly what they match.
Without a condition, the trust relationship may allow tokens from any repository on GitHub to assume your role. That is the most common mistake with this setup.
New repository format
GitHub notes that repositories created after July 15, 2026, or those that opt in, put immutable owner and repository IDs in the sub claim. If your trust policy matches names, check it against the format your repositories actually emit.
Hardening further
- Use GitHub environments, and protect them with deployment rules, then bind the role to the environment claim. A production deploy role then requires an approved environment.
- Create separate roles for separate jobs, for example one that only pushes images and one that deploys. Give each the minimum IAM permissions.
- Keep role session credentials short. They are temporary by design.
- Log role assumptions and alert on assumption from unexpected repositories.
Migrating from stored keys
- Create the provider and role.
- Change one low-risk workflow to use OIDC and confirm it works.
- Move other workflows over one at a time.
- Delete the old access keys and the GitHub secrets that held them. Deactivate first if you want a safety net, then delete.
- Add a repository scan to catch any new static credentials.
Quick check
Does OIDC remove the need for IAM permissions?
No. The role still needs a permissions policy. OIDC only changes how the workflow proves who it is.
What if two repositories need the same role?
List both repositories explicitly in the trust condition, rather than using a broad wildcard.
Sources
Last reviewed: 19 October 2026.