inferenceProvider to gateway and supply the base URL and credentials described below.
The gateway must implement the Anthropic Messages API:
POST /v1/messageswith streaming and tool use is required.GET /v1/modelsis optional. If the gateway implements it, Claude Desktop on 3P auto-discovers available models; if not, setinferenceModelsexplicitly.
cache_control breakpoints with each turn so that the provider can reuse the tool definitions, system prompt, and earlier turns of the conversation instead of reprocessing them. A gateway that forwards these fields, or translates them for its upstream provider, keeps that behavior. A gateway that strips cache_control, or that changes the system prompt or tool list from one request to the next, makes the provider reprocess the whole conversation on every turn at full input-token cost and higher latency. To verify, check the usage fields your gateway returns or logs for Claude Desktop traffic: after the first request of a session, cache_read_input_tokens should be well above zero on most requests. If it is zero on every request, review the gateway’s request transformation and caching settings for the route that serves Claude models.
Choose an authentication approach
Prepare devices
Static API key
No per-device preparation is required. Generate an API key in your gateway and place it in the managed configuration asinferenceGatewayApiKey (see Configure the app).
Single sign-on with your identity provider
Instead of distributing a shared gateway API key, you can have each user sign in with their own work account. The first time a user opens Claude Desktop, the app opens their browser to your organization’s normal sign-in page (Microsoft Entra ID, Okta, or any OpenID Connect provider). After they sign in, the app sends a per-user token to your gateway on every request, and your gateway checks that token to confirm who the user is. This gives you per-user attribution in your gateway logs, lets your identity provider enforce MFA and conditional access, and means there is no long-lived credential to distribute or rotate. You need three things in place:- An LLM gateway that can validate JSON Web Tokens (LiteLLM, Kong, Envoy, and Azure API Management all support this)
- Admin access to your identity provider to register a new application
- A way to push managed configuration to user devices (your existing MDM)
Set up single sign-on
1
Register an application in Entra ID
In the Microsoft Entra admin center, go to Identity → Applications → App registrations and select New registration. Give it a name such as A few details that matter here: use
Claude Desktop gateway, choose Accounts in this organizational directory only, and select Register.On the overview page, copy the Application (client) ID and Directory (tenant) ID. You will use both in the next two steps.Open the Authentication blade, select Add a platform, and choose Mobile and desktop applications. Under Custom redirect URIs, add exactly:127.0.0.1 (not localhost), include the /callback path, and add it under the Mobile and desktop applications platform specifically. That platform is the only one Entra allows to use any local port, which the app needs because it picks a free port at sign-in time. You do not need a client secret or any additional API permissions.2
Configure your gateway to validate the token
Tell your gateway to accept the bearer token only if it was issued by your tenant for this application. In LiteLLM that looks like:Replace
YOUR_TENANT_ID and YOUR_CLIENT_ID with the values from step 1.For Kong, Envoy, or Azure API Management, configure the equivalent JWT validation policy with the same JWKS URL and audience.3
Configure in the app
Open the in-app configuration window (Developer → Configure Third-Party Inference…). In the Connection section, set Inference provider to Gateway and Credential kind to Interactive sign-in. This hides the API-key field and reveals Gateway SSO IdP (OIDC):
Then click Export to produce a
.mobileconfig (macOS) or .reg (Windows) file for your MDM. See Deploy with MDM for the export and deployment workflow.When a user next opens Claude Desktop, they see a Sign in to your organization button. Clicking it opens their browser to your Entra sign-in page; once they approve, they return to the app and can start working. The app keeps them signed in and refreshes the token in the background. If the session is revoked or expires under your tenant’s policy, the app shows a Sign in again prompt; clicking it reopens the sign-in page in the browser.Using Okta instead
In the Okta Admin Console, create a Native application with the Authorization Code and Refresh Token grant types. Okta requires the redirect URI to match exactly, including the port, so pick a fixed port (for example53180), register http://127.0.0.1:53180/callback, and set that same port in Gateway SSO IdP (OIDC):
Use the issuer value, not the Metadata URI. Okta’s admin console shows the metadata URI (ending in
/.well-known/openid-configuration) prominently — that is the discovery document the app fetches from the issuer, not the issuer itself. If you are unsure, open the metadata URI in a browser and copy the "issuer" field from the JSON response. For a custom Okta authorization server the issuer is https://YOUR_ORG.okta.com/oauth2/AUTH_SERVER_ID.https://YOUR_ORG.okta.com/oauth2/v1/keys with audience set to the Okta client ID.
Map users at the gateway
Claude Desktop forwards the identity provider’s token to your gateway verbatim — it does not add, remove, or rewrite any claims. With the default scopes (openid profile email offline_access), the ID token your gateway receives contains the standard OIDC sub, email, and name claims, plus whatever your provider includes for the profile scope. You can confirm exactly what is present by base64-decoding the middle segment of the Authorization: Bearer value your gateway receives.
Key the gateway’s user record on the provider’s immutable user ID rather than email, so the record survives email or name changes:
If your gateway has no existing user records to preserve, the simplest setup is to auto-provision on first sign-in. For LiteLLM, extend the validation block from step 2:
groups claim for team-level budgets), add them on your identity provider’s authorization server — they pass through to the gateway unchanged. To request a non-default scope, set scopes in inferenceGatewayOidc (see Single sign-on configuration keys).
Refresh tokens and session lifetime
Silent token refresh requires a refresh token from your identity provider, which in turn requires theoffline_access scope on the authorization request. Whether Claude Desktop sends that scope depends on how you set scopes and bearerTokenType:
scopesleft unset — the default (openid profile email offline_access) includesoffline_access, so a refresh token is issued.bearerTokenType: "access_token"— Claude Desktop automatically appendsoffline_accessto whateverscopesvalue you supply, unlessappendOfflineAccessis set tofalse.bearerTokenType: "id_token"(the default) withscopesset explicitly — Claude Desktop does not addoffline_accessfor you. Include it in yourscopesvalue if you want silent refresh; without it, users are prompted to sign in again each time the ID token expires (commonly about one hour).
offline_access signals that the client may use the refresh token while the user is not present, and the provider must obtain consent for it. Claude Desktop therefore does not add this scope to an administrator-supplied scopes value in the default mode, so that requesting offline access remains an explicit choice.
Authorization servers that reject offline_access. Standard OIDC providers (Entra ID, Okta, Auth0) accept offline_access and require it to issue a refresh token, so the automatic append is what you want. If your authorization server instead rejects unrecognized scopes with an invalid_scope error — for example, servers that issue refresh tokens via a provider-specific scope rather than offline_access — set appendOfflineAccess to false and include your provider’s own refresh-token scope in scopes directly.
Refresh tokens govern whether users are re-prompted to sign in, not how long a sign-in may stay valid. To cap the sign-in lifetime under your identity provider’s session policy, set inferenceSessionLifetimeSec; Claude Desktop shows a re-authenticate banner before the session expires.
Configure the app
Open the in-app configuration window (Developer → Configure Third-Party Inference…). In the Connection section, set Inference provider to Gateway, then fill in the Gateway credentials card:
Then click Export to produce a
.mobileconfig (macOS) or .reg (Windows) file for your MDM. See Deploy with MDM for the export and deployment workflow.
Configuration keys
inferenceStreamIdleTimeoutSec details
inferenceStreamIdleTimeoutSec details
Raises how long Cowork, Chat and Code sessions wait for the next model event on an open streaming response (Claude Code’s
CLAUDE_STREAM_IDLE_TIMEOUT_MS). It only helps when the gateway writes SSE keep-alive ping events (or : comment lines) into the response while the upstream model is silent — for example a LiteLLM proxy with keep-alive pings enabled in front of Amazon Bedrock. With pings arriving, Claude Code accepts at least about five minutes of keep-alives and then waits this many seconds more for real model output before abandoning the request. Gateway provider only; the other providers keep Claude Code’s defaults.A response on which nothing at all arrives — no pings — still fails after about 5 minutes regardless of this key, because at the device a silent connection cannot be told apart from a dead one. If long generations fail behind a gateway that does not send pings, configure the gateway to send them rather than raising this value. While this key is set, the app’s value takes precedence over CLAUDE_STREAM_IDLE_TIMEOUT_MS in Claude Code’s own managed settings for sessions the app starts; when it is unset, that setting still applies. Values outside 300–1800 are rejected at parse time (the error is listed in the diagnostics report) and the default applies.inferenceGatewayOidcAuthFlow details
inferenceGatewayOidcAuthFlow details
browser(default) — opens the system browser for an authorization-code (PKCE) sign-in on a loopback redirect URI. See the IdP setup notes oninferenceGatewayOidcfor redirect-URI registration.broker— signs in through the OS identity broker (Web Account Manager on Windows, Company Portal on macOS). Requires the IdP to be Microsoft Entra ID — theissueroninferenceGatewayOidcmust behttps://login.microsoftonline.com/{tenant-id}/v2.0. The broker satisfies Conditional Access policies that require a compliant/managed device or token protection, and needs no127.0.0.1/callbackloopback redirect. The Entra app registration must include the broker redirect URIsms-appx-web://Microsoft.AAD.BrokerPlugin/{client-id}(Windows) andmsauth.com.anthropic.claudefordesktop://auth(macOS) under the Mobile and desktop applications platform. Not supported on Linux.
scopes, and forwards it to the customer’s own gateway; both endpoints of that trust relationship are inside the customer’s control.inferenceGatewayOidc details
inferenceGatewayOidc details
External IdP mode. The app discovers
<issuer>/.well-known/openid-configuration, runs an OIDC authorization-code-with-PKCE sign-in in the system browser with clientId, and sends the resulting token as Authorization: Bearer on every inference request. Leave this unset for a gateway that hosts its own RFC 8414 metadata at <baseUrl>/.well-known/oauth-authorization-server.Bearer token type. id_token (the default) sends the OIDC ID token; the gateway validates signature, iss, and aud (the clientId configured here). access_token sends the OAuth access token, for gateways that validate as a resource server (Portkey, Kong, Envoy JWT filter, AWS API Gateway authorizers); scopes must then name the gateway’s registered API scope. Either way the gateway must check aud, not just signature and issuer, or it accepts any token from your tenant.IdP setup. The app’s loopback callback is http://127.0.0.1:<port>/callback; register 127.0.0.1 (not localhost) and include /callback. Entra: a public-client app with a Mobile and desktop applications redirect URI of http://127.0.0.1/callback (any port; omitting the path fails with AADSTS50011); in access_token mode also grant the gateway API’s delegated permission, or sign-in fails with AADSTS65001. Okta: a Native app with the exact URI http://127.0.0.1:<port>/callback and that port in redirectPort.Refresh. With offline_access the app renews the token silently and prompts a browser sign-in only when refresh fails. Google never returns an id_token on refresh, so a Google Workspace-backed gateway in id_token mode re-prompts about hourly; access_token mode is unaffected.inferenceCustomHeaders. It applies to all providers, not just gateways.
Single sign-on configuration keys
Single sign-on is enabled by settinginferenceCredentialKind to interactive and supplying inferenceGatewayOidc. Both are required — interactive alone (without inferenceGatewayOidc) selects a different mode where the gateway itself acts as the authorization server.
The
inferenceGatewayOidc value is one JSON object with these fields:
* Either
issuer, or both authorizationUrl and tokenUrl, is required.
In a macOS .mobileconfig payload (Okta example):
inferenceGatewayAuthScheme: "sso" to select this mode. That value is deprecated; set inferenceCredentialKind: "interactive" instead. Existing deployments that still send inferenceGatewayAuthScheme: "sso" continue to work until October 7, 2026. After that date the value no longer selects browser sign-in, so set inferenceCredentialKind: "interactive" before then.
Models
WheninferenceModels is unset, Claude Desktop on 3P populates the model picker from your gateway’s GET /v1/models response. Auto-discovery shows only models whose IDs are recognizably Claude; if your gateway advertises models under opaque aliases, set inferenceModels explicitly. Set inferenceModels to override discovery with an explicit list — the picker will show exactly the entries you provide. Use the model IDs your gateway expects (for example bedrock/us.anthropic.claude-opus-5 for a LiteLLM-style routing prefix).
If your gateway serves a Claude model under an opaque routing alias, it can mark the model as Claude by returning an anthropic_family_tier field (a Claude tier name such as sonnet or opus) on that model object in its /v1/models response, optionally with is_family_default: true when several models map to the same tier. Models marked this way pass the auto-discovery filter.
If your gateway does not implement GET /v1/models, give every inferenceModels entry the full model ID your gateway accepts; bare tier aliases such as sonnet rely on discovery to resolve. When every entry is a full model ID, the app skips the /v1/models call automatically. A list that contains a bare alias keeps discovery on, so for a gateway without the endpoint, replace the alias with the full model ID; a bare alias cannot be resolved without discovery. On earlier app versions that do not skip the call automatically, also set modelDiscoveryEnabled to false to avoid the discovery attempt. The cost of leaving discovery on without the endpoint depends on how the gateway fails: an error response makes the app fall back to the inferenceModels list immediately, while an endpoint that accepts the request and hangs delays the model list by up to 10 seconds at launch.
If your deployment supports the 1M-token context window for a model, set supports1m: true on that model’s entry:
supports1m is an assertion about your gateway rather than something the app can verify: if the gateway does not accept 1M-token requests for that model, requests made from the 1M picker entry fail at inference time. Only set it on models you have confirmed against your deployment. The Models section of the configuration reference documents the remaining entry fields, including display labels and tier mapping.
MCP tool search
MCP tool search loads MCP tool schemas on demand instead of inlining every schema into the context window. It reduces context pressure when many MCP tools are configured (sessions that otherwise compact every turn or two). On gateway deployments, Claude Desktop turns tool search off by default, along with Claude Code’s other experimental beta features, because strict gateways reject the experimentalanthropic-beta request headers and request fields those features add. The same applies to Microsoft Foundry deployments and to any provider configured with a custom base URL. Setting the ENABLE_TOOL_SEARCH environment variable to true does not lift this suppression. To turn tool search on for these deployments, set the toolSearchEnabled configuration key. Requires app version 1.21459.0 or later.
On Claude API, Google Cloud’s Agent Platform, Amazon Bedrock, and Amazon Bedrock Mantle deployments with no custom base URL, tool search is on by default from Claude Desktop 1.49585.0 and toolSearchEnabled is not needed. These versions leave Claude Code’s experimental beta features on for those providers, as terminal Claude Code does (on Google Cloud’s Agent Platform, tool search applies to Claude 4.5 and newer models). To turn tool search off on these deployments, set ENABLE_TOOL_SEARCH to false in the env block of OS-level Claude Code managed settings, with parentSettingsBehavior set to merge. On earlier app versions these providers also have tool search off by default, and toolSearchEnabled turns it on.
Troubleshoot
gateway SSO: server does not advertise device_authorization_endpoint — The app could not read your inferenceGatewayOidc value, so it fell back to treating the gateway itself as the sign-in server. Almost always this means the value is missing or not valid JSON, for example because it was written as separate dotted keys instead of one inferenceGatewayOidc value. Re-export from the in-app configuration window, or copy the .mobileconfig snippet above.
OIDC discovery failed (HTTP 404) or (HTTP 405) — The issuer value is not the issuer base URL. Most often the metadata URI (ending in /.well-known/openid-configuration) was pasted instead, which doubles the path. Remove that suffix so issuer is just https://YOUR_ORG.okta.com (or the equivalent for your provider).
no credential configured for provider "gateway": set inferenceCredentialKind or one of the credential fields — inferenceCredentialKind: "interactive" is not present in the pushed configuration.
Browser shows “Connected” but the app reports the sign-in failed, or Token exchange failed (HTTP 401) — The browser step succeeded, but the identity provider rejected the follow-up token request. This usually means the IdP application is registered as a confidential (Web) client, which expects a client secret. Claude is a public PKCE client and doesn’t send one. Register a public/native client instead: Native Application in Okta, or the Mobile and desktop applications platform in Entra ID. Application type generally can’t be changed after creation, so you may need to create a new one.
Google Workspace can be used as the identity provider, but in the default
id_token mode Google does not issue a fresh ID token on background refresh, so users are prompted to sign in again roughly once an hour. Setting bearerTokenType to access_token avoids this. Entra ID and Okta are not affected in either mode.anthropic_family_tier in its /v1/models response or you list them in inferenceModels (see Models). When /v1/models is unreachable or returns an error, the picker falls back to the inferenceModels list; if that list is empty, so is the picker.
The 1M context window entry does not appear in the picker. supports1m takes effect only when the entry’s name matches the model ID the picker uses. Setting it on a bare alias (for example sonnet) while discovery returns full model IDs produces no match. Set supports1m on an entry whose name is the exact ID your gateway’s /v1/models endpoint returns.