Skip to content

Native Google Cloud auth for IAM-gated A2A agents (Cloud Run / OIDC identity tokens) #81

Description

@alDuncanson

Summary

Handler currently can't authenticate to A2A agents hosted on Google Cloud Run (or anything behind Google IAM / an identity-aware proxy) — an increasingly common enterprise deployment for A2A agents. A private Cloud Run service requires a short-lived OIDC identity token whose aud (audience) equals the service URL, refreshed roughly hourly. None of the current auth methods can produce that.

Why the current methods don't fit

  • bearer (env / value) — a static string. You'd have to paste the output of gcloud auth print-identity-token --audiences=<service-url> into an env var and manually refresh it every ~60 min. resolve_server_credentials() reads it once via os.getenv(...); there's no refresh or credential-helper hook.
  • oauth2 (client credentials) — sends only the scope parameter, but Google's OIDC token endpoint needs an audience parameter to mint a Cloud-Run-scoped ID token, so the resulting token isn't accepted by Cloud Run.
  • mtls / api_key — don't map to Cloud Run IAM (which is OIDC-bearer based).

Proposed enhancement

Any one of these unblocks it; (1) is the most general primitive, (3) is the most turnkey for GCP users:

  1. Dynamic bearer via command / credential helper — let a bearer token be produced by running a command, re-run before expiry:

    [servers.remy.auth]
    type = "bearer"
    command = "gcloud auth print-identity-token --audiences=https://remy-xxxx.us-central1.run.app"
    refresh_seconds = 3000

    Provider-agnostic — also covers AWS/Azure/any token source.

  2. audience field for oauth2 — add an optional audience param so the client-credentials flow can target Google's OIDC token endpoint (and RFC 8693 token-exchange style flows), not just scope.

  3. Native Google identity-token auth — an auth type (e.g. type = "google_id_token" with an audience) that uses Application Default Credentials / service-account impersonation via google-auth to mint an audience-scoped OIDC token and auto-refresh it. Near zero-config for anyone with gcloud/ADC configured.

Why it matters

Enterprise A2A agents are commonly deployed on Cloud Run / GKE behind IAM — the A2A spec itself recommends fronting servers with an identity-aware proxy / API gateway. Without native support, pointing Handler at an internal company agent means a manual hourly token dance, which is a real adoption blocker for team/enterprise use.

Current workaround

gcloud run services proxy <service> --port 8080 opens an authenticated localhost tunnel that handles the OIDC token; point Handler at --url http://localhost:8080 with no auth config. Works for interactive/local use, but requires the tunnel and doesn't cover non-interactive or remote Handler deployments.

Relevant code

  • src/a2a_handler/auth.py — oauth2 sends scope, not audience
  • src/a2a_handler/servers.pyresolve_server_credentials() reads a static bearer from env; ServerAuthConfig fields

Context: hit while wiring Handler to an internal ADK agent on Cloud Run (backed by Vertex AI Memory Bank). Leaning toward implementing (1) as the general primitive plus (3) for GCP ergonomics.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions