Codex CLI auth.json copy flow is broken: refresh succeeds but session still rejected (docs misleading)
Here’s a refined, sharper version that references the GitHub issue and clearly positions this as a known limitation + documentation gap.
---
Title
Codex CLI auth.json copy flow is unreliable / broken (refresh invalidates session) — contradicts documentation (#15410)
---
Summary
The documented workflow:
“Authenticate locally and copy your auth cache (~/.codex/auth.json)”
does not work reliably in practice and appears to conflict with known behavior described in #15410.
In my case:
auth.jsonis valid (ChatGPT mode, all tokens present)- Codex does attempt refresh (
last_refreshupdates) - but immediately fails with:
```id="err1"
Error loading configuration: Your authentication session could not be refreshed automatically.
This indicates that:
* refresh is executed
* auth cache is rewritten
* but the resulting session is unusable
---
### Relation to Existing Issues
This appears closely related to:
* **#15410** — refresh token invalidation across copies / CODEX_HOME usage
That issue states:
* refresh tokens are effectively single-use
* once one instance refreshes, other copies become invalid
* behavior is “not planned” to change
My case suggests the same underlying limitation applies to:
* cross-machine `auth.json` copy
* not just `CODEX_HOME` isolation
---
### Why This Is a Problem
The official documentation still presents `auth.json` copy as a supported fallback for:
* headless environments
* machines where browser login is not possible
However:
* the copied auth **looks valid**
* refresh is **actually executed**
* but session still fails immediately
This makes the workflow **unreliable and misleading**.
---
### Environment
* Codex CLI: `0.116.0`
* Source: corporate-managed machine (browser login allowed)
* Target: macOS (browser login blocked by policy)
* Auth storage: `cli_auth_credentials_store = "file"`
---
### Reproduction Steps
1. On source machine:
```bash id="step1"
cli_auth_credentials_store = "file"
codex logout
codex login
- Verify auth file:
```bash id="step2"
jq '{
auth_mode,
has_access_token: ((.tokens.access_token // "") != ""),
has_id_token: ((.tokens.id_token // "") != ""),
has_refresh_token: ((.tokens.refresh_token // "") != "")
}' ~/.codex/auth.json
Result:
```id="step2r"
auth_mode = "chatgpt"
all tokens = true
- Copy to target machine:
```bash id="step3"
cp ~/.codex/auth.json ~/.codex/auth.json
4. Run Codex:
```bash id="step4"
codex
---
Expected Behavior
Codex should:
- refresh tokens from
auth.json - proceed normally
(as described in documentation)
---
Actual Behavior
Codex:
- updates
last_refresh - retains valid tokens
- still fails immediately with auth error
---
Evidence
1. Refresh is executed
```bash id="ev1"
jq '.last_refresh' ~/.codex/auth.json
codex
jq '.last_refresh' ~/.codex/auth.json
Result:
```id="ev1r"
timestamp changed → refresh attempted
---
2. Tokens remain valid
```bash id="ev2"
jq '{
has_access_token: ((.tokens.access_token // "") != ""),
has_id_token: ((.tokens.id_token // "") != ""),
has_refresh_token: ((.tokens.refresh_token // "") != "")
}' ~/.codex/auth.json
Result:
```id="ev2r"
all = true
---
3. No login flow triggered
- no relevant entries in
codex-login.log - failure occurs in runtime refresh path
---
Key Observation
This matches the pattern described in #15410:
- auth cache appears valid
- refresh occurs
- but session becomes unusable due to token invalidation semantics
The limitation appears broader than documented:
- not only
CODEX_HOME - also cross-machine auth reuse
---
Why This Is Not User Error
- correct auth storage mode (
file) - correct file location (
~/.codex) - valid ChatGPT session
- valid refresh token present
- refresh confirmed via
last_refresh - no concurrent usage
- no config mismatch
---
Request
- Clarify in documentation that
auth.jsonis not safely portable across machines - Explicitly document refresh-token invalidation behavior
- Either:
- fix cross-machine auth reuse
- or remove / restrict “copy auth cache” recommendation
- Improve error message to reflect real cause (e.g. token invalidation vs generic refresh failure)
---
Bottom Line
- Current behavior aligns with #15410
- Documentation still suggests this workflow is supported
- In practice, it is unreliable
This is either:
- a design limitation not documented
- or a bug in refresh handling
But as it stands, the current guidance is misleading.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗