{"record":{"id":"268376765e2f8535","repo":"Kuberwastaken/claurst","slug":"oauth-callback-path-mismatch-expected-got","errorCode":null,"errorMessage":"OAuth callback path mismatch: expected '{}', got '{}'","messagePattern":"OAuth callback path mismatch: expected '(.+?)', got '(.+?)'","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-rust/crates/mcp/src/oauth.rs","lineNumber":278,"sourceCode":"            .await\n            .map_err(|e| anyhow::anyhow!(\"Failed to read OAuth callback headers: {}\", e))?;\n        if header.trim().is_empty() {\n            break;\n        }\n    }\n\n    let path = request_line.split_whitespace().nth(1).unwrap_or(\"\");\n    let parsed_url = url::Url::parse(&format!(\"http://{}{}\", host, path))\n        .map_err(|e| anyhow::anyhow!(\"Failed to parse OAuth callback URL '{}': {}\", path, e))?;\n\n    let response = \"HTTP/1.1 200 OK\\r\\nContent-Type: text/plain; charset=utf-8\\r\\nConnection: close\\r\\n\\r\\nMCP OAuth authentication finished. You can close this tab.\\r\\n\";\n    writer\n        .write_all(response.as_bytes())\n        .await\n        .map_err(|e| anyhow::anyhow!(\"Failed to write OAuth callback response: {}\", e))?;\n\n    if parsed_url.path() != callback_path {\n        anyhow::bail!(\n            \"OAuth callback path mismatch: expected '{}', got '{}'\",\n            callback_path,\n            parsed_url.path()\n        );\n    }\n\n    if let Some(expected_state) = expected_state {\n        let received_state = parsed_url\n            .query_pairs()\n            .find(|(key, _)| key == \"state\")\n            .map(|(_, value)| value.to_string());\n        if received_state.as_deref() != Some(expected_state) {\n            anyhow::bail!(\"OAuth state mismatch — possible CSRF attack\");\n        }\n    }\n\n    parsed_url\n        .query_pairs()","sourceCodeStart":260,"sourceCodeEnd":296,"githubUrl":"https://github.com/Kuberwastaken/claurst/blob/b0637c97ec34144387cbf2f74f65df6d16a6cef1/src-rust/crates/mcp/src/oauth.rs#L260-L296","documentation":"During OAuth authorization-code flow, the library spins up a local callback server and waits for the identity provider to redirect to it. After writing the response page, it validates that the incoming request path equals the expected callback path; a mismatch means the request did not come from the expected redirect and is rejected.","triggerScenarios":"wait_for_authorization_code (invoked by run_mcp_auth_session) receives an HTTP request on the local callback port whose path differs from the registered callback_path.","commonSituations":"User or another app visited the callback URL directly; a port previously used by another tool now receives stray requests; the OAuth client's registered redirect URI path was changed server-side; browser extension or health-check probe hits the local server.","solutions":["Retry the auth flow and complete the browser login without editing the URL","Ensure the redirect_uri registered with the OAuth provider matches the local callback path exactly","Check that no other process is bound to the same callback port and sending requests","Re-run the auth session so a fresh callback path/port is bound"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match run_mcp_auth_session(server).await {\n    Err(e) if e.to_string().contains(\"callback path mismatch\") => {\n        // restart flow; warn user not to touch the callback URL and check the port is free\n    }\n    other => other?,\n}","preventionTips":["Complete the browser OAuth step promptly and do not modify the redirect URL","Ensure the redirect_uri registered with the provider matches the local callback path","Avoid letting other tools bind the same local callback port"],"tags":["oauth","csrf","callback","security"],"backgroundTag":"unexpected-http-status","analyzedSha":"b0637c97ec34144387cbf2f74f65df6d16a6cef1","analyzedAt":"2026-09-10T00:24:58.650Z","contentChangedAt":"2026-09-10T00:24:58.650Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}