> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.mixlayer.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.mixlayer.com/_mcp/server.

# Workload Identity Federation

> Authenticate workloads to Mixlayer without long-lived API keys

Workload identity federation lets automated services authenticate to Mixlayer without storing a long-lived API key. The workload presents a short-lived OIDC token or X.509 certificate, and Mixlayer exchanges it for a short-lived access token.

Use workload identity federation for production services, deployment pipelines, and other automated workloads that can obtain an OIDC token or an X.509 client certificate. Continue using an [API key](/api-keys) for local development or environments without a workload identity.

## How it works

1. An organization owner creates a workload identity provider that trusts an external OIDC issuer or certificate authority.
2. The provider transforms credential claims into a required `mixlayer.subject`, optional `mixlayer.groups`, and custom `attribute.*` values.
3. An optional admission condition rejects identities that should not authenticate.
4. Mixlayer evaluates authorization rules in order. The first matching rule supplies the complete permission set.
5. The workload exchanges its external credential for a short-lived Mixlayer bearer token.
6. The workload uses that bearer token with `https://mixlayer.ai` or `https://api.mixlayer.com`.

The final authorization rule is always the unconditional fallback condition `true`. Permissions are not merged between rules.

## Choose a provider type

| Provider type | External credential                                                                                                             | Trust configuration                                                                 |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| OIDC          | A signed JWT from AWS, Azure, GitHub Actions, Google Cloud, Kubernetes, SPIFFE/SPIRE, Vercel, or another OIDC-compatible issuer | Exact issuer URI, one or more audiences, and OIDC discovery or a static public JWKS |
| X.509         | A client certificate presented during TLS                                                                                       | Root CA trust anchors and optional intermediate CA certificates                     |

Choose a setup guide for your workload:

* [AWS](/workload-identity-aws)
* [Azure](/workload-identity-azure)
* [GitHub Actions](/workload-identity-github-actions)
* [Google Cloud](/workload-identity-google-cloud)
* [Kubernetes](/workload-identity-kubernetes)
* [SPIFFE / SPIRE](/workload-identity-spiffe)
* [Vercel](/workload-identity-vercel)
* [X.509 certificates](/workload-identity-x509)

## Configure a provider

You must be an organization owner or use a machine credential with `api-admin` to create or change providers.

#### Console

Open [Workload Identity](https://console.mixlayer.com/app/workload-identity) in the Mixlayer console and select **New provider**.

Configure these sections:

1. **General settings:** Give the provider a descriptive name, choose OIDC or X.509, and choose whether it accepts exchanges.
2. **Provider trust configuration:** Enter the OIDC issuer and audiences or the X.509 CA certificates.
3. **Attribute transformations:** Map verified credential values into `mixlayer.subject`, `mixlayer.groups`, or `attribute.*` values.
4. **Admission condition:** Optionally reject credentials before authorization.
5. **Permissions:** Set the fallback permissions. Add ordered authorization rules after creating the provider when different workloads need different permissions.

Use **Test rules** with a representative assertion before enabling a provider. Policy tests evaluate transformations, admission, and authorization without issuing a credential.

#### API

The following example creates an OIDC provider for one GitHub repository. Use an existing API key with `api-admin` for this management request.

**`file=`**

```bash file=create-workload-identity-provider.sh
curl https://api.mixlayer.com/v1/organizations/$MIXLAYER_ORG_ID/workload_identity/providers \
  -H "Authorization: Bearer $MIXLAYER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "github-actions-production",
    "active": true,
    "attribute_transformations": {
      "mixlayer.subject": "assertion.sub",
      "attribute.repository_id": "assertion.repository_id",
      "attribute.repository_owner_id": "assertion.repository_owner_id"
    },
    "attribute_condition": "attribute.repository_owner_id == \"12345678\" && attribute.repository_id == \"87654321\"",
    "authorization_rules": [
      {
        "condition": "true",
        "permissions": ["inference"]
      }
    ],
    "config": {
      "type": "oidc",
      "issuer_uri": "https://token.actions.githubusercontent.com",
      "allowed_audiences": ["https://api.mixlayer.com"],
      "jwks": null
    }
  }'
```

Omit `jwks` or set it to `null` to use public OIDC discovery. Supply a static public JWKS object when the issuer is not publicly reachable. Never include private signing-key material.

## Map identity attributes

Attribute transformations are CEL expressions evaluated against the verified external credential. Every provider must produce a non-empty string at `mixlayer.subject`.

```text
mixlayer.subject       = assertion.sub
mixlayer.groups        = assertion.groups
attribute.environment = assertion.environment
```

Transformations can read only `assertion.*` values and are evaluated independently. If `mixlayer.groups` is omitted, Mixlayer uses an empty list.

OIDC assertions include the verified `iss`, `sub`, `aud`, `exp`, and `iat` claims plus other claims from the JWT. X.509 assertions are described in the [X.509 guide](/workload-identity-x509).

## Restrict admission

An admission condition can read `assertion.*`, `mixlayer.*`, and `attribute.*`. Use it to reject identities that should receive no Mixlayer access, especially when trusting a shared issuer such as GitHub Actions.

```cel
attribute.repository_owner_id == "12345678" &&
attribute.repository_id == "87654321"
```

A false result or evaluation error rejects the exchange.

## Assign permissions

Authorization conditions can read normalized `mixlayer.subject`, `mixlayer.groups`, and `attribute.*` values. They cannot read raw `assertion.*` claims; map an authorization-relevant claim first.

```json
[
  {
    "condition": "attribute.environment == \"production\"",
    "permissions": ["api-read", "inference"]
  },
  {
    "condition": "true",
    "permissions": ["inference"]
  }
]
```

Evaluation stops at the first match. Its permissions are the complete result; later rules are not evaluated or merged. To deny an identity entirely, reject it in the admission condition.

The available permissions are the same as for API keys:

| Permission  | Grants                                                                           |
| ----------- | -------------------------------------------------------------------------------- |
| `inference` | Calls to Mixlayer model inference APIs                                           |
| `api-read`  | Read access to Platform API resources                                            |
| `api-write` | `api-read` plus non-administrative Platform API writes                           |
| `api-admin` | Administrative Platform API operations; also includes `api-read` and `api-write` |

`api-admin` does not imply `inference`.

## Exchange an OIDC token

Set the provider ID returned when you created the provider and obtain a current JWT from your workload environment:

```bash
export MIXLAYER_IDENTITY_PROVIDER_ID="wi_..."
export MIXLAYER_SUBJECT_TOKEN="..."
```

Exchange it for a Mixlayer access token:

**`file=`**

```bash file=exchange-workload-identity-token.sh
MIXLAYER_ACCESS_TOKEN=$(
  jq -n \
    --arg provider "$MIXLAYER_IDENTITY_PROVIDER_ID" \
    --arg token "$MIXLAYER_SUBJECT_TOKEN" \
    '{
      grant_type: "urn:ietf:params:oauth:grant-type:token-exchange",
      subject_token_type: "urn:ietf:params:oauth:token-type:jwt",
      subject_token: $token,
      identity_provider_id: $provider
    }' |
  curl --fail-with-body --silent --show-error \
    https://api.mixlayer.com/v1/workload_identity/token \
    -H "Content-Type: application/json" \
    --data-binary @- |
  jq -er .access_token
)
```

Use the resulting token like an API key:

**`file=`**

```bash file=call-mixlayer-with-workload-token.sh
curl https://mixlayer.ai/v1/chat/completions \
  -H "Authorization: Bearer $MIXLAYER_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen/qwen3.5-4b-free",
    "messages": [{"role": "user", "content": "Hello from a federated workload"}]
  }'
```

Mixlayer does not return a refresh token. The access token lasts for at most one hour and never outlives the external JWT or X.509 certificate. Reuse it until shortly before expiry, then obtain a new external credential and exchange again.

## Operate providers safely

* Use a separate provider for each issuer and trust boundary.
* Use a dedicated audience such as `https://api.mixlayer.com` rather than an audience shared with unrelated services.
* Prefer stable, immutable subject identifiers.
* Grant only the permissions the workload needs.
* Keep clocks synchronized so short-lived credentials pass `iat`, `nbf`, and `exp` validation.
* Do not log external credentials, Mixlayer access tokens, certificates, or private keys.
* Deactivate a provider to stop new exchanges. Provider policy changes also invalidate tokens issued under the previous policy revision; inference services may take up to one minute to observe the change.

If an exchange fails, compare the credential's issuer, audience, subject, expiry, and signing key with the provider. Then test the same assertion against the provider policy to find transformation, admission, or rule errors.