# Codex 令牌交换失败 403 怎么解决？按错误后缀定位登录拒绝

> Codex 令牌交换 403 没有通用的一键修复：保留完整错误后缀，回调不通时选设备码或 SSH，地区与工作区拒绝时核对资格和权限，最后在原环境验证原认证方式。

- URL: https://blog.laozhang.ai/zh/posts/codex-token-exchange-failed-403
- Published: 2026-07-12
- Updated: 2026-10-06
- Author: LaoZhang AI Team (https://blog.laozhang.ai/zh/about)
- Topic: 开发工具与智能体
- Tags: OpenAI Codex, Codex CLI, 令牌交换失败, 403 Forbidden, OAuth, 登录排查

---
遇到 `Token exchange failed: token endpoint returned status 403 Forbidden`，先保留这行后面的完整错误，再决定怎么处理。**浏览器授权完成、终端仍等待，先查回调是否到达；终端已经报令牌交换 403，就应查看响应正文和实际运行环境；正文明确写国家、地区或工作区限制时，停止重复登录，转向资格核验或管理员。** 换浏览器、清缓存和设备码登录各有适用条件，不能互相替代。

403 的含义是响应这一请求的服务器拒绝执行。它不保证拒绝来自 OpenAI 源站，也不直接说明代理、账号或令牌是哪一个出了问题；中间代理也可能返回 403。[HTTP 403 的定义](https://www.rfc-editor.org/rfc/rfc9110.html#section-15.5.4)还明确指出，拒绝原因可以与凭据无关，不应自动用同一凭据重复请求。

## 先对照完整错误，找到下一动作

| 你实际看到的现象 | 先做什么 | 什么结果会改变判断 |
| --- | --- | --- |
| 浏览器完成授权，终端一直等，没有交换 403 | 确认浏览器能否到达运行 Codex 的回环回调端口 | 回调确实到达后，若出现交换 403，再进入交换排查 |
| `token endpoint returned status 403 Forbidden` | 保留脱敏响应正文、时间和请求 ID，确认 CLI、IDE、WSL 或容器到底在哪里运行 | 账号政策码、工作区信息或企业拦截页能缩小处理范围 |
| `error sending request for url` 或“发送 URL 出错” | 从完整错误链找连接、TLS、代理等具体信息，记录目标主机名 | 若没有实际 HTTP 响应，不能仅凭这句称为服务器 403 |
| “国家、地区或领土不受支持”或 `unsupported_country_region_territory` | 停止连续尝试，核对对应服务的当前资格规则；认为误判时联系支持 | 官方确认资格与访问条件后，才重新验证登录 |
| `Workspace routing is unavailable`、工作区或政策提示 | 确认选择的工作区和管理员允许的登录方式，把原文交给管理员 | 权限或网络政策被确认、调整后再试；这句话本身不证明是缓存问题 |
| 登录已完成，第一次任务才报 403 | 查看该次请求的服务、认证方式和权限 | 这是登录后的请求失败，不能按 OAuth 交换失败处理 |

这里的关键是**失败发生在哪一步**，而不是看到 403 就套一条代理命令。浏览器是否成功、请求是否收到 HTTP 响应、响应由谁生成，需要分开记录。

## 在真正报错的环境收集线索

先在原终端记录版本和认证状态：

```bash
codex --version
codex login status
```

如果报错来自 IDE 或桌面应用，另一个终端里的状态只能作比较：它可能不在同一主机、不继承同一组变量，甚至使用了不同的 `CODEX_HOME`。WSL、容器和 SSH 尤其要写清楚“浏览器在哪台机器，Codex 进程在哪台机器”。版本与安装有疑问时，按[原安装方式检查 Codex CLI](https://blog.laozhang.ai/zh/posts/codex-cli-install)，不要照抄论坛里的版本号反复升降级。

`codex login status` 用于确认当前认证方式。[CLI 命令说明](https://learn.chatgpt.com/docs/developer-commands#codex-login)说退出码为 0 表示有凭据，**并不表示服务端接受了凭据，也不表示任务能完成**。因此“status 成功”只能是中间检查。

直接执行 `codex login` 时，当前官方说明会在配置的日志目录写入 `codex-login.log`。已有登录日志可用来核对先后顺序，别只截取最后一行。分享前删除授权码、访问及刷新令牌、设备码、Cookie、API key、完整回调 URL、代理用户名密码与内部地址；保留时间、短错误码、请求 ID 和目标主机名即可。[登录日志说明](https://learn.chatgpt.com/docs/auth#login-diagnostics)

### 安全比较环境变量，不打印代理密码

下面是 macOS、Linux、WSL 或容器中有 Python 3 时可用的本地摘要。它只报告变量是“已设置”还是“未设置”，不读取认证文件、不发请求，也不显示变量值：

```bash
python3 - <<'PY'
import os

names = (
    "HTTP_PROXY", "HTTPS_PROXY", "ALL_PROXY", "NO_PROXY",
    "http_proxy", "https_proxy", "all_proxy", "no_proxy",
    "CODEX_CA_CERTIFICATE", "SSL_CERT_FILE", "CODEX_HOME",
    "OPENAI_API_KEY", "CODEX_ACCESS_TOKEN",
)
for name in names:
    state = "已设置" if os.environ.get(name) else "未设置"
    print(f"{name}: {state}")
PY
```

这个摘要可帮助比较宿主机与容器，或两个启动终端的差异；“已设置”仍不证明配置正确，另一个终端的输出也不能代替正在失败的应用进程。需要确认实际代理地址时，由你或网络管理员在本机查看，别把完整环境变量导出到公开工单。上面的输出逻辑只做过含合成敏感值的离线检查，未用它完成真实登录。

## 浏览器成功，终端没收到回调：选设备码或 SSH

浏览器授权后还要把结果返回 Codex，Codex 才能继续交换令牌。远程主机或容器里的回调监听器，与本机浏览器可能不在同一可达环境。这种情况下，先修复回调，不必去改账号凭据。

![Codex 登录阶段与跨主机回调示意：浏览器授权后，Codex 仍需收到回调、交换令牌、保存凭据并验证原环境请求；设备码和获准 SSH 转发解决回调条件](https://blog.laozhang.ai/posts/zh/codex-token-exchange-failed-403/img/auth-stages.webp)

[官方无头登录说明](https://learn.chatgpt.com/docs/auth#login-on-headless-devices)优先建议设备码认证，目前标为 beta。**先确认设备码登录已开启**：个人账号在 ChatGPT 安全设置启用，工作区账号需要管理员允许。然后在实际运行 Codex 的终端使用：

```bash
codex login --device-auth
```

打开终端给出的官方链接，在自己的浏览器里完成授权并输入这次生成的一次性代码。只处理你自己刚发起的登录，不接收别人发来的设备码。成功判断是原终端完成登录，不是另一台设备出现一个成功页面。

设备码改掉的是对本地浏览器回调的依赖。若它仍返回国家、账号或工作区拒绝，应按对应限制处理；它不会修复任意出站连接错误，也不会授予原本没有的服务权限。

如果设备码不可用，而你获准从本机 SSH 到远程主机，可以使用官方给出的回调转发方式。下面假设使用文档中的默认回调端口 1455：

```bash
# 在有浏览器的本机执行，替换 user@remote
ssh -L 1455:localhost:1455 user@remote
```

进入这个 SSH 会话后，在远程主机运行：

```bash
codex login
```

再用本机浏览器打开远程终端打印的授权地址。隧道把本机回调送到远程监听器；1455 是回调端口，不是代理端口。如果实际监听端口不同，先核对终端提示和当前官方说明，不把监听器暴露到公网。

官方还列出“在有浏览器的机器上登录，再复制自己的认证缓存”的后备方案，但它只适用于确实存在文件缓存、目标机器受信任且组织允许安全传输的情况。使用系统凭据存储时不一定有可复制文件，`CODEX_HOME` 改过时路径也不同。需要这条路线时按[官方缓存复制条件](https://learn.chatgpt.com/docs/auth#login-on-headless-devices)操作，不能复制别人的令牌，也不能借复制缓存规避目标环境的政策。

## 已收到交换 403：分别查网络拒绝、地区与工作区

回调到达并不表示交换一定能通过。接下来应看错误正文与网络记录，判断是哪一方明确拒绝了请求。响应是 HTML 拦截页时，页面标识与代理请求 ID 可提供网络侧线索；JSON 中的短错误码可提供服务侧线索。**仅凭格式或一行日志，仍不足以确认根因或响应者身份。**

![根据回调、网络、证书、账号地区、工作区与缓存证据选择恢复动作](https://blog.laozhang.ai/posts/zh/codex-token-exchange-failed-403/img/safe-recovery.webp)

### 企业代理或“发送 URL 出错”：核对实际进程的出站路径

让网络管理员根据时间、目标主机名、代理请求 ID 核对是否拦截认证请求，以及当前进程是否使用了批准的网络路径。浏览器能打开 ChatGPT，不证明 WSL、容器或 IDE 里的 Codex 能走同一路径。`NO_PROXY` 也不能盲目加入所有认证域名：回环请求和必须经过企业代理的出站交换是两件事。

旧教程中的“Codex 一律忽略系统代理，只读环境变量”不宜作为通用判断。官方[更新记录](https://learn.chatgpt.com/docs/changelog)已经记录登录与启动请求的系统代理回退支持；这说明应同时考虑系统设置和进程环境，但不代表任意版本、平台或 403 都会被回退机制修好。比较网络时保留版本与启动方式，以实际错误和批准路径的结果为准。

如果完整错误链是证书不受信任，且公司确实使用 TLS 检查或私有根证书，先向安全团队取得批准的 PEM 证书包。官方的文档示例是：

```bash
# 仅用于已确认的企业 CA 场景，替换为批准的 PEM 文件
export CODEX_CA_CERTIFICATE=/path/to/corporate-root-ca.pem
codex login
```

未设置 `CODEX_CA_CERTIFICATE` 时，Codex 回退使用 `SSL_CERT_FILE`；这些 CA 设置适用于登录、HTTPS 与安全 WebSocket。[自定义 CA 说明](https://learn.chatgpt.com/docs/auth#custom-ca-bundles)

证书链失败与收到 HTTP 403 是不同信号。补证书后仍出现同一拒绝，需要继续查看响应，不应继续添加陌生证书或关闭 TLS 校验。

### “国家、地区或领土不受支持”：停止换代理，核对官方资格

这类明确后缀需要资格核验，清登录缓存不会授予支持地区资格。先确认错误属于哪个服务：ChatGPT 登录、OpenAI Platform API，还是另一个供应商的请求。然后到 [OpenAI 帮助中心](https://help.openai.com/)查看对应服务当前的支持国家与地区说明。不同服务的名单不能互相替代，使用中文界面也不说明所在地符合资格。

如果你认为这是误判，向 OpenAI 支持提交出错时间与时区、服务名称、运行环境、脱敏错误正文和请求 ID，请支持确认当前访问条件。不要提供凭据或完整回调地址，也不要用借用账号、伪造所在地或更换出口绕过限制。只有资格与允许的访问条件明确后，再尝试原认证路线；本文不列一个未经本轮直接核验的国家清单。

### 工作区或管理员拒绝：本地缓存不能覆盖允许列表

先确认浏览器选中了预期账号与工作区。受管理的本地客户端，管理员可以在系统 `requirements.toml` 或 macOS MDM 要求中设置 `allowed_login_methods`、`allowed_chatgpt_workspaces`、`cli_auth_credentials_store` 与 `chatgpt_base_url`。这些本地认证要求在加载凭据、获取云策略之前生效；用户的 `forced_login_method` 和 `forced_chatgpt_workspace_id` 也必须服从要求。[本地认证管理说明](https://learn.chatgpt.com/docs/enterprise/managed-configuration#manage-authentication-locally)

可执行的下一步是请管理员核对：你的工作区是否在允许列表里，允许 ChatGPT 还是 API 登录，当前成员是否有相应产品权限，设备码是否被允许，以及日志中的网络政策提示由哪一层产生。没有匹配工作区时 ChatGPT 登录不可用；只有 API 认证被允许时，才可考虑 API 路线。所有登录方式都不可用时，客户端会拒绝启动。

不要自行改管理策略或反复换账号来试。管理员确认或调整相应条件后，再用同一工作区、同一环境复验；`Workspace routing is unavailable` 本身不足以证明是服务事故、网络拦截或本机缓存中的某一个。

## 什么时候才该退出重登或更换认证方式

如果错误指向失效登录态，或者你确认当前存储的账号、工作区与预期不符，并且网络与管理要求允许这条路线，可以做一次受控重登：

```bash
codex logout
codex login
codex login status
```

这里用的是默认浏览器 ChatGPT 登录。退出会清除当前存储的凭据，CLI 与 IDE 扩展共享登录缓存，一处退出会影响另一处。ChatGPT 会话通常在使用中自动刷新令牌，所以“用了很久”本身不证明缓存已经过期。[认证状态与缓存说明](https://learn.chatgpt.com/docs/auth#login-caching)

凭据也不一定在 `~/.codex/auth.json`：

- `file`：保存在 `CODEX_HOME` 下的 `auth.json`，默认目录是 `~/.codex`。
- `keyring`：使用操作系统凭据存储，不可用时失败。
- `auto`：优先系统凭据存储，不可用时才回退到文件。
- `ephemeral`：只保留在当前进程内，进程结束后不能按持久缓存理解。

这些模式由 `cli_auth_credentials_store` 控制，管理员也可能强制指定。别用删除某个文件的结果推断全部缓存已清理，更不要先删除整个 `~/.codex`。若进程环境选择了工作负载身份（workload identity），官方说明会拒绝 `codex login` 和 `codex logout`，应交由管理该环境的人处理。[凭据存储与认证说明](https://learn.chatgpt.com/docs/auth#credential-storage)

### 可以用 API key 吗？可以换路线，但不能当作原登录已修好

本地 Codex 支持 ChatGPT 和 API key 认证。只有当你确实希望使用 OpenAI Platform、具备 API 权限且接受独立按量计费时，才切换；Codex cloud 仍要求 ChatGPT 登录，依赖工作区或云服务的功能也可能受限。[两种认证方式的条件](https://learn.chatgpt.com/docs/auth#sign-in-with-an-api-key)

已在当前环境安全提供 `OPENAI_API_KEY` 时，官方 CLI 示例通过标准输入传入 key：

```bash
printenv OPENAI_API_KEY | codex login --with-api-key
codex login status
```

不要把真实 key 写成命令参数、贴进文章或工单。API 路线成功只证明另一条认证方式可用，不证明 ChatGPT 的令牌交换问题已恢复，也不能绕过地区或工作区限制。

如果你实际使用的是第三方网关，还需要确认凭据由谁签发、请求由谁接收。官方说明中，`requires_openai_auth = true` 会忽略 `env_key`；另一个供应商的 key 并不自动替代 OpenAI 登录。配置混用可参考[Codex 的 Key、Base URL 与 Provider 选择](https://blog.laozhang.ai/zh/posts/codex-config-toml)，第三方端点的拒绝则找该供应商核对。

## 恢复后，在同一环境验证原本要用的路线

恢复要看三个结果：原终端或应用完成登录；`codex login status` 显示预期认证方式；在**同一环境、同一工作区和原本要用的服务**完成一个最小任务。不要用浏览器成功、换成 API key 成功，或另一台主机有缓存来替代最后一步。

在确认费用、权限与数据范围允许后，可以启动 Codex，发送一个不包含仓库、客户或账号数据的短任务，例如“只回复 `AUTH_OK`，不要调用工具”。这一步会访问服务，API key 路线可能计费；它是读者获准后的验证动作，本文没有实际执行登录、退出或收费请求。

如果最小任务仍报 403，但令牌交换已经完成，应保存这次请求的新错误，转向服务权限、工作区或供应商配置排查。单次短任务成功也只证明这次认证和基本请求可用，不保证所有模型、工具和云端功能都可用。

一次改变一个条件即可：例如管理员修正允许列表，或者修复回调拓扑。记录“改变前失败在哪一步，改变后在哪一步成功”，不要同时清浏览器、换网络、换账号和改版本，否则恢复后也不知道原因。

## 仍然失败，提交这份脱敏记录

正文明确指向资格或管理员限制时直接找相应负责人；其余情况，在允许的路径上尝试有依据的修改后仍出现相同失败，就带着记录求助。可由 [OpenAI 帮助中心](https://help.openai.com/)进入支持渠道，并查看[服务状态页](https://status.openai.com/)是否有相关事件；没有公告也不能排除个别账号或网络问题。

```text
时间与时区：<实际失败时间>
Codex 版本：<版本输出>
运行位置：<本机 / WSL / 容器 / SSH，CLI / IDE / 桌面应用>
预期认证：<ChatGPT / API key / 组织提供的其他方式>
浏览器授权：<完成 / 未完成 / 未知>
回调：<到达 / 未到达 / 未知>
令牌交换：<完整错误的脱敏文本与短错误码>
响应标识：<请求 ID 或代理请求 ID，如有>
网络条件：<批准的代理 / 企业 TLS 检查 / 其他已确认条件>
唯一修改：<这次改了什么>
结果：<仍在同一步失败 / 登录完成 / 后续请求失败>
```

保留证据能让支持人员判断该核对网络、身份还是工作区。`auth.json`、操作系统凭据、访问令牌、设备码和完整回调 URL 都不能作为附件公开分享。

## 常见问题

### 为什么浏览器显示成功，Codex 还报令牌交换 403？

浏览器授权完成后，Codex 还要收到回调并完成令牌交换。终端仍等待时先查回调可达性；终端明确收到交换 403 时，查看该次响应正文与运行环境。成功页面不能证明后两步完成。[官方登录流程](https://learn.chatgpt.com/docs/auth)

### 设备码登录能解决所有 403 吗？

不能。它适合没有浏览器或回环回调不可达的场景，且需要个人安全设置或工作区管理员启用。它不取消账号、地区、工作区及网络访问条件。[设备码登录条件](https://learn.chatgpt.com/docs/auth#login-on-headless-devices)

### login status 返回 0，为什么任务仍失败？

0 只表示凭据存在。仍需确认认证方式正确，并在原环境完成获准的最小请求；请求失败时按其完整错误继续排查。[CLI status 的含义](https://learn.chatgpt.com/docs/developer-commands#codex-login)

### 报国家或地区不支持，清 auth.json 有用吗？

清文件不会改变服务资格，而且凭据可能存于系统凭据存储。先在 [OpenAI 帮助中心](https://help.openai.com/)核对对应服务当前规则；认为误判时联系支持。未明确允许的访问条件前，停止连续重试。

## 参考来源

本文引用的外部页面，按正文出现顺序排列。最后更新于 2026-10-06。

- [HTTP 403 的定义](https://www.rfc-editor.org/rfc/rfc9110.html) (rfc-editor.org)
- [CLI 命令说明](https://learn.chatgpt.com/docs/developer-commands) (learn.chatgpt.com)
- [登录日志说明](https://learn.chatgpt.com/docs/auth) (learn.chatgpt.com)
- [更新记录](https://learn.chatgpt.com/docs/changelog) (learn.chatgpt.com)
- [OpenAI 帮助中心](https://help.openai.com/) (help.openai.com)
- [本地认证管理说明](https://learn.chatgpt.com/docs/enterprise/managed-configuration) (learn.chatgpt.com)
- [服务状态页](https://status.openai.com/) (status.openai.com)
