docs: RFC 8707 resource field + extra_token_params for openai-compatible OAuth (all three flows, merge/precedence notes)

Dark-Alex-17 committed 2026-09-14 18:31:48 -06:00
1 parent b87cafd75d
commit 338da31a43
1 file changed
+19
+19
@@ -288,6 +288,10 @@ copy/paste), but requires that the provider's OAuth app allows a loopback redire
**Optional fields:**
- `scopes: [scope1, scope2]`: space-joined into the `scope=` query param.
- `extra_authorize_params: { key: value }`: extra query params on the authorize URL (e.g. xAI needs `plan: generic`).
- `extra_token_params: { key: value }`: extra form params on every token request (code exchange and refresh); the
token-side mirror of `extra_authorize_params`.
- `resource: <uri>`: RFC 8707 resource indicator. Sent as `resource=` on the authorize URL and on every token
request (code exchange and refresh). Use this when your provider scopes tokens to a specific API/resource server.
- `echo_pkce_in_token_exchange: true`: some providers (like xAI) require re-sending `code_challenge` on token exchange.
- `include_state_in_token_exchange: false`: some providers reject `state` on the token endpoint (default `true`).
- `token_request_format: form_url_encoded`: some providers require form-encoded token bodies (default is
@@ -359,6 +363,10 @@ are supported.
- `scopes: [scope1, scope2]`
- `use_pkce_in_device_flow: true`: some providers (like MiniMax) require PKCE with device flow. Coyote generates a
fresh `code_verifier` + `code_challenge` (S256) on each authentication.
- `extra_token_params: { key: value }`: extra form params on every token request (device polling and refresh).
- `resource: <uri>`: RFC 8707 resource indicator. Sent as `resource=` on the device-authorization request and on
every token request (device polling and refresh). Use this when your provider scopes tokens to a specific
API/resource server.
- `token_request_format: form_url_encoded`: usually needed for device flow (default for openai-compatible).
- `extra_token_headers: { key: value }`: custom headers applied to both device and token endpoints.
- `client_secret`: rare but supported.
@@ -375,6 +383,7 @@ clients:
device_authorization_url: https://auth.example.com/oauth/device_authorization
token_url: https://auth.example.com/oauth/token
flow: device_code
resource: https://api.example.com/
scopes: [openid, profile]
```
@@ -395,6 +404,8 @@ For headless machine-to-machine authentication. No user, no browser. Coyote POST
**Optional fields:**
- `scopes: [scope1, scope2]`
- `token_request_format`
- `extra_token_params: { key: value }`: extra form params on the token request (and each silent re-exchange).
- `resource: <uri>`: RFC 8707 resource indicator, sent as `resource=` on the token request.
- `extra_token_headers: { key: value }`
**Example:**
@@ -439,6 +450,14 @@ which field is missing.
You can override individual fields. For example, if the bundled default has the wrong token URL for your corporate
gateway, just set `oauth.token_url` inline and the rest of the bundled defaults still apply.
Two special cases:
- **Map fields merge per-key** rather than being replaced wholesale: `extra_authorize_params`, `extra_token_params`,
and `extra_token_headers` from `config.yaml` are merged into the bundled defaults, with your keys winning on conflict.
- **A `resource` entry inside `extra_authorize_params` / `extra_token_params` wins over the first-class `resource`
field** on its respective request surface. This keeps configs that predate the `resource` field (which passed it via
the extra-params maps) working without sending duplicate or conflicting `resource=` values.
### 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`