docs: OAuth for openai-compatible providers (xAI, generic gateways)
+81
@@ -176,6 +176,85 @@ Simply click the `Advanced` link and click `Go to Coyote (unsafe)` to continue t
|
|||||||

|

|
||||||

|

|
||||||
|
|
||||||
|
### xAI OAuth Note
|
||||||
|
|
||||||
|
xAI OAuth requires a **SuperGrok** or **X Premium+** subscription. Coyote ships with the required OAuth endpoints and
|
||||||
|
client ID bundled in `models.yaml`, so you can enable OAuth by just adding `auth: oauth` to your xAI client entry — no
|
||||||
|
additional endpoints or app registration needed.
|
||||||
|
|
||||||
|
When authenticating, Coyote starts a localhost server on port **56121** to capture the OAuth callback automatically.
|
||||||
|
This port matches what xAI's OAuth app expects and cannot be changed. Make sure port 56121 is available when you run
|
||||||
|
`--authenticate`/`.authenticate`.
|
||||||
|
|
||||||
|
If the authorization succeeds but the token exchange returns 403, that indicates your account does not have a valid
|
||||||
|
SuperGrok / X Premium+ subscription — not a Coyote configuration error.
|
||||||
|
|
||||||
|
Example configuration:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
clients:
|
||||||
|
- type: openai-compatible
|
||||||
|
name: xai
|
||||||
|
api_base: https://api.x.ai/v1
|
||||||
|
auth: oauth
|
||||||
|
```
|
||||||
|
|
||||||
|
### OAuth for OpenAI-Compatible Providers
|
||||||
|
|
||||||
|
For any provider that speaks the OpenAI API shape, you can enable OAuth on an `openai-compatible` client. Coyote resolves
|
||||||
|
OAuth configuration in two layers:
|
||||||
|
|
||||||
|
1. **Bundled defaults** in `models.yaml` under `provider: <name>` (Coyote ships defaults for providers like xAI).
|
||||||
|
2. **Inline overrides** in your `config.yaml` under `clients[i].oauth` — you can either supply the whole block (for
|
||||||
|
providers not shipped with Coyote) or override individual fields (e.g. to point at a corporate token endpoint).
|
||||||
|
|
||||||
|
For each optional field, the user's `config.yaml` value wins over the `models.yaml` default. If neither source provides
|
||||||
|
a required field (`client_id`, `token_url`), Coyote will bail with a clear error when you attempt to authenticate.
|
||||||
|
|
||||||
|
**Example — inline OAuth for a private gateway:**
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
clients:
|
||||||
|
- type: openai-compatible
|
||||||
|
name: acme-gateway
|
||||||
|
api_base: https://gateway.acme.com/v1
|
||||||
|
auth: oauth
|
||||||
|
oauth:
|
||||||
|
client_id: '{{ACME_CLIENT_ID}}'
|
||||||
|
client_secret: '{{ACME_CLIENT_SECRET}}'
|
||||||
|
token_url: https://auth.acme.com/oauth/token
|
||||||
|
scopes: [openai.chat]
|
||||||
|
flow: client_credentials
|
||||||
|
```
|
||||||
|
|
||||||
|
### Providers with Bundled OAuth Defaults
|
||||||
|
|
||||||
|
Coyote ships OAuth defaults for the following providers, so you only need `auth: oauth` in your config:
|
||||||
|
|
||||||
|
* **xAI** — SuperGrok / X Premium+ subscribers
|
||||||
|
|
||||||
|
To bundle defaults for additional providers locally, edit your `models.yaml` (see [Local Models Override](#local-models-override))
|
||||||
|
and add an `oauth:` block under the provider entry.
|
||||||
|
|
||||||
|
### client_credentials Flow
|
||||||
|
|
||||||
|
For headless machine-to-machine (M2M) authentication — no browser, no user interaction — set `flow: client_credentials`
|
||||||
|
in your `oauth` block. Coyote will POST directly to the token endpoint with `client_id` and `client_secret` and cache
|
||||||
|
the returned access token.
|
||||||
|
|
||||||
|
RFC 6749 §4.4.3 forbids refresh tokens for the client credentials flow, so when the token expires Coyote silently
|
||||||
|
re-runs the client credentials exchange (still no browser). This makes it suitable for CI, servers, and other
|
||||||
|
non-interactive environments.
|
||||||
|
|
||||||
|
### Known Limitation: Token Namespacing
|
||||||
|
|
||||||
|
OAuth tokens are stored on disk at `~/.cache/coyote/oauth/{client_name}_oauth_tokens.json`, keyed by the client's `name`
|
||||||
|
field only (not by provider type). Two clients with the same `name` — even if they use different provider types — will
|
||||||
|
overwrite each other's tokens.
|
||||||
|
|
||||||
|
To prevent accidental collisions, Coyote now rejects configuration files with duplicate `name` values across all
|
||||||
|
`clients[]` entries at load time. Fixing the underlying single-namespace layout is future work.
|
||||||
|
|
||||||
**Step 3: Use normally**
|
**Step 3: Use normally**
|
||||||
|
|
||||||
Once authenticated, the client works like any other. Coyote uses the stored OAuth tokens automatically:
|
Once authenticated, the client works like any other. Coyote uses the stored OAuth tokens automatically:
|
||||||
@@ -191,6 +270,8 @@ coyote -m my-claude-oauth:claude-sonnet-4-20250514 "Hello!"
|
|||||||
* Claude
|
* Claude
|
||||||
* Gemini
|
* Gemini
|
||||||
* OpenAI (requires ChatGPT Plus or Pro subscription)
|
* OpenAI (requires ChatGPT Plus or Pro subscription)
|
||||||
|
* xAI (requires SuperGrok or X Premium+ subscription; configured via `type: openai-compatible`)
|
||||||
|
* Any OpenAI-compatible provider via an inline `oauth:` block (see [OAuth for OpenAI-Compatible Providers](#oauth-for-openai-compatible-providers))
|
||||||
|
|
||||||
# Extra Settings
|
# Extra Settings
|
||||||
Coyote also lets you customize some extra settings for interacting with APIs:
|
Coyote also lets you customize some extra settings for interacting with APIs:
|
||||||
|
|||||||
Reference in New Issue
Block a user