diff --git a/Clients.md b/Clients.md index aa902b3..380d77c 100644 --- a/Clients.md +++ b/Clients.md @@ -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: `: 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: `: 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: `: 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`