[GH-ISSUE #20] [Feature] Add automatic OAuth token refresh support for runtime /v1/token flow #16

Closed
opened 2026-02-27 15:37:57 +03:00 by kerem · 2 comments
Owner

Originally created by @DarKWinGTM on GitHub (Feb 19, 2026).
Original GitHub issue: https://github.com/NikkeTryHard/zerogravity/issues/20

Summary

Please add first-class auto refresh token support when users provide token at runtime via /v1/token (or env/file startup modes), so long-running sessions do not break when access token expires.


Background

Current behavior (documented) indicates:

  • Bare ya29... access token expires quickly
  • Without refresh token source, users must manually update token

In practical usage this causes interruptions and manual ops overhead for long-running proxy sessions.


Problem

When only access token is configured at runtime:

  1. Requests work initially
  2. Token expires
  3. Upstream calls fail (auth/quota-related errors)
  4. Operator must manually call /v1/token again

This is fragile for automation and daemon use.


Requested capability

Implement an automatic refresh strategy for runtime token mode.

Desired behavior

  • Detect token expiry/auth failure proactively (or from expiry metadata)
  • Refresh token automatically before/when needed
  • Retry original request after successful refresh
  • Keep refresh state in memory (and optionally persisted securely)
  • Expose health/status for current token lifecycle

Suggested API/UX additions

  1. POST /v1/token accepts structured payload (optional extension):
    • access_token
    • refresh_token (optional)
    • expires_at / expires_in (optional)
  2. GET /v1/token/status (or include in /v1/health//v1/quota) to report:
    • token source (env/file/runtime)
    • access token expiry
    • refresh availability
    • last refresh attempt/result
  3. Automatic refresh + bounded retry policy for in-flight request

Acceptance criteria

  • Long-running session survives access-token expiration without manual /v1/token update
  • Refresh attempts are observable in logs and status endpoint
  • Failure modes are explicit (refresh unavailable/invalid, backoff, terminal failure)
  • Existing simple token flow remains backward compatible

Why this matters

  • Improves reliability for daemon/container deployments
  • Reduces operational burden and manual intervention
  • Better fit for Anthropic/OpenAI-compatible clients expecting stable long-lived endpoint behavior
Originally created by @DarKWinGTM on GitHub (Feb 19, 2026). Original GitHub issue: https://github.com/NikkeTryHard/zerogravity/issues/20 ## Summary Please add first-class **auto refresh token** support when users provide token at runtime via `/v1/token` (or env/file startup modes), so long-running sessions do not break when access token expires. --- ## Background Current behavior (documented) indicates: - Bare `ya29...` access token expires quickly - Without refresh token source, users must manually update token In practical usage this causes interruptions and manual ops overhead for long-running proxy sessions. --- ## Problem When only access token is configured at runtime: 1. Requests work initially 2. Token expires 3. Upstream calls fail (auth/quota-related errors) 4. Operator must manually call `/v1/token` again This is fragile for automation and daemon use. --- ## Requested capability Implement an automatic refresh strategy for runtime token mode. ### Desired behavior - Detect token expiry/auth failure proactively (or from expiry metadata) - Refresh token automatically before/when needed - Retry original request after successful refresh - Keep refresh state in memory (and optionally persisted securely) - Expose health/status for current token lifecycle --- ## Suggested API/UX additions 1. `POST /v1/token` accepts structured payload (optional extension): - `access_token` - `refresh_token` (optional) - `expires_at` / `expires_in` (optional) 2. `GET /v1/token/status` (or include in `/v1/health`/`/v1/quota`) to report: - token source (env/file/runtime) - access token expiry - refresh availability - last refresh attempt/result 3. Automatic refresh + bounded retry policy for in-flight request --- ## Acceptance criteria - Long-running session survives access-token expiration without manual `/v1/token` update - Refresh attempts are observable in logs and status endpoint - Failure modes are explicit (refresh unavailable/invalid, backoff, terminal failure) - Existing simple token flow remains backward compatible --- ## Why this matters - Improves reliability for daemon/container deployments - Reduces operational burden and manual intervention - Better fit for Anthropic/OpenAI-compatible clients expecting stable long-lived endpoint behavior
kerem closed this issue 2026-02-27 15:37:57 +03:00
Author
Owner

@NikkeTryHard commented on GitHub (Feb 19, 2026):

hey, thanks for the detailed writeup. we've been looking into this.

so the thing is — when Antigravity is installed locally, the proxy already reads the full OAuth Topic proto (access_token + refresh_token + expiry) from state.vscdb and injects it into the LS. the LS has Google's own refresh logic built-in so tokens stay alive forever. oauth2.googleapis.com is explicitly passthrough'd in the MITM layer so refresh traffic is never touched.

the real gap is exactly what you described: bare ya29.xxx tokens via env/file//v1/token in docker/remote setups where there's no state.vscdb. those die after ~60min.

we're not going to have the proxy hit oauth2 directly though — that's a fingerprint risk (the real webview never refreshes from an arbitrary IP like that). instead we're exploring injecting the refresh_token into the LS's internal state through the stub extension server so the LS does its own refresh natively. that way the refresh traffic looks byte-identical to the real app.

do you have any insights on how Google's OAuth flow works from the LS side? specifically how the extension server feeds the refresh_token to the LS's internal OAuth state machine? if you've poked at the LS binary at all that would be super helpful for this.

in the meantime, a workaround that already works today: Backend::oauth_token() re-reads the token file on every request, so if you have a cron or systemd timer writing fresh tokens to ~/.config/zerogravity/token, it'll pick them up automatically without any code changes.

<!-- gh-comment-id:3926020122 --> @NikkeTryHard commented on GitHub (Feb 19, 2026): hey, thanks for the detailed writeup. we've been looking into this. so the thing is — when Antigravity is installed locally, the proxy already reads the full OAuth Topic proto (access_token + refresh_token + expiry) from state.vscdb and injects it into the LS. the LS has Google's own refresh logic built-in so tokens stay alive forever. oauth2.googleapis.com is explicitly passthrough'd in the MITM layer so refresh traffic is never touched. the real gap is exactly what you described: bare `ya29.xxx` tokens via env/file/`/v1/token` in docker/remote setups where there's no state.vscdb. those die after ~60min. we're not going to have the proxy hit oauth2 directly though — that's a fingerprint risk (the real webview never refreshes from an arbitrary IP like that). instead we're exploring injecting the refresh_token into the LS's internal state through the stub extension server so the LS does its own refresh natively. that way the refresh traffic looks byte-identical to the real app. do you have any insights on how Google's OAuth flow works from the LS side? specifically how the extension server feeds the refresh_token to the LS's internal OAuth state machine? if you've poked at the LS binary at all that would be super helpful for this. in the meantime, a workaround that already works today: `Backend::oauth_token()` re-reads the token file on every request, so if you have a cron or systemd timer writing fresh tokens to `~/.config/zerogravity/token`, it'll pick them up automatically without any code changes.
Author
Owner

@DarKWinGTM commented on GitHub (Feb 20, 2026):

in the meantime, a workaround that already works today: Backend::oauth_token() re-reads the token file on every request, so if you have a cron or systemd timer writing fresh tokens to ~/.config/zerogravity/token, it'll pick them up automatically without any code changes.

Agree this that is safe way to prevent to inject any action Antigravity do with token and refresh.

<!-- gh-comment-id:3930883716 --> @DarKWinGTM commented on GitHub (Feb 20, 2026): in the meantime, a workaround that already works today: Backend::oauth_token() re-reads the token file on every request, so if you have a cron or systemd timer writing fresh tokens to ~/.config/zerogravity/token, it'll pick them up automatically without any code changes. Agree this that is safe way to prevent to inject any action Antigravity do with token and refresh.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/zerogravity#16
No description provided.