Outcome: Workloads can call Formal APIs with IdP JWTs and mint connector access tokens.
Prerequisites: A Formal machine user, and an IdP that can mint OIDC JWTs.
Overview
OIDC integrations let external workloads authenticate to the Formal with short-lived identity-provider JWTs. Formal verifies the token, evaluates a claim condition, and maps the caller to a configured machine user. The same trust can mint a short-lived federation token. Use that credential to access data through a Formal — without long-lived Formal API keys or machine access tokens. Use this for remote workloads such as GitHub Actions, GitLab, Terraform, SPIFFE workloads, E2B sandboxes, Modal Functions, or the Kubernetes Operator.OIDC integrations are separate from SSO. SSO
covers human Control Plane login. OIDC integrations cover machine authentication to
core APIs and optional federated connector access.
How It Works
- You create an OIDC integration with an issuer, machine user, and claim condition.
- Formal returns an audience value:
oidc.formal.ai/<integration_id>. - Your identity provider issues a JWT with that exact
audclaim. - The caller presents the JWT as a Bearer token to Formal core APIs.
- Formal verifies signature, issuer, audience, time claims, and the claim condition.
- The request runs as the integration’s machine user.
- Optionally, the caller mints a federation token and connects through a Connector.
Fixed IdP Audiences
Some identity providers do not let callers customize the JWTaud claim.
These callers must select the integration with a request header:
sub, which varies by run type and
scope:
401 Unauthorized.
The Formal Terraform provider can read Spacelift’s token and send the header:
Setup in the Control Plane
- Go to OIDC.
- Click Create Integration.
- Fill in:
- Name — unique friendly name in your org
- Issuer — absolute HTTPS issuer URL
- JWKS URI — optional; leave empty to use OIDC Discovery
- Machine User — Formal principal that authenticated tokens map to
- Claim Condition — CEL expression over
claims(defaulttrue) - End-User Email Expression — optional CEL that returns an email string
- Status —
activeordraft(draft disables auth)
- Copy the Audience value shown after create.
- Configure your identity provider to mint tokens with that audience.
oidc.formal.ai/integrationoidc_….
Claim Conditions
Claim conditions are CEL expressions that must return a boolean. Verified JWT claims are available underclaims.
Examples:
SPIFFE and SPIRE
SPIFFE workloads authenticate with a JWT-SVID. Formal verifies it like any other OIDC JWT, so the SPIFFE ID arrives as thesub claim.
Formal fetches signing keys from the SPIRE OIDC Discovery Provider. Formal
must reach it over public HTTPS on port 443.
1. Set the JWT-SVID issuer
Formal requires the tokeniss claim to match the integration issuer exactly.
SPIRE omits iss unless you set jwt_issuer on the SPIRE server:
domains entry in the OIDC Discovery Provider config.
Verify:
2. Create the integration
In OIDC, click Create Integration and choose the SPIFFE / SPIRE preset. Set Issuer to thejwt_issuer
URL.
Match the full SPIFFE ID in the claim condition:
/:
3. Fetch a JWT-SVID for Formal
Request a JWT-SVID whose audience is the integration audience. SPIRE lets you set the audience, so you do not needX-Formal-OIDC-Integration-Id.
token(spiffe://example.org/...) followed by
the JWT. Use it as the Bearer token for Formal APIs and CreateFederationToken.
SPIRE issues JWT-SVIDs that expire after five minutes by default. Federation
tokens minted from them expire at the same time.
4. Write policies on the SPIFFE ID
Connector policies read the SPIFFE ID frominput.user.oidc.claims.sub:
E2B Sandboxes
E2B Workload Identity gives each sandbox execution a short-lived JWT-SVID. On E2B Cloud, tokens use issuerhttps://id.e2b.dev and a sub in this format:
1. Create the integration
In OIDC, click Create Integration and choose the E2B preset. Restrict the claim condition to your E2B project, with a trailing/ so other projects cannot match:
2. Inject the token into Formal requests
Register a workload token with the integration audience, then add a network rule that injects it into HTTPS requests to Formal. E2B’s egress proxy adds the header, so sandbox code never handles the token:input.user.oidc.claims.project_id,
input.user.oidc.claims.sandbox_id, and input.user.oidc.claims.template_id.
Modal
Modal injects an identity token into every Function container asMODAL_IDENTITY_TOKEN. Sandboxes and
Sidecars receive one only when created with include_oidc_identity_token=True.
Modal tokens always use the fixed audience oidc.modal.com, so select the
integration with the X-Formal-OIDC-Integration-Id header (see
Fixed IdP Audiences).
1. Create the integration
In OIDC, click Create Integration and choose the Modal preset. Restrict the claim condition to your Modal workspace, and optionally an environment, app, or function:modal token info.
2. Mint a federation token from a Function
input.user.oidc.claims.app_name and
input.user.oidc.claims.function_name.
Federated Connector Access
After an OIDC JWT authenticates to the control plane, callCreateFederationToken to mint a short-lived connector credential.
Only OIDC-authenticated machine users can call this RPC. API keys and human
sessions cannot mint federation tokens.
Mint a federation token
Connect through a Connector
Use the response like any Formal username and access token:<USERNAME> and <FEDERATION_TOKEN> with username and token from
the mint response.
Protocols that present the Formal JWT can authenticate immediately. Protocols
that match stored credentials (for example some MySQL and S3 paths) need the
token to sync to the Connector first. Retry briefly if auth fails right after
mint.
Connect over SSH
Add the resource name after a+ in the SSH username. Enter the password when
prompted:
sshpass in automation:
input.user.oidc.claims.
Token lifetime and claims
Federation token expiry is:Evaluate connector policies with source claims
Connector policy evaluation over source OIDC claims requires Connector 2.16.1 or later.
input.user.oidc:
input.user.oidc.integration_idinput.user.oidc.claims.*
input.end_user.
For example, this session policy allows only a specific GitHub repository and branch:
End-user attribution
Set End-User Email Expression when the workload acts for a human. The CEL expression runs over verified IdP claims and must return an email string. At mint time, Formal resolves that email to a Formal human user (case-insensitive). Sessions then use the machine user for credentials and the human user as the for policy and audit. On resources with linked accounts, the Connector sends the human user’s linked account. The workload then acts upstream as that person, so build the expression only from claims the workload can’t choose itself. Examples:Permissions and Audit
Verified OIDC callers expose claim context to Permissions as:input.user.oidc.integration_idinput.user.oidc.issuerinput.user.oidc.claims.*
Terraform
You can manage the same resource with Terraform:Troubleshooting
Discovery or JWKS fails
Discovery or JWKS fails
Possible causes:
- Issuer is not HTTPS
- Discovery endpoint is unreachable from Formal
- JWKS URI is missing when discovery is unavailable
CreateFederationToken returns failed precondition
CreateFederationToken returns failed precondition
Possible causes:
- Caller used an API key instead of an OIDC Bearer JWT
- Caller is not a machine user
- Upstream OIDC JWT is expired
- End-user email expression failed or matched no Formal human
Connector rejects the federation token
Connector rejects the federation token
Possible causes:
- Token expired (
min(OIDC exp, 1 hour)) - Wrong Formal username (must be the mint response
username) - Credential-match protocol used before the token synced
SSH returns Permission denied
SSH returns Permission denied
Possible causes:
- OpenSSH truncated the federation token, which is longer than 1,023 bytes
- The hashed token was used before it synced to the Connector
- The token expired
formalhash: form of the token as the password, and retry
briefly after mint. Mint a new token if it expired.Next Steps
Permissions
Authorize federated callers with claim-aware rules
Machine Users
Create the machine principal OIDC tokens map to
Connectors
Deploy Connectors that accept federation tokens
SSO
Configure human Control Plane login separately