mirror of
https://github.com/googleapis/genai-toolbox.git
synced 2026-01-12 00:49:08 -05:00
Fix(tools/bigquery-conversational-analytics): fix authentication scope error in Cloud Run (#1381)
## Problem Fixes #1378 - BigQuery Conversational Analytics tool fails with `ACCESS_TOKEN_SCOPE_INSUFFICIENT` error in Cloud Run environments while other BigQuery tools work fine. ## Root Cause The conversational analytics tool was using `BigQueryTokenSource()` with limited `bigqueryapi.Scope`, but the Gemini Data Analytics API (`geminidataanalytics.googleapis.com`) requires broader `cloud-platform` scope. ## Solution - Replace ADC token acquisition to use `google.DefaultTokenSource` with `cloud-platform` scope - Remove dependency on limited BigQuery scope from source - Maintain compatibility with existing OAuth flow ## Testing - ✅ **Local testing confirmed**: Tool now works perfectly - ✅ **Test script**: https://github.com/johanesalxd/bq-agent-app/blob/main/setup/mcp_toolbox_ca_issue/test_detailed_error.py - ✅ **Successful response**: Returns proper schema information and conversational answers - ✅ **All BigQuery tool tests pass**: No regression in other tools - ✅ **Build successful**: No compilation errors ## Impact - **Fixes**: Cloud Run deployment authentication errors - **Maintains**: Local development functionality - **Preserves**: All existing BigQuery tool functionality --------- Co-authored-by: Huan Chen <142538604+Genesis929@users.noreply.github.com>
This commit is contained in:
@@ -188,6 +188,10 @@ func (s *Source) BigQueryTokenSource() oauth2.TokenSource {
|
||||
return s.TokenSource
|
||||
}
|
||||
|
||||
func (s *Source) BigQueryTokenSourceWithScope(ctx context.Context, scope string) (oauth2.TokenSource, error) {
|
||||
return google.DefaultTokenSource(ctx, scope)
|
||||
}
|
||||
|
||||
func (s *Source) GetMaxQueryResultRows() int {
|
||||
return s.MaxQueryResultRows
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (tools.T
|
||||
|
||||
type compatibleSource interface {
|
||||
BigQueryClient() *bigqueryapi.Client
|
||||
BigQueryTokenSource() oauth2.TokenSource
|
||||
BigQueryTokenSourceWithScope(ctx context.Context, scope string) (oauth2.TokenSource, error)
|
||||
BigQueryProject() string
|
||||
BigQueryLocation() string
|
||||
GetMaxQueryResultRows() int
|
||||
@@ -145,6 +145,17 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error)
|
||||
InputSchema: parameters.McpManifest(),
|
||||
}
|
||||
|
||||
// Get cloud-platform token source for Gemini Data Analytics API during initialization
|
||||
var bigQueryTokenSourceWithScope oauth2.TokenSource
|
||||
if !s.UseClientAuthorization() {
|
||||
ctx := context.Background()
|
||||
ts, err := s.BigQueryTokenSourceWithScope(ctx, "https://www.googleapis.com/auth/cloud-platform")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get cloud-platform token source: %w", err)
|
||||
}
|
||||
bigQueryTokenSourceWithScope = ts
|
||||
}
|
||||
|
||||
// finish tool setup
|
||||
t := Tool{
|
||||
Name: cfg.Name,
|
||||
@@ -155,7 +166,7 @@ func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error)
|
||||
AuthRequired: cfg.AuthRequired,
|
||||
Client: s.BigQueryClient(),
|
||||
UseClientOAuth: s.UseClientAuthorization(),
|
||||
TokenSource: s.BigQueryTokenSource(),
|
||||
TokenSource: bigQueryTokenSourceWithScope,
|
||||
manifest: tools.Manifest{Description: cfg.Description, Parameters: parameters.Manifest(), AuthRequired: cfg.AuthRequired},
|
||||
mcpManifest: mcpManifest,
|
||||
MaxQueryResultRows: s.GetMaxQueryResultRows(),
|
||||
@@ -197,13 +208,13 @@ func (t Tool) Invoke(ctx context.Context, params tools.ParamValues, accessToken
|
||||
return nil, fmt.Errorf("error parsing access token: %w", err)
|
||||
}
|
||||
} else {
|
||||
// Use ADC
|
||||
// Use cloud-platform token source for Gemini Data Analytics API
|
||||
if t.TokenSource == nil {
|
||||
return nil, fmt.Errorf("ADC is missing a valid token source")
|
||||
return nil, fmt.Errorf("cloud-platform token source is missing")
|
||||
}
|
||||
token, err := t.TokenSource.Token()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get token from ADC: %w", err)
|
||||
return nil, fmt.Errorf("failed to get token from cloud-platform token source: %w", err)
|
||||
}
|
||||
tokenStr = token.AccessToken
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user