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

# Set up OIDC sign-in for MDM

> Create the public OIDC client that Claude Code, Codex, and Claude Desktop use to sign employees in to the TrueFoundry AI Gateway in an MDM rollout.

With OIDC, no credential is written into the agents' configuration. Claude Code and Codex ask the installed `tfy-local-ai-setup` binary for a token when they need one, and Claude Desktop signs in itself. One public OIDC client, with no client secret, serves all three agents.

To compare OIDC with device login, see [Choose how employees sign in](https://www.truefoundry.com/docs/ai-gateway/mdm-setup.md#choose-how-employees-sign-in).

## Create the OIDC client

**1. Create a Personal Access Token**

Create a [Personal Access Token](https://www.truefoundry.com/docs/generating-truefoundry-api-keys.md#create-a-pat) as a user with the **Manage settings** permission on the tenant. You need it only to create the client.

**2. Create the client**

Replace the control-plane URL and token, then run:

```bash theme={"dark"}
curl --request PUT '<your-control-plane-url>/api/svc/v1/oidc/clients' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer <your-PAT>' \
  --data '{
    "manifest": {
      "name": "tfy-mdm",
      "display_name": "TrueFoundry MDM",
      "client_type": "public",
      "application_type": "native",
      "token_endpoint_auth_method": "none",
      "pkce": "required",
      "redirect_uris": [
        "http://127.0.0.1/callback",
        "http://127.0.0.1:8585/callback",
        "http://127.0.0.1:8586/callback",
        "http://127.0.0.1:8587/callback"
      ],
      "allowed_scopes": ["openid", "profile", "email", "offline_access"],
      "allowed_grant_types": ["authorization_code", "refresh_token"],
      "access_token_ttl": "1d",
      "refresh_token_ttl": "7d",
      "refresh_token_max_uses": 1
    }
  }'
```

On a self-hosted control plane, use its URL; the path stays `/api/svc/v1/oidc/clients`.

* **Redirect URIs:** Claude Desktop uses `http://127.0.0.1/callback`. The binary, which signs in for Claude Code and Codex, listens on port 8585, or on 8586 or 8587 if that port is busy.
* **`refresh_token_ttl`** sets how long an employee stays signed in without using an agent. With `refresh_token_max_uses: 1`, each refresh issues a new refresh token.

**3. Copy the client ID**

The response looks like `{ "data": { "id": "cli_...", "manifest": { ... } } }`. `data.id` is the client ID.

Sending the request again with the same `manifest.name` updates the client and keeps its ID. `client_type` cannot be changed after creation.

**4. Find the issuer**

The issuer is your control-plane URL followed by `/<tenant>`, for example `https://<tenant_name>.truefoundry.cloud/<tenant_name>`. Open `<issuer>/.well-known/openid-configuration` and copy its `issuer` value exactly.

**5. Add OIDC to mdm.toml**

Replace the `[auth]` table in your deployment script:

```toml theme={"dark"}
[auth]
mode = "oidc"

[auth.oidc]
issuer = "https://<tenant_name>.truefoundry.cloud/<tenant_name>"
client_id = "cli_abc123"
```

The client ID is public, so it is safe in the script. To use OIDC for only some agents, keep `mode = "api-key"` and set `auth = "oidc"` in the `[agents.claude-code]`, `[agents.codex]`, or `[agents.claude-desktop]` table. All additional agents must use the same mode.

## What employees see

* **MDM runs** write the configuration and never open a browser.
* **Claude Code and Codex** open a browser sign-in the first time they need a token. Later requests reuse the cached access token, or refresh it silently, without a browser.
* **Claude Desktop** asks the employee to sign in on first launch and keeps its own session.
* **When the refresh token expires**, after `refresh_token_ttl` without use, the next request opens the browser again.

If an employee closes the sign-in window, they use the agent again to get a new one. They do not need to wait for the next MDM run.

## What OIDC writes

| Agent | Configuration |
| - | - |
| Claude Code | `apiKeyHelper` runs `tfy-local-ai-setup --_print-oidc-token --oidc-issuer=<issuer> --oidc-client-id=<client-id>` |
| Codex | `[model_providers.truefoundry.auth]` with the same command and arguments |
| Claude Desktop | `inferenceCredentialKind` = `external-idp`, and `inferenceIdpOidc` = `{"bearerTokenType":"access_token","clientId":"<client-id>","issuer":"<issuer>","scopes":"openid profile email offline_access"}` |

The binary caches tokens in the employee's `~/.tf/oidc-*` files. These are separate from device login's `~/.tf/refresh-token`.

Keep the Claude Desktop defaults:

* **`bearerTokenType` must be `access_token`.** The gateway validates access tokens and rejects ID tokens, which are Desktop's default.
* **Keep `openid` in the scopes**, or Desktop's sign-in fails. Desktop still sends the access token to the gateway.

The binary flags `--oidc-bearer-token-type` and `--oidc-scopes` change these values; leave them at their defaults for TrueFoundry.

> [!NOTE]
>
> **Claude Desktop 2.7032.0 or later is required** on every device before you roll out OIDC. These settings replace the older `interactive` and `inferenceGatewayOidc` pair, which the binary removes on its next run. The issuer, client ID, scopes, and token type stay the same.

## Limitations

* Codex's [ChatGPT subscription mode](https://www.truefoundry.com/docs/ai-gateway/mdm/codex.md#use-a-chatgpt-business-or-enterprise-subscription) needs device login.
* [Deferred PAT sign-in](https://www.truefoundry.com/docs/ai-gateway/mdm-setup.md#defer-sign-in-with-a-pat) does not work with OIDC.
* [MCP discovery](https://www.truefoundry.com/docs/ai-gateway/mdm-setup.md#discover-each-employees-mcp-servers-and-skills) uses the employee's cached OIDC sign-in. Until the employee has signed in once, runs with `mcp.discovery` fail without writing any configuration, so Claude Code never receives its sign-in command. Roll out without discovery first.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.