1. Codex 买号后登录卡住:auth.json 里 refresh_token 与 access_token 到底谁管什么
Codex 买号登录失败,绝大多数情况不是账号被回收,而是本地auth.json里的refresh_token、access_token或 JWT 过期、缺失、错位。这篇记录聚焦一个很具体的场景:你拿到一个 Codex 账号(常见格式是邮箱----密码----UUID----refresh_token),浏览器 OAuth 流程走不通,邮箱收不到验证码,但账号本身还能查到余额。这时候最有效的路径不是反复点登录,而是直接手动构造~/.codex/auth.json,让 Codex 启动时从文件读取凭证,跳过浏览器验证码环节。
先把三个字段的职责讲清楚,不然后面配置一定乱。refresh_token是长期凭证,用来向服务端换取新的access_token,它决定的是「这个账号有没有额度、订阅是否有效、扣费走谁的钱」。access_token是短期凭证,通常是一个 JWT,Codex 用它来显示当前用户信息、读取对话记录、标识身份。JWT 的 Payload 部分只是 Base64 编码,不是加密,任何人拿到完整 token 都能解出里面的邮箱、用户名、订阅类型。所以auth.json属于敏感文件,别随手丢进 Git 仓库或者发给别人。
我踩过的一个坑很典型:把卖家的refresh_token写进去之后,Codex 确实能跑起来,但解一下access_token的 Payload,发现邮箱还是我自己的。原因是本地之前登录过自己的账号,auth.json里残留了旧的access_token和id_token,我只替换了refresh_token。结果就是身份信息用我的、额度扣卖家的,两者分开管理。这个现象本身说明字段是解耦的,但也提醒你:手动配置时要么把access_token一起清掉让它重新换取,要么明确知道自己在用哪套身份。
适合谁看这篇:买了 Codex 号但登录流程卡在验证码的人;auth.json报 401 或 token 过期的人;想把 endpoint 切到统一 Key 通道、避免每次手动换 token 的人。下面从文件位置、字段对照、可复制配置、curl 验证到报错排查,一步步走完,目标是你能独立复现一次登录修复。
2. TaoToken 统一 Key 通道前置准备:endpoint 与凭证存储方式
在动手改auth.json之前,先把「凭证从哪读、请求发到哪」这两件事定下来。Codex 默认走 OpenAI 官方 endpoint,并且默认可能从系统钥匙串或浏览器 OAuth 拿凭证。手动配置的核心就是两件事:用config.toml告诉 Codex 从文件读凭证,用统一 Key 通道替换掉需要频繁刷新 token 的官方直连。
统一 Key 通道的价值在于:你不需要每次access_token过期就重新走一遍 OAuth,也不需要把卖家的refresh_token反复贴来贴去。把 Base URL 指向 TaoToken 的 API 入口,用一把统一的 Key 完成鉴权,Codex 侧的凭证管理会简单很多。API 入口是https://taotoken.net/api,注意这个地址不带任何查询参数,直接作为 Base URL 使用。官网入口是https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=,需要看文档或开 Key 的时候从这进。
凭证存储方式由config.toml里的cli_auth_credentials_store决定。默认值可能是keyring或auto,意思是优先从系统钥匙串读。你要手动控制auth.json,就得把它设成file,强制 Codex 只认文件。这一步不做,你改完auth.json会发现 Codex 根本不读,还是走钥匙串里的旧凭证,然后你以为是 token 写错了,其实是存储位置没切。
目录位置先确认清楚,两个系统不一样:
| 系统 | auth.json 路径 | config.toml 路径 |
|---|---|---|
| Windows | C:\Users\用户名\.codex\auth.json | C:\Users\用户名\.codex\config.toml |
| macOS/Linux | ~/.codex/auth.json | ~/.codex/config.toml |
如果.codex目录不存在,先建目录再建文件。Windows 下用资源管理器或者 PowerShell 都行,macOS/Linux 用mkdir -p ~/.codex。建好之后先别急着写内容,下一步会给完整的字段对照和可复制片段。
这里要强调一个顺序:先写config.toml把存储方式切成file,再写auth.json。反过来做的话,中间那次启动可能又往钥匙串里写了一份,后面排查会多一层干扰。另外,如果你之前登录过自己的账号,建议先把旧的auth.json备份一份再改,出问题能回滚。
3. 可复制配置:auth.json 字段对照与 config.toml 完整片段
这一节给可直接复制的配置。先看auth.json的字段对照,理解每个键的作用再填值,比无脑粘贴靠谱。
| 字段 | 类型 | 作用 | 是否必填 |
|---|---|---|---|
auth_mode | string | 认证模式,ChatGPT 账号填chatgpt | 是 |
tokens.refresh_token | string | 长期凭证,换新 access_token、决定额度 | 是 |
tokens.access_token | string | 短期 JWT,标识身份、读对话记录 | 可留空由刷新生成 |
tokens.id_token | string | 身份 JWT,含邮箱等信息 | 可留空 |
last_refresh | string | 上次刷新时间,ISO8601 格式 | 建议填 |
auth.json可复制片段(把rt_xxx换成你拿到的refresh_token):
{ "auth_mode": "chatgpt", "tokens": { "refresh_token": "rt_xxx" }, "last_refresh": "2026-04-30T00:00:00Z" }如果你希望连access_token也手动写死(比如已经有合法 JWT),可以扩展成:
{ "auth_mode": "chatgpt", "tokens": { "refresh_token": "rt_xxx", "access_token": "eyJhbGciOi...", "id_token": "eyJhbGciOi..." }, "last_refresh": "2026-04-30T00:00:00Z" }注意:手动写access_token只在它还没过期时有效,过期后 Codex 会用refresh_token去换新的。所以更稳的做法是只填refresh_token,让 Codex 自己刷新。
config.toml可复制片段,关键是cli_auth_credentials_store = "file",以及把 endpoint 指向统一 Key 通道:
cli_auth_credentials_store = "file" # 统一 Key 通道,Base URL 不带查询参数 base_url = "https://taotoken.net/api"如果你的 Codex 版本用model_provider段来配置,可以写成:
cli_auth_credentials_store = "file" [model_providers.taotoken] base_url = "https://taotoken.net/api" wire_api = "chat"三件套要写全:Base URL 用https://taotoken.net/api,Key 用你在控制台开的统一 Key,Model ID 按你实际要调的模型填。只写 Base URL 不写 Key,请求会 401;只写 Key 不写 Model ID,可能报模型不存在。这三样缺一不可。
写完两个文件后,检查一下编码。Windows 下用记事本另存为 UTF-8,别存成带 BOM 的格式,否则解析可能出问题。macOS/Linux 用cat看一眼内容确认没写错。下一步用 curl 验证 token 是否真的有效,别等 Codex 启动报错才发现。
4. 验证请求:用 curl 检查 token 有效性与 endpoint 连通
配置写完不要直接开 Codex,先用 curl 做一次独立验证,把「token 问题」和「Codex 客户端问题」分开。验证分两步:先验证统一 Key 通道的 endpoint 通不通,再验证refresh_token能不能换出有效凭证。
第一步,验证 endpoint 连通和 Key 是否有效。把YOUR_KEY换成你的统一 Key:
curl -sS https://taotoken.net/api/v1/models \ -H "Authorization: Bearer YOUR_KEY" \ -H "Content-Type: application/json"正常返回是一个包含模型列表的 JSON,能看到data数组。如果返回 401,说明 Key 不对或者没带上;如果连接超时,检查网络和 Base URL 是否写错(注意是https://taotoken.net/api,不要多加/v1之外的路径)。
第二步,验证refresh_token是否还能用。这一步是向认证端点提交 refresh_token 换新 token,不同实现路径略有差异,核心是 POST 一个表单或 JSON,带上grant_type=refresh_token和你的refresh_token:
curl -sS -X POST https://taotoken.net/api/v1/oauth/token \ -H "Content-Type: application/json" \ -d '{ "grant_type": "refresh_token", "refresh_token": "rt_xxx" }'如果返回里带access_token字段,说明refresh_token有效,Codex 启动后能自动刷新。如果返回invalid_grant或 400,说明refresh_token已失效或被回收,需要重新获取。
第三步,验证 JWT 内容。拿到access_token后,解一下 Payload 确认身份信息对不对。Payload 是 Base64 编码,用下面命令解(取 JWT 中间那段):
echo "eyJlbWFpbCI6...中间段..." | base64 -d解出来能看到email、name等字段。如果邮箱不是你以为的那个,说明access_token是旧的残留,需要清掉让它重新换。
验证通过后,再启动 Codex:
codex启动后 Codex 会读auth.json,用refresh_token换新access_token,然后正常进入。如果这一步还报错,看下一节的排查对照。
5. 常见报错排查:401、local proxy failed、reading choices、OAuth 失败对照
这一节按真实报错逐条对照。每个报错先给现象,再给原因,最后给动作。
401 Unauthorized。现象是 curl 或 Codex 返回 401。原因通常是三种:Key 没带、Key 写错、access_token过期且refresh_token也失效。动作:先用第 4 节的 curl 验证 Key,确认 Key 本身有效;再检查auth.json里refresh_token是否完整(有没有被截断、有没有多余空格);如果refresh_token返回invalid_grant,说明它已失效,需要重新获取。
local proxy failed。现象是 Codex 启动时报本地代理失败。原因一般是config.toml里配了本地代理地址但代理没开,或者代理端口写错。动作:检查config.toml里有没有proxy相关配置,确认代理服务在运行;如果不需要代理,把相关行删掉,直接用统一 Key 通道的 Base URL。注意 Base URL 是https://taotoken.net/api,不要写成带本地端口的地址。
reading choices 报错。现象是请求返回后解析响应失败,提示读取choices出错。原因通常是 endpoint 路径不对,或者wire_api类型和实际接口不匹配。动作:确认 Base URL 是https://taotoken.net/api,wire_api按接口类型填(chat 类填chat);用 curl 直接打一次接口,看返回结构里有没有choices字段,如果返回的是错误 JSON,先解决错误再调 Codex。
OAuth 登录失败 / 验证码收不到。现象是浏览器 OAuth 流程卡住,邮箱收不到验证码。原因就是这篇开头说的场景。动作:不走 OAuth,直接手动配auth.json,把cli_auth_credentials_store设成file,填refresh_token,让 Codex 从文件读凭证。
auth.json 不生效。现象是改完文件 Codex 还是用旧凭证。原因几乎都是cli_auth_credentials_store没设成file,Codex 还在读钥匙串。动作:确认config.toml里这一行存在且拼写正确,重启 Codex。
JWT 解出来邮箱不对。现象是access_token里的邮箱不是当前账号。原因是旧access_token残留。动作:把auth.json里的access_token和id_token删掉,只留refresh_token,让 Codex 重新换。
排查顺序建议固定:先 curl 验 Key 和 endpoint,再验refresh_token,再看config.toml存储方式,最后看auth.json字段。这个顺序能把问题范围快速缩小,避免在多个文件之间来回猜。
6. 把 endpoint 固定到统一 Key 通道:长期使用的配置与 CTA
修复一次登录只是开始,长期用下去要解决的是「token 反复过期、每次都要手动换」的问题。把 endpoint 固定到统一 Key 通道,用一把 Key 完成鉴权,Codex 侧的凭证管理会稳定很多。核心配置就是第 3 节那两段:config.toml里cli_auth_credentials_store = "file"加上base_url = "https://taotoken.net/api",auth.json里保留有效的refresh_token。
如果你要长期跑编码任务或者 Agent 类工作流,建议直接看 Coding Plan,把额度、模型、Key 统一管理,避免每次手动配auth.json。需要开 Key 或看接入细节,从 API Keys 和接入文档进;想先验证模型对话效果,用模型对话页面试一次请求,确认返回正常再落到 Codex 配置里。这几个入口分别是:
- 模型对话:
https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= - Coding Plan:
https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= - API Keys:
https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= - 接入文档:
https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=
最后给一个实用习惯:把auth.json加进.gitignore,任何时候都不要提交。JWT 的 Payload 是明文编码,泄露一次就等于把邮箱和订阅信息交出去。配置改完后用 curl 验一次,再启动 Codex,这套流程走顺了,下次遇到 token 过期你自己就能定位到是refresh_token失效还是access_token残留,不用再从头猜。