Skip to content
LearnOIDC for CI

What is OIDC for CI?

Also known asOpenID Connect in CICI identity token
Example. Kiteline is a fictional company.
On this page

OIDC for CI is the use of OpenID Connect identity tokens, short-lived signed JWTs that a CI provider issues to a running job, so the job can prove where it runs instead of presenting a long-lived stored secret.

How it works

  1. A job asks its CI provider for a token and names an audience: the service it is about to call.
  2. The provider returns a JWT signed with its key. As in OpenID Connect Core, it carries an issuer (iss), a subject (sub), an audience (aud) and an expiry (exp), plus claims that describe the job.
  3. The receiving service checks the signature against the provider's published keys, checks the audience and expiry, and compares the claims with its rules.

Each provider exposes it a little differently:

  • GitHub Actions issues the token only to jobs granted the id-token: write permission. Claims include repository, ref and environment (GitHub).
  • GitLab CI issues tokens declared with id_tokens, each with its own aud. Claims include project_path, ref, ref_type and environment. A token expires with the job's timeout, or after 5 minutes if none is set (GitLab).
  • Bitbucket Pipelines acts as an OIDC identity provider for pipeline steps, and custom audiences can be set under oidc (Atlassian).

Why it helps

A stored token works from anywhere until someone revokes it. An OIDC token is minted for one job, expires quickly and says which repository and branch it came from. A rule can require "only the main branch of this repository, deploying to production."

The binding is only as tight as the rules you write. A rule that checks the repository but not the branch accepts any branch that can run a workflow.

How Crunu uses it

In Crunu, OIDC is a binding on a service token, not a replacement for it. You add a CI binding (OIDC) with rules for the provider (GitHub Actions, GitLab CI, Bitbucket Pipelines or any OIDC issuer) and for the repository, branch and deployment environment. With a binding, the token signs in only together with a matching JWT from the CI provider, and a replayed JWT is rejected. The crunu agent picks up the job's token automatically on all three providers.

For example, Kiteline's token github-actions-web-app can read only web-app / staging and is bound to the repository kiteline/web-app on branch main. Kiteline is a fictional company. If that token leaked, it would not sign in outside a matching job.

A restricted environment can go further and accept CI access only from tokens that have an OIDC binding. See OIDC binding and CI/CD.

Sources

From the blog

  • CI/CD

    Giving CI only the secrets it needs

    Long-lived CI tokens work from anywhere until revoked. How to scope pipeline secrets, keep production out of CI, and bind tokens to a repo with OIDC.

  • Security

    One key per environment: why dev must not open prod

    Most tools separate dev and prod with permissions the server enforces. Why the boundary is stronger when each environment has its own encryption key.