-
Notifications
You must be signed in to change notification settings - Fork 3k
Description
🔴 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 includesuserinfo.emailregardless of the requested scopes. - Service Account key file: Fails — tokens are minted on demand with only the requested scopes, so
userinfo.emailis 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_defaultThis 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.Clientconstructor already accepts an optionalcredentialsparameter, so no upstream changes are needed. - The
userinfo.emailscope is a read-only, non-sensitive scope that grants no additional access to GCP resources.