Kuberwastaken/claurst · error · anyhow::Error

OAuth callback did not contain an authorization code

Error message

OAuth callback did not contain an authorization code

What it means

The OAuth callback request arrived and matched the expected path, but its query string contained no `code` parameter. This means the authorization server redirected back without granting a code — typically the user denied consent or the server reported an error (e.g. `error=access_denied`) in the query string instead.

Solutions

  1. Retry the authentication flow and approve the consent prompt in the browser
  2. Check the callback URL query string for an `error` parameter from the authorization server
  3. Verify the MCP server's OAuth client is correctly registered with the authorization server
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at src-rust/crates/mcp/src/oauth.rs:299 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of Kuberwastaken/claurst@b0637c97ec (2026-09-10). Data as JSON: /api/errors/99d97b231447bf55. Report an issue: GitHub.

Appendix: source

Thrown at src-rust/crates/mcp/src/oauth.rs:299

            parsed_url.path()
        );
    }

    if let Some(expected_state) = expected_state {
        let received_state = parsed_url
            .query_pairs()
            .find(|(key, _)| key == "state")
            .map(|(_, value)| value.to_string());
        if received_state.as_deref() != Some(expected_state) {
            anyhow::bail!("OAuth state mismatch — possible CSRF attack");
        }
    }

    parsed_url
        .query_pairs()
        .find(|(key, _)| key == "code")
        .map(|(_, value)| value.to_string())
        .ok_or_else(|| anyhow::anyhow!("OAuth callback did not contain an authorization code"))
}

pub async fn run_mcp_auth_session(session: McpAuthSession) -> anyhow::Result<McpAuthResult> {
    let (listener, host, callback_path) = bind_callback_listener(&session.redirect_uri).await?;
    open::that(&session.auth_url)
        .map_err(|e| anyhow::anyhow!("Failed to open browser for OAuth: {}", e))?;

    let code = wait_for_authorization_code(listener, &host, &callback_path, None).await?;
    let mut token = exchange_code(
        &session.metadata.token_endpoint,
        &code,
        &session.verifier,
        &session.redirect_uri,
    )
    .await?;
    token.server_name = session.server_name.clone();
    store_mcp_token(&token).map_err(|e| {
        anyhow::anyhow!(

View on GitHub (pinned to b0637c97ec)