Skip to content

ask_data_insights fails authentication when using per-user OAuth (use_client_oauth: true) #3057

@flaviojdz

Description

@flaviojdz

Prerequisites

  • I've searched the current open issues
  • I've updated to the latest version of Toolbox

Toolbox version

toolbox version 1.0.0+dev.darwin.arm64

Environment

1. OS type and version:

Darwin Flavios-MacBook-Pro.local 24.6.0 Darwin Kernel Version 24.6.0: Wed Mar 25 21:38:31 PDT 2026; root:xnu-11417.140.69.709.8~3/RELEASE_ARM64_T6000 arm64

2. How are you running Toolbox:

Compiled from source (go build -o toolbox)

3. Version:

v1.0.0 (commit da6f5f8a15400d8b14e54c01a23f51601a584b7f )

Client

  1. Client: toolbox-core
  2. Version: toolbox-core>=0.2.0
  3. Example: If possible, please include your code of configuration:
from toolbox_core import ToolboxClient

async def bearer_header() -> str:
    token = get_user_token_fn()
    if hasattr(token, "__await__"):
        token = await token
    return f"Bearer {token}"

client = ToolboxClient(
    "http://localhost:5001",
    client_headers={"Authorization": bearer_header},
)
tools = await client.load_toolset()

Expected Behavior

The ask_data_insights tool should authenticate successfully with the Gemini Data Analytics API using the user's Looker OAuth token, the same way get_models and get_explores do.

Current Behavior

The GDA API rejects the Looker credentials in the payload with an authentication error. get_models and get_explores work correctly with the same token and the same source configuration.

Steps to reproduce?

  1. Configure tools.yaml with use_client_oauth: true on the Looker source
  2. Authenticate a user via Looker OAuth (PKCE) and inject their token via the Authorization header
  3. Call get_models — succeeds
  4. Call get_explores — succeeds
  5. Call ask_data_insights — fails with authentication error from the GDA API

Additional Details

Root cause

The accessToken passed to Invoke() contains the full HTTP header value including the "Bearer " prefix (e.g., "Bearer abc123").

  • get_models/get_explores pass this value to GetLookerSDK(), which sets it as an HTTP Authorization header — the prefix is expected there and works correctly.
  • ask_data_insights embeds the full "Bearer abc123" string directly into the JSON payload's access_token field sent to the GDA API, which expects only the raw token value "abc123".

File: internal/tools/looker/lookerconversationalanalytics/lookerconversationalanalytics.go

// Current (broken):
oauth_creds.Token = TokenBased{AccessToken: string(accessToken)}
// Produces: {"access_token": "Bearer abc123"}

// Fix:
rawToken, err := accessToken.ParseBearerToken()
oauth_creds.Token = TokenBased{AccessToken: rawToken}
// Produces: {"access_token": "abc123"}

The ParseBearerToken() method already exists on the AccessToken type for this purpose but is not called in the conversational analytics tool.

Metadata

Metadata

Labels

priority: p2Moderately-important priority. Fix may not be included in next release.type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.

Type

No fields configured for Bug.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions