Skip to content
LearnJSON Web Token (JWT)

What is a JSON Web Token (JWT)?

Also known asJWT claimsID token
Example. Kiteline is a fictional company.
On this page

A JSON Web Token (JWT) is a short string made of a header, a set of claims and a signature, which lets one system make statements, such as "this token was issued by GitHub for a job in repository kiteline/web-app, and it expires at 10:05", that another system can check without calling the first one.

The structure

RFC 7519 defines a JWT as "a compact, URL-safe means of representing claims to be transferred between two parties" (RFC 7519). A signed JWT has three parts separated by dots: header.payload.signature, each base64url-encoded. Decoded, the payload of a CI token might look like this:

JSON
{
  "iss": "https://token.actions.githubusercontent.com",
  "sub": "repo:kiteline/web-app:ref:refs/heads/main",
  "aud": "https://app.crunu.com",
  "exp": 1793352300,
  "iat": 1793352000,
  "jti": "example-unique-id",
  "repository": "kiteline/web-app",
  "ref": "refs/heads/main"
}

The RFC registers seven claim names: iss "identifies the principal that issued the JWT", sub the principal that is its subject, aud "the recipients that the JWT is intended for", exp the time after which it "MUST NOT be accepted", nbf the time before which it must not be accepted, iat when it was issued, and jti a unique identifier. Providers add their own claims, such as repository above. Kiteline is a fictional company.

Signed is not secret

Most JWTs are signed, not encrypted. Anyone holding one can decode the payload and read every claim; the signature only proves who made it and that it hasn't changed. So:

  • don't put secrets in claims;
  • treat the whole token as a credential while it is valid, because whoever holds it can present it.

The RFC also allows encrypted JWTs and an "Unsecured JWT" with no protection at all; the second must never be accepted where identity matters.

What a receiver must check

  1. The signature, against the issuer's published keys, with the algorithm you expect rather than the one the token claims.
  2. iss, exactly.
  3. aud, so a token minted for one service can't be replayed against another.
  4. exp and nbf, with a small allowance for clock skew.
  5. The claims that matter to you, such as the repository and branch. For CI, that is mostly the subject claim.
  6. Single use, where replay matters: remember jti values until they expire.

Common mistakes

  • Checking the signature but not the audience. A valid token for a different receiver passes.
  • Logging the token. A JWT printed in a build log works for anyone until it expires.
  • Long expiry. CI tokens should last minutes, not days.

How Crunu uses JWTs

Crunu accepts the JWTs that GitHub Actions, GitLab CI, Bitbucket Pipelines and other OIDC issuers give to CI jobs, as part of a CI binding (OIDC) on a service token. The server checks the signature against the provider's keys, the issuer, audience and expiry, and matches the claims against your rules. Each JWT can be used once: a replay is refused and raises an alert. Bitbucket's tokens carry no jti, so the server recognizes a replay by a fingerprint of the token's signed part. Use your server address, such as https://app.crunu.com, as the audience.

The claims each CI provider includes, and how to pin them, are in CI/CD secrets with OIDC.

Sources

From the blog

  • CI/CD

    Bitbucket Pipelines OIDC: the step token explained

    What oidc: true gives a Bitbucket step: the BITBUCKET_STEP_OIDC_TOKEN, the workspace issuer, audiences, the sub claim and how to pin a trust policy to it.

    CI and OIDC guide

  • CI/CD

    GitLab CI OIDC without Premium: id_tokens on the Free tier

    The secrets keyword needs GitLab Premium, but id_tokens works on Free. How to exchange a job's ID token for AWS, Google Cloud, Azure or Crunu by hand.

    CI and OIDC guide

  • AI agents

    API keys in MCP server configs: where they end up

    MCP clients keep server settings as plain JSON, and the API key usually sits in it. Where those files live, who can read them and how to keep keys out.

    AI coding agents guide