The OAuth dance
Standard Google OAuth: an access token is good for ~1 hour. After that you POST the refresh token to oauth2.googleapis.com/token with grant_type=refresh_token, and you get a new access token back. Persist the new expiry; rotate before it dies.
loadCodeAssist — the pre-flight you can't skip
Before the first generate call on the OAuth path, you must call loadCodeAssist. It returns a cloudaicompanionProject string that you have to pass in every subsequent generateContent body's project field. Skip it and you get HTTP 500 with a confusing error.
The OAuth client credentials are public
The Gemini CLI ships with hardcoded client_id and client_secret values. They're public — anyone running the CLI uses the same pair. Google treats them as identifiers, not secrets. You can use them for your own OAuth flow.