Skip to content

[google-vertex] provider rejects service_account ADC; only authorized_user accepted #79837

@jared-rebel

Description

@jared-rebel

Feature Request

Please add service_account ADC support to the google-vertex provider, in addition to the existing authorized_user flow.


Problem Statement

The google-vertex provider's ADC layer silently rejects standard GCP service-account JSON key files. In dist/vertex-adc-CXnQBcxJ.js (source: extensions/google/vertex-adc.ts), the credential-reader bails out immediately if the credentials file is not authorized_user:

// extensions/google/vertex-adc.ts (line ~38 in dist)
if (record.type !== "authorized_user") return;

hasGoogleVertexAuthorizedUserAdcSync also hard-codes the same check:

parsed.type === "authorized_user"

So if GOOGLE_APPLICATION_CREDENTIALS (or ~/.config/gcloud/application_default_credentials.json) points to a service-account JSON key, OpenClaw silently falls through to "no credentials" and the request fails.


Why This Matters

Google's ADC documentation defines two standard credential types that ADC consumers are expected to handle:

Type Source
authorized_user gcloud auth application-default login
service_account Downloaded SA JSON key, set via GOOGLE_APPLICATION_CREDENTIALS

For headless/server-side deployments (VMs, containers, systemd services like OpenClaw), service-account JSON is the standard GCP practice. authorized_user requires an interactive browser flow and binds auth to a human's Google session — it's unsuitable for:

  • Credential durability (user sessions expire)
  • Service-account isolation (least-privilege per workload)
  • CI/CD and server environments

Repro

  1. Create a GCP service account with roles/aiplatform.user
  2. Download the SA JSON key and set GOOGLE_APPLICATION_CREDENTIALS=/path/to/key.json
  3. Configure OpenClaw with google-vertex provider (ADC path)
  4. Attempt any google-vertex model call
  5. Observed: Call fails — OpenClaw does not pick up SA credentials; falls through to "No API key found" or similar
  6. Verified independently: Direct curl with gcloud auth application-default print-access-token (which does support SA JSON) returns valid responses against us-central1-aiplatform.googleapis.com Vertex endpoints for gemini-2.5-flash and gemini-2.5-pro

We provisioned vertex-ai-runtime@alberto-openclaw.iam.gserviceaccount.com with roles/aiplatform.user and confirmed SA key auth works end-to-end via curl — just can't plug it into OpenClaw.


Expected Behavior

The provider should accept both ADC credential types, mirroring standard Google ADC semantics:

  • type === "authorized_user" → existing refresh-token OAuth flow (unchanged)
  • type === "service_account" → use google-auth-library's GoogleAuth (or equivalent) with keyFile and scopes ["https://www.googleapis.com/auth/cloud-platform"] to mint an access token, then attach it as Authorization: Bearer <token>

Proposed Fix Sketch

In extensions/google/vertex-adc.ts, add a parallel service_account path:

// After reading the credentials file:
if (record.type === "service_account") {
  // Use google-auth-library (already a transitive dep via @google/genai)
  const { GoogleAuth } = await import("google-auth-library");
  const auth = new GoogleAuth({
    keyFile: credentialsPath,
    scopes: ["https://www.googleapis.com/auth/cloud-platform"],
  });
  const client = await auth.getClient();
  const tokenResponse = await client.getAccessToken();
  return { token: tokenResponse.token!, expiresAtMs: Date.now() + 3600_000 };
}

The rest of the Vertex transport request-signing logic (constructing the Vertex AI endpoint URL, attaching Authorization: Bearer) should not need to change — only the credential-resolution step.

Note: google-auth-library is already a transitive dependency of @google/genai so no new package dependency is needed.


Additional Notes


Environment

  • OpenClaw version: 2026.5.x (installed via npm global, Linux x64)
  • GCP project: server-side Linux deployment
  • Auth target: us-central1-aiplatform.googleapis.com
  • Models tested: gemini-2.5-flash, gemini-2.5-pro

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions