Skip to main content
Workload identity federation lets a workload call the Dodo Payments API with no stored API key. The workload gets a signed OIDC token (a JWT) from its own platform, for example GitHub Actions or Google Cloud. Dodo Payments verifies the JWT and gives back a short-lived Dodo token. The token expires in 1 hour or less, except for terraform_cloud, where it lasts until the run phase ends.

Dashboard Setup

Add an identity provider and a mapping, then monitor tokens and events.

SDK Usage

Configure the SDKs to do the exchange and the refresh for you.

Provider Guides

Step-by-step setup for each supported platform.

Terraform

Run the Terraform provider with no API key in your pipeline.

Why Use Workload Identity

An API key is a long-lived secret. You must store it in your CI system or your cloud, rotate it, and remove it when a person leaves. If the key leaks, an attacker can use it until you delete it. With workload identity federation:
  • No secret to store. The workload keeps only the identity provider id (wip_...). This id is not a secret.
  • Short-lived credentials. Each Dodo token expires in 1 hour or less. A terraform_cloud token lasts until the end of the run phase. To continue, the workload does a new exchange.
  • Precise trust. A mapping trusts only the JWTs that match its conditions, for example one repository and one branch.
  • Same permissions model. The token gets the scopes of the mapping, and the usual API key rate limits apply.
  • Audit. Each exchange, failure, revocation, and configuration change writes an event that you can see in the dashboard.

Supported Platforms

Key Concepts

An identity provider (wip_...) tells Dodo Payments which issuer to trust. It has a provider type, an issuer URL, and an audience. Each provider belongs to one mode, test mode or live mode. A business can have 50 providers.
A mapping (wim_...) belongs to a provider. It has a list of claim conditions, a list of API scopes, an optional list of allowed CIDR ranges, and a token lifetime. A provider can have 50 mappings.
The exchange gives a Dodo token that has the same format as an API key. Send it as Authorization: Bearer <token>. There is no refresh token. To renew the token, do the exchange again.

How the Exchange Works

  1. The workload requests an OIDC token from its platform. The audience of the token is the Dodo Payments audience of your mode.
  2. The workload sends the JWT and the identity provider id to POST /workload-identity/token. This request does not need an API key.
  3. Dodo Payments verifies the JWT signature with the public keys of the issuer. It also checks the issuer, the audience, the times, and the required claims.
  4. Dodo Payments finds the enabled mappings whose conditions all match the JWT. Exactly one mapping must match.
  5. Dodo Payments gives back a Dodo token with the scopes of that mapping.
The SDKs do these steps for you. Refer to SDK Usage.

Audience

The default audience is the Dodo Payments URL of the mode of the provider: Thus a test mode JWT fails in live mode. A provider cannot use the audience of the other mode. The kubernetes, gcp, vercel, and custom types must use the default audience. The github_actions, gitlab, terraform_cloud, and aws types can use a different audience.

Verification Rules

Token Lifetime

A Dodo token lives for the token_ttl_seconds of the mapping. The value is between 300 and 3600 seconds. The default is 3600 seconds (1 hour). The lifetime does not depend on the exp of the JWT. The terraform_cloud type is different. HCP Terraform gives one JWT for each plan or apply phase, and that JWT can do one exchange only. Thus the Dodo token lives until the JWT expires, which is the end of the run phase, with a maximum of 24 hours. A mapping can have a maximum of 500 active tokens. When it has 500, the exchange fails with the token_limit reason until tokens expire or you revoke them.

Scopes

The Dodo token gets the scopes of the mapping that matched. The workload cannot ask for more scopes. Each scope of a mapping must be a scope that the dashboard user who creates the mapping also holds. Refer to Dashboard Setup.

IP Allowlist

A mapping can have a list of allowed CIDR ranges (allowed_cidrs), for IPv4 and IPv6.
  • At the exchange. If the source IP is not in the list, the exchange fails with invalid_grant and the ip_not_allowed reason.
  • On each API call. The Dodo token gets a copy of the list. Each API call from an IP that is not in the list gets 403.
Use this list to limit a workload to its known egress IPs, for example the NAT IPs of a cluster.

Replay Protection

The github_actions, gitlab, terraform_cloud, and aws platforms give a new JWT for each request. For these types, the JWT must have a jti claim, and each JWT can do one exchange only. A second exchange with the same JWT fails with invalid_subject_token and the replay reason. The kubernetes, gcp, vercel, and custom types do not enforce jti. For example, the kubelet writes the same service account token to a file for most of its life, and all processes in the pod read that token. For these types, these controls apply:
  • The provider must use the Dodo Payments audience of its mode, thus no other service accepts the JWT.
  • The mapping must pin a stable claim, for example sub.
  • The Dodo token lives 1 hour or less.
  • You can add allowed_cidrs to the mapping.

Revocation

These actions stop Dodo tokens immediately: Dodo Payments examines the JWT claims at the exchange only. A change on your platform after the exchange does not revoke a Dodo token. Examples are a moved repository, a deleted service account, or a renamed environment. The token stays valid until it expires, and the next exchange fails. For an immediate stop, use one of the actions in the table. To revoke the current token from a workload, send it to the revoke endpoint. The response is 204:

Audit Events

The dashboard lists the events of your providers for 90 days. Events record only an allowlist of claims, for example iss, sub, jti, repository, ref, sha, and run_id. Dodo Payments never stores the JWT.

Reason Codes

Event Limits

Dodo Payments records failure events only for a known provider. A provider records a maximum of 60 exchange_failed events each minute for one source IP, and 600 each minute for all source IPs. The first failure over a limit records one rate_limited event. These limits apply to the audit log only. They do not change the result of an exchange.

Exchange Errors

The exchange endpoint uses the OAuth 2.0 error format { "error", "error_description" }. error_description tells you which claim or value to correct. It does not show the expected value of a condition. The audit event has the full reason.

Dashboard Setup

Create your first provider and mapping.

SDK Usage

Use workload identity from the SDKs or with curl.
Last modified on October 28, 2026