Skip to content

ApigeeLlm: Add userinfo.email scope for Apigee Gateway tokeninfo user identification #4721

@polar3130

Description

@polar3130

🔴 Required Information

Is your feature request related to a specific problem?

When using ApigeeLlm with Service Account (SA) key authentication, the Apigee Gateway cannot identify the caller via Google's tokeninfo API (https://oauth2.googleapis.com/tokeninfo).

The tokeninfo API returns the email field only when the OAuth token includes the userinfo.email scope. Currently, ApigeeLlm.api_client delegates credential creation to genai.Client, which internally calls google.auth.default() with only the cloud-platform scope. This means:

  • ADC (gcloud auth application-default login): Works — the refresh token from the browser OAuth flow already includes userinfo.email regardless of the requested scopes.
  • Service Account key file: Fails — tokens are minted on demand with only the requested scopes, so userinfo.email is not included.

A common Apigee Gateway pattern is to call the tokeninfo API to extract the caller's email for quota management and request logging. Without the email field, this user identification fails.

Describe the Solution You'd Like

Have ApigeeLlm.api_client explicitly call google.auth.default() with both cloud-platform and userinfo.email scopes, and pass the resulting credentials to genai.Client(credentials=...).

This change is scoped to ApigeeLlm only — the base Gemini class and genai SDK are unaffected. The userinfo.email scope is needed specifically for the Apigee Gateway integration, so it belongs in the Apigee-specific connector rather than in the genai SDK.

Impact on your work

This issue blocks any production deployment that uses Service Account authentication with Apigee Gateway's tokeninfo-based user identification. Without this fix, users must apply a monkey-patch workaround (see below).

Willingness to contribute

Yes — I have a PR ready to submit.


🟡 Recommended Information

Describe Alternatives You've Considered

Application code must monkey-patch google.auth.default to inject the userinfo.email scope before initializing ApigeeLlm:

import google.auth

_original_auth_default = google.auth.default

def _patched_auth_default(scopes=None, **kwargs):
    extra_scopes = ["https://www.googleapis.com/auth/userinfo.email"]
    if scopes:
        scopes = list(scopes) + [s for s in extra_scopes if s not in scopes]
    else:
        scopes = extra_scopes
    return _original_auth_default(scopes=scopes, **kwargs)

google.auth.default = _patched_auth_default

This works but is fragile and requires every application to duplicate the same workaround.

Proposed API / Implementation

# In apigee_llm.py

import google.auth

_APIGEE_SCOPES = [
    'https://www.googleapis.com/auth/cloud-platform',
    'https://www.googleapis.com/auth/userinfo.email',
]

# In api_client property:
credentials, _ = google.auth.default(scopes=_APIGEE_SCOPES)
return Client(
    credentials=credentials,
    http_options=http_options,
    **kwargs_for_client,
)

Additional Context

  • The genai.Client constructor already accepts an optional credentials parameter, so no upstream changes are needed.
  • The userinfo.email scope is a read-only, non-sensitive scope that grants no additional access to GCP resources.

Metadata

Metadata

Assignees

No one assigned

    Labels

    auth[Component] This issue is related to authorization

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions