From d407eb5a6aa26d7b43482e399afff5199f975fc6 Mon Sep 17 00:00:00 2001 From: Alex Clarke Date: Tue, 21 Jul 2026 10:30:36 -0600 Subject: [PATCH] fix(oauth): send Accept: application/json in device flow requests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GitHub's device flow endpoints (and likely other RFC 8628 servers) default to responding in application/x-www-form-urlencoded unless the client asks for JSON via the Accept header. Our device auth and polling paths both call .json() on the response and were failing to decode form-urlencoded bodies with 'expected value at line 1 column 1'. Adds Accept: application/json to: - The device authorization POST in run_device_code_flow - The device_code polling POST (on the RequestBuilder returned by build_token_request) RFC 6749 ยง5.1 already specifies JSON as the token response format, so this is spec-compliant across providers. Servers that already default to JSON (Moonshot, etc.) ignore the redundant header. --- src/client/oauth.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/client/oauth.rs b/src/client/oauth.rs index 49d340d..69dabc0 100644 --- a/src/client/oauth.rs +++ b/src/client/oauth.rs @@ -390,7 +390,10 @@ async fn run_device_code_flow(provider: &dyn OAuthProvider, client_name: &str) - } let form: HashMap<&str, &str> = device_params.iter().copied().collect(); - let mut device_request = client.post(device_auth_url).form(&form); + let mut device_request = client + .post(device_auth_url) + .header("Accept", "application/json") + .form(&form); for (key, value) in provider.extra_token_headers() { device_request = device_request.header(key, value); } @@ -468,6 +471,7 @@ async fn run_device_code_flow(provider: &dyn OAuthProvider, client_name: &str) - token_params.push(("code_verifier", verifier.as_str())); } let token_response: Value = build_token_request(&client, provider, &token_params) + .header("Accept", "application/json") .send() .await? .json()