fix(grok): persist rotated OAuth refresh token so GROK_CREDENTIALS survives past 6h#773
Merged
Merged
Conversation
…rvives past 6h The captured GROK_CREDENTIALS holds a 6h access token plus a refresh token that xAI rotates AND revokes on every refresh, so a static secret self-destructs ~6h after Connect: the first post-expiry run refreshes and rotates the token but writes the new one only to the ephemeral runner HOME, leaving the secret holding a now-revoked token. Headless runs then fail "Not signed in". Fix (mirrors scripts/mcp-oauth-refresh.sh's durable-refresh contract): - scripts/run-grok.sh section 2b refreshes the access token from the refresh token before each run, rewrites auth.json, and PERSISTS the rotated file back to the GROK_CREDENTIALS secret via a secrets-write PAT. Reuses the existing MCP_SECRETS_PAT (or GH_GLOBAL); the default GITHUB_TOKEN cannot write secrets. Refreshes only within GROK_OAUTH_SKEW seconds of expiry (default 1800). No-op on the XAI_API_KEY path and on a local `grok login` session. - aeon.yml: add a grok) case to the harness AUTH_MODE detection (grok was defaulting to openrouter, mislabelling a Connected X account as native), and pass MCP_SECRETS_PAT/GH_GLOBAL/GROK_OAUTH_SKEW into the grok install step. - messages.yml: same grok env on the inbound-message run. - dashboard GrokAuthModal: a secrets-PAT setup note (parallels McpPanel), hidden once MCP_SECRETS_PAT/GH_GLOBAL is set. - docs/harnesses.md + CHANGELOG: document the durable-refresh contract. - scripts/tests/test_run_grok.sh: 6 integration tests (refresh+persist, no-PAT warn, skip-when-valid, invalid_grant, API-key path). Verified end-to-end on a live instance: a forced run logged "persisted rotated GROK_CREDENTIALS (durable refresh active)" and the secret's updated_at bumped, so auth survives past 6h.
aaronjmars
added a commit
that referenced
this pull request
Jul 24, 2026
… for MCP + Grok (#774) One secrets-write PAT now serves both OAuth refresh-persistence paths: - MCP OAuth (scripts/mcp-oauth-refresh.sh), and - Grok X-account OAuth (scripts/run-grok.sh section 2b, landed in #773). Both read GH_SECRETS_PAT and fall back to GH_GLOBAL. #773 reused the MCP-named PAT as an interim; this generalizes the name now that it drives two features. MCP_SECRETS_PAT was still under [Unreleased], so no tagged release ever shipped it: operators tracking main who already set it should re-add the PAT as GH_SECRETS_PAT; GH_GLOBAL users are unaffected. - scripts/run-grok.sh, scripts/mcp-oauth-refresh.sh: read GH_SECRETS_PAT // GH_GLOBAL - aeon.yml / messages.yml: grok install/run env now passes GH_SECRETS_PAT - dashboard: secrets-catalog entry + McpPanel + GrokAuthModal point at GH_SECRETS_PAT; the catalog description + secrets reference now name both MCP and the Grok harness - docs (harnesses, mcp-oauth, CONFIGURATION) + .claude skill references - CHANGELOG: rename note under Changed - tests updated; test_run_grok.sh + test_mcp_oauth_refresh.sh both green
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Makes the grok harness's captured X-account OAuth session (
GROK_CREDENTIALS) durable past its 6h access-token lifetime.Why
The captured
GROK_CREDENTIALSholds a 6h access token plus a refresh token. xAI rotates and revokes the refresh token on every refresh (confirmed live -auth.x.aireturnsinvalid_grant"Refresh token has been revoked"). So a static secret self-destructs ~6h after Connect: the first post-expiry run refreshes and rotates the token, but grok writes the new one only to the ephemeral runner$HOME; the secret still holds the now-revoked token, and every later headless run failsNot signed in.How
Mirrors the existing
scripts/mcp-oauth-refresh.shdurable-refresh contract.scripts/run-grok.sh(§2b) refreshes the access token from the refresh token before each run, rewritesauth.json, and persists the rotated file back to theGROK_CREDENTIALSsecret via a secrets-write PAT. Reuses the existingMCP_SECRETS_PAT(orGH_GLOBAL) - the defaultGITHUB_TOKENcannot write secrets. Refreshes only withinGROK_OAUTH_SKEWseconds of expiry (default 1800). No-op on theXAI_API_KEYpath and on a localgrok loginsession.aeon.yml: adds agrok)case to the harness AUTH_MODE detection - grok was defaulting toopenrouter, so a Connected X account was mislabelled in the banner; nownative-oauth. PassesMCP_SECRETS_PAT/GH_GLOBAL/GROK_OAUTH_SKEWinto the grok install step, andGROK_CREDENTIALS/XAI_API_KEYinto the resolve step so the new case can see them.messages.yml: same grok env on the inbound-message run.GrokAuthModal: a secrets-PAT setup note (parallelsMcpPanel), hidden onceMCP_SECRETS_PAT/GH_GLOBALis set.docs/harnesses.md+CHANGELOG: document the durable-refresh contract.scripts/tests/test_run_grok.sh: 6 integration tests (refresh+persist, no-PAT warn, skip-when-valid, invalid_grant, API-key path).Notes
MCP_SECRETS_PATsecret rather than introducing a new name. A follow-up PR standardizes both the MCP and grok paths onto a singleGH_SECRETS_PAT(withGH_GLOBALfallback).docs/harnesses.md.Test
bash scripts/tests/test_run_grok.sh-> ALL PASS (incl. the 6 new OAuth tests)actionlintclean on both workflowsgrok oauth: persisted rotated GROK_CREDENTIALS (durable refresh active)and the secret'supdated_atbumped.