feat(ai): xAI subscription OAuth login (SuperGrok / X Premium) - #1328
feat(ai): xAI subscription OAuth login (SuperGrok / X Premium)#1328MingTeer wants to merge 5 commits into
Conversation
Device-code OAuth for SuperGrok / X Premium alongside XAI_API_KEY, with https-validated verification links (prefilled when the server provides verification_uri_complete), token refresh 5 minutes before expiry, and interval-0 tolerance. When a subscription credential is active, grok-4.5 and grok-4.6 route through the OpenAI Responses API; API key credentials and other models keep using OpenAI Completions unchanged. Ported from pi-mono 5220aba61 (#6651), a01baaaea (#6734), and the xAI parts of fed6009cc, adapted to this repo's OAuth provider interface.
Follow the upstream pruning strategy: drop grok-4.20 variants and grok-code-fast-1, and stop hand-adding models missing from models.dev. grok-4.6 is listed on models.dev and will enter the generated catalog on the next regeneration.
The footer stays empty by default; it now shows a single muted label when the current model runs on a known subscription (OAuth credential from a provider marked isSubscription: anthropic, github-copilot, openai-codex, xai). Ported from pi-mono b0bd0ff9d.
xAI now lists grok-4.3, grok-4.5, grok-4.6, and grok-build-0.1. Also refreshes other providers from models.dev. Adjusts the routing test to tolerate grok-4.6 already present in the catalog.
jonaowen
left a comment
There was a problem hiding this comment.
This is not safe to merge yet. I found five concrete credential/routing and device-flow blockers at exact head 7abadda7608fdb2d80767df90443a9d1fb6dc0b2:
-
Runtime routing follows stored OAuth rather than the credential actually used. Model construction applies the OAuth
modifyModelsview when auth storage contains xAI OAuth, but a runtime--api-keyoverride takes precedence only later. Stored OAuth plus--api-keytherefore still filters xAI models, changes grok-4.5/4.6 to/responses, and can display the subscription footer even though the request uses an API key. Please bind model shaping and UI labeling to the effective request credential. Add an integration test with stored xAI OAuth plus--model xai/grok-4.6 --api-key ...; it must remainopenai-completions, use/chat/completions, and show no subscription label. Cover stale OAuth plus an effective non-OAuth fallback too. -
xaiOAuthProvider.modifyModels()spreads the incoming model and preserves itsbaseUrlwhile upgrading the credential to the broader subscription bearer. A pre-existing xAI custom model/proxy URL can therefore receive the subscription access token after login. Subscription routing must pin or strictly validate the officialhttps://api.x.ai/v1origin. Add a test with an eligible xAI model whose inputbaseUrlishttps://attacker.invalid/v1and prove the OAuth token can only target the official/responsesendpoint (or the model is rejected). -
The stated malicious-response defense for browser URLs only checks
https:. Bothverification_uriandverification_uri_completeaccept arbitrary HTTPS origins, so a response can send the user/code to a phishing origin. Pin an explicit allowed xAI origin set and test that a legitimate base URI plus a cross-origin complete URI is rejected beforeonAuth, as is a cross-origin base URI. -
Device expiry does not bound an in-flight token poll. The deadline is checked before/after
options.poll(), but thefetchreceives only the user cancellation signal. A stalled request can therefore keep login alive indefinitely beyondexpires_in. Combine cancellation with a deadline abort for each poll (and use finite request limits for initial device authorization/refresh), then fake-timer test a 2-second code with a fetch that settles only on abort: it must reject at expiry and the fetch signal must be aborted. -
slow_downcan reduce the current interval: a positive serverintervalreplaces the accumulated client interval. For example, 5s ->slow_downwithout interval gives 10s, thenslow_down {interval:1}drops to 1s, contrary to RFC 8628's cumulative +5s requirement. Use at leastmax(current + 5s, server minimum)and test that sequence; the next poll must be no earlier than 15 seconds later.
Summary
Port of pi-mono's xAI subscription OAuth (5220aba61 #6651, a01baaaea #6734, b0bd0ff9d, xAI parts of fed6009cc), adapted to this repo's structure (utils/oauth, runtime model routing via
modifyModels)./login) alongsideXAI_API_KEY: https-validated verification links (prefilled user code whenverification_uri_completeis provided), token refresh 5 minutes before expiry, RFC 8628 interval-0 tolerance, clean cancellation.isSubscription).Testing
test/xai-oauth.test.ts(15 tests) andtest/xai-responses.test.ts(5 tests), mocked fetch, no network: device-code request shape, poll pending/slow_down/success/timeout/cancel, refresh incl. non-rotated refresh token, https rejection, prefill preference, interval-0 fallback; routing matrix and/responsesrequest shape.npm run checkclean (biome, tsgo, installer, browser-smoke)./loginbrowser authorization and grok-4.6 conversation.Note
Add xAI subscription OAuth login (SuperGrok / X Premium) via device-code flow
xaiOAuthProviderin xai.ts implementing the full OAuth device-code flow: device authorization request, polling for tokens, refresh, and model shaping restricted togrok-4.5andgrok-4.6.isSubscriptionflag to theOAuthProviderInterfaceand marks xAI, Anthropic, GitHub Copilot, and OpenAI Codex providers accordingly; the interactive TUI footer displays a subscription label when the active model uses a subscription provider.reasoning.encrypted_contentin theincludefield for reasoning-capable xAI models.grok-4.20-0309-reasoningtogrok-4.6and removesgrok-code-fast-1andgrok-4.20variants from the generated model catalog.grok-4.5/grok-4.6exclusively through/responseswith a different auth header.Macroscope summarized 7abadda.