agenticaisecured

GitHub Actions OIDC without secrets: deploy to AWS, GCP, and Azure

GitHub Actions OIDC lets a workflow prove its identity to a cloud provider and receive a short-lived access token at runtime, so you never store long-lived cloud keys in repository secrets. You add id-token write permission, register GitHub as a trusted identity provider, and restrict access by repository and branch in the trust policy.

By Sunny Patel Updated

Independent SEO consultant & AI practitioner who builds and tests these tools.

GitHub Actions OIDC without secrets: deploy to AWS, GCP, and Azure

GitHub Actions OIDC lets a workflow authenticate to a cloud provider using a short-lived token minted at runtime, so you never store long-lived access keys in repository secrets. You add id-token: write permission, register GitHub as a trusted OpenID Connect identity provider on the cloud side, and restrict who can assume access by repository and branch.

TL;DR:

  • OIDC replaces stored cloud keys with a short-lived token that GitHub signs for each workflow run.
  • Add permissions: id-token: write and contents: read to the workflow, then trust GitHub as an identity provider in your cloud account.
  • Lock access down with a trust policy condition on the sub claim, scoping to one repository and branch.
  • This article sits in the guides library; pair it with least-privilege for AI agents and committed a secret to GitHub.

Why avoid long-lived secrets in CI?

A stored access key is a standing liability. Once an AWS access key, GCP service account JSON, or Azure client secret sits in repository secrets, it works until someone rotates it, and anyone who can read it, leak it, or print it in a log can use it from anywhere. Most CI breaches trace back to a static credential that was copied, forgotten, or exposed.

OIDC removes the static credential entirely. Instead of holding a key, the workflow proves who it is and borrows a token that expires in minutes. Nothing durable is stored, so there is nothing durable to steal. If you have already leaked one, follow committed a secret to GitHub first, then move to OIDC so it cannot happen again.

What is OIDC in GitHub Actions?

OpenID Connect is an identity layer that lets one system vouch for another using signed tokens. In GitHub Actions, GitHub acts as the identity provider. When a job requests it, GitHub issues a JSON Web Token (JWT) describing the run: which repository, which branch or tag, which workflow, and which environment.

Your cloud provider is configured to trust GitHub’s issuer, token.actions.githubusercontent.com. The cloud validates the token’s signature and its claims, and if they match your rules, it returns a short-lived access token. The full mechanism is documented in GitHub’s guide to security hardening with OpenID Connect.

The most important claim is sub (subject). It encodes the source of the run, for example repo:OWNER/REPO:ref:refs/heads/main. Your cloud trust policy matches against sub so that only the repository and branch you choose can obtain credentials.

How do you turn on OIDC in a workflow?

You grant the job permission to request a token. Without id-token: write, the request fails. Setting contents: read keeps the rest of the job least privilege rather than inheriting broad defaults.

name: deploy
on:
  push:
    branches: [main]

permissions:
  id-token: write   # required to request the OIDC token
  contents: read    # least privilege for the rest of the job

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/github-deploy
          aws-region: eu-west-2

The official cloud auth action exchanges the GitHub token for cloud credentials. Below are the three you will reach for.

Which auth action does each cloud use?

CloudOfficial actionKey inputWhat you configure on the cloud side
AWSaws-actions/configure-aws-credentialsrole-to-assume (IAM role ARN)An IAM OIDC identity provider plus a role whose trust policy conditions on the sub claim.
Google Cloudgoogle-github-actions/authworkload_identity_providerA Workload Identity Pool and provider, plus a service account the pool can impersonate.
Azureazure/loginclient-id, tenant-id, subscription-idAn app registration with a federated credential matching the repository and branch.

How do you set up OIDC step by step?

The shape is identical across clouds: register GitHub as a trusted issuer, then bind a role or service account to a specific repository and branch.

  1. Add the workflow permissions. Set id-token: write and contents: read as shown above.
  2. Register GitHub as an OIDC identity provider in your cloud account, using the issuer token.actions.githubusercontent.com.
  3. Create the role or service account the workflow will assume, granting it only the permissions that deployment needs.
  4. Add a trust condition on the sub claim, scoping to repo:OWNER/REPO:ref:refs/heads/main so only that branch qualifies.
  5. Add the official auth action to the job with the role ARN, workload identity provider path, or client ID.
  6. Run the workflow and verify. Confirm credentials are issued and that a push from another branch is rejected.

What does the AWS trust policy look like?

On AWS you create an IAM OIDC identity provider for token.actions.githubusercontent.com with the audience sts.amazonaws.com, then attach a trust policy to the role. The policy conditions the aud claim on sts.amazonaws.com and the sub claim on your repository and branch, for example repo:OWNER/REPO:ref:refs/heads/main. Only a workflow matching both claims can call AWS STS to assume the role. The setup is described in the AWS configure-aws-credentials documentation.

How does GitHub OIDC AWS authentication work without secrets?

GitHub OIDC AWS authentication lets a workflow assume an AWS IAM role at runtime instead of holding an access key. The GitHub Actions AWS OIDC flow has the workflow request a signed token, which AWS STS validates against the IAM OIDC identity provider and the role’s trust policy before returning short-lived credentials, so no long-lived secret is ever stored.

How does GCP differ?

Google Cloud uses Workload Identity Federation. You create a Workload Identity Pool and an OIDC provider inside it pointing at GitHub’s issuer, map the sub claim with an attribute condition, then let the pool impersonate a service account. The workflow passes workload_identity_provider and the target service account to google-github-actions/auth. No service account JSON key is ever downloaded.

How does Azure differ?

Azure uses federated identity credentials on an app registration. You add a federated credential whose subject matches repo:OWNER/REPO:ref:refs/heads/main and whose issuer is GitHub. The workflow supplies client-id, tenant-id, and subscription-id to azure/login, which trades the GitHub token for an Azure access token. No client secret is stored.

What are the security benefits?

OIDC narrows three risks at once. Tokens are short-lived, so a captured token is near worthless within minutes. Access is scoped by claim, so credentials only work from the exact repository and branch you named, not from a fork or a feature branch. And nothing is stored, so there is no static key to leak through a log, a screenshot, or a misconfigured secret.

This pairs naturally with least privilege: the assumed role should grant only what the deployment needs, nothing more. See least-privilege for AI agents for the same principle applied to tool-using agents, and the checklists library for a pre-deploy review. If secret-scanning is still part of your pipeline, gitleaks vs trufflehog compares the two main tools.

Where to go next

Start from the GitHub OIDC documentation for the canonical reference, then wire up your cloud with the AWS, Google Cloud, or Azure auth action. Browse more in the guides library, and if you handle credentials in agent workflows too, read MCP security best practices.

Frequently asked questions

What is OIDC in GitHub Actions?

OIDC lets a GitHub Actions workflow request a signed JSON Web Token that describes the run. A cloud provider configured to trust GitHub validates that token and exchanges it for a short-lived access token, removing the need to store static cloud keys in repository secrets.

Do I still need repository secrets if I use OIDC?

Not for cloud access keys. You still store non-credential configuration such as a role ARN or workload identity provider path, but these are identifiers, not secrets. The actual access token is minted at runtime and expires within minutes.

What permission does an OIDC workflow need?

The workflow needs permissions with id-token set to write, which lets the job request an OIDC token from GitHub. You should also set contents to read so the rest of the job follows least privilege rather than inheriting broad write access.

How do I restrict OIDC access to one branch?

Add a condition in the cloud trust policy that checks the sub claim, for example repo:OWNER/REPO:ref:refs/heads/main. Only runs from that repository and branch produce a token that matches, so other branches and forks cannot assume the role.

Is OIDC more secure than stored access keys?

Yes. Tokens are short-lived, scoped to a specific repository and branch, and never stored, so there is nothing static to leak. A committed key can be used indefinitely until rotated, whereas an OIDC token expires automatically within minutes.