> ## Documentation Index
> Fetch the complete documentation index at: https://www.c1.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Custom OIDC providers

> Set up workload federation with any OIDC-compliant identity provider.

<Warning>
  **Early access.** This feature is in early access, which means it's undergoing ongoing testing and development while we gather feedback, validate functionality, and improve outputs. Contact the C1 Support team if you'd like to try it out or share feedback.
</Warning>

Any platform that issues OIDC tokens can be used with workload federation. This guide covers the generic token exchange flow for providers that don't have a built-in preset.

## Provider requirements

Your OIDC provider must:

1. Serve a `/.well-known/openid-configuration` document at the issuer URL
2. Have a publicly accessible JWKS (JSON Web Key Set) endpoint
3. Issue JWTs with standard claims: `iss`, `aud`, `exp`, `iat`

## Prerequisites

* A service principal with a Custom OIDC federation trust. See [set up federation](/product/admin/service-principals/federation-setup) if you haven't created one yet. Use the **Custom OIDC** preset and enter your provider's issuer URL.
* The trust's **client ID** (for example `quiet-bear-88456@yourcompany.conductor.one/wfe`)

## Exchange the token

Send the external OIDC JWT to C1's token exchange endpoint:

```bash theme={"theme":{"light":"css-variables","dark":"css-variables"}}
curl -s -X POST "https://yourcompany.conductor.one/auth/v1/token" \
  -d "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
  -d "subject_token=$YOUR_JWT" \
  -d "subject_token_type=urn:ietf:params:oauth:token-type:jwt" \
  -d "client_id=quiet-bear-88456@yourcompany.conductor.one/wfe"
```

Response on success:

```json theme={"theme":{"light":"css-variables","dark":"css-variables"}}
{
  "access_token": "eyJhbGciOiJFZERTQSIs...",
  "issued_token_type": "urn:ietf:params:oauth:token-type:access_token",
  "token_type": "Bearer",
  "expires_in": 1800
}
```

Use the `access_token` in an `Authorization: Bearer` header for API calls.

## Token requirements

The JWT must satisfy these requirements:

| Requirement            | Detail                                                                       |
| :--------------------- | :--------------------------------------------------------------------------- |
| **Issuer (`iss`)**     | Must match the provider's issuer URL exactly                                 |
| **Audience (`aud`)**   | Must contain your C1 tenant domain (for example `yourcompany.conductor.one`) |
| **Expiration (`exp`)** | Must not be expired                                                          |
| **Issued at (`iat`)**  | Must be within the last 10 minutes                                           |
| **Signature**          | Must be verifiable via the provider's JWKS endpoint                          |

## Writing CEL expressions

The CEL expression evaluates against the JWT's decoded claims. Write an expression that validates the `sub` claim and any additional claims for defense-in-depth scoping:

```go theme={"theme":{"light":"css-variables","dark":"css-variables"}}
claims.sub == "expected-subject" && claims.custom_claim == "expected-value"
```

### Tips for writing expressions

* Always validate the `sub` claim or an equivalent unique identifier
* Use additional claims for defense-in-depth: organization, project, environment
* CEL string functions are available: `contains()`, `startsWith()`, `endsWith()`, `matches()`, `size()`
* For namespaced claims (like AWS), use bracket notation: `claims["https://example.com/"].field`
* Expressions are limited to 1,024 bytes

## Using with C1 tools

Once you have the access token, set the `CONDUCTORONE_ACCESS_TOKEN` environment variable and all C1 tools pick it up automatically:

```bash theme={"theme":{"light":"css-variables","dark":"css-variables"}}
export CONDUCTORONE_ACCESS_TOKEN=$(curl -s -X POST ... | jq -r '.access_token')

# Use with any tool
cone whoami
terraform apply
```

Alternatively, set `CONDUCTORONE_OIDC_TOKEN` with the raw JWT and `CONDUCTORONE_CLIENT_ID` with the trust client ID. The Go SDK, Cone CLI, and Terraform provider all support this pattern and handle the token exchange internally.

## Security best practices for custom OIDC providers

<Warning>
  Always validate the `sub` claim and use additional claims for defense-in-depth scoping. A CEL expression that only checks one claim may be too permissive if the provider issues tokens with broad subjects.
</Warning>
