opencodex 多账户 OAuth 认证体系从 auth.json 多账户存储到 GUI 账户切换的完整实现【免费下载链接】opencodexUniversal provider proxy for OpenAI Codex Claude Code — use any LLM (Claude, Gemini, Grok, DeepSeek, Ollama…) with Codex CLI, App, SDK, and Claude Code项目地址: https://gitcode.com/gh_mirrors/ope/opencodexopencodex 作为 OpenAI Codex / Claude Code 的通用 Provider 代理其 OAuth 认证层在 260706 迭代中完成了多账户化改造multiauth同一 Provider 下可以同时登录多个账户运行时只使用“激活账户”的凭据并在 GUI 上提供账户下拉切换、添加、删除能力。本文以devlog/_fin/260706_provider-multiauth的开发记录为主线结合src/oauth源码与测试完整讲解数据模型、迁移策略、解析器、Token Guardian、管理 API 与 GUI 交互并如实说明各 Provider 的适用边界。功能背景与设计目标在 multiauth 之前~/.opencodex/auth.json中每个 Provider 只保存一份 OAuth 凭据单槽位。用户在同一 Provider 下拥有多个账号时只能反复登出再登录且后台账户的刷新令牌无人维护容易出现“登录中途失效”开发日志中称为“로그인 안풀리는”问题。multiauth 单元的明确目标见 000_plan.md是auth.json每个 Provider 保存 N 个账户支持激活账户切换GUI Provider 卡片出现细条账户下拉框点击即激活请求只使用激活账户本单元不做跨账户 429 自动轮换轮换属于后续单元显式非目标跨账户 429 自动轮换、按账户拉取配额、API-key 池、Codex 池改动、usage-log 的 accountId 归属。范围排除Codex / ChatGPT 的 passthrough 池已有独立体系codex-accounts.json Codex Auth 页multiauth 不重复实现。数据模型与迁移策略新形状ProviderAccountSet每个 Provider 在auth.json中的值从单个凭据对象升级为账户集合types.tsexport interface ProviderAccount { id: string; // 追加时一次性生成的稳定短 id轮换后不再重推 alias?: string; // 用户自定义显示名不参与鉴权 credential: OAuthCredentials; // access / refresh / expires / email / accountId ... needsReauth?: boolean; // 终态刷新失败invalid_grant / reused / revoked addedAt?: number; } export interface ProviderAccountSet { activeAccountId: string; // 当前激活账户请求只使用它 selectionRevision?: string; // 选择代数旧仓库无此字段 accounts: ProviderAccount[]; }持久化形状为{ provider: { activeAccountId, accounts: [...] } }示例000_plan.md{ anthropic: { activeAccountId: a1b2, accounts: [ { id: a1b2, credential: { access: ..., refresh: ..., expires: 0, email: xy.z }, needsReauth: false, addedAt: 0 } ] } }账户 id 派生规则账户 id 必须“对同一凭据稳定、对不同凭据可区分”。src/oauth/store.ts中newAccountId()使用sha256(accountId ?? email ?? refresh)取 128 bit32 个 hex 字符追加时若与既有账户冲突则加-1、-2后缀distinctAccountId。注意id 只在追加时生成一次并持久化轮换刷新令牌后不再重推——因为getAccountCredential依赖 id 定位账户若每次刷新都重新派生 id会导致刷新结果写入失败、令牌静默丢失。旧数据兼容legacy 归一化 一次性降级备份加载时若某 Provider 的值是旧的单凭据对象含access字符串normalizeAccountSet会将其包装为{ activeAccountId: derived, accounts: [一条] }登录不丢失持久化一律写新形状加载器对两种形状永久兼容降级安全网首次以新形状覆盖仍含 legacy 条目的文件前会写入一次性备份auth.json.pre-multiauth0600 权限防止旧版 opencodex 静默丢弃新形状后无法恢复刷新令牌实现见 store.ts 的backupLegacyOnce。单槽位例外chatgpt始终单槽位codex-auth-api把它当作 Codex 池登录的临时槽位池子自己有codex-accounts.json账本因此saveCredential(chatgpt, ...)总是整体替换SINGLE_SLOT_PROVIDERS。无身份字段无 accountId/email的凭据普通登录时替换激活槽位避免轮换刷新令牌制造重复账户显式“添加账户”登录则保留旧槽位并追加preserveIdentityless选项。存储层mutateStore 与多账户 APIsrc/oauth/store.ts约 1108 行是 multiauth 的核心存储实现全部写操作走in-process 串行化mutateStore内部先获取auth.store.lock文件锁30s stale在队列中执行 load → mutate → persist避免“guardian 刷新非激活账户”与“用户切换激活账户”并发造成的丢失更新。跨进程竞态被接受单代理假设。存储公开 APIstore.tsAPI语义getCredential(provider)返回激活账户凭据请求路径用saveCredential(provider, cred)同身份 upsert替换凭据并清除 needsReauth并激活新身份追加无身份替换激活槽removeCredential(provider)仅删除激活账户剩余账户提升第一个否则删除 Provider 键listAccounts(provider)列出全部账户getAccountSet(provider)获取账户集合getAccountCredential(provider, accountId)/getAccountCredentialWithStatus读取指定账户凭据后者一次性带回 needsReauth 标志省一次全文件解析saveAccountCredential(provider, accountId, cred)为指定账户持久化刷新后的凭据不动 activeAccountIdguardian 专用路径setActiveAccount(provider, accountId)切换激活账户removeAccount(provider, accountId)删除指定账户激活账户被删则提升下一个markAccountNeedsReauth(provider, accountId, flag)标记终态刷新失败upsertCredentialByIdentity(provider, cred)原子插入/更新身份凭据导入器用返回 inserted/updatedcommitOAuthAccountSelection/captureOAuthAccountSelection配合selectionRevision实现选择一致性只有选择确实变化或手动重申才推进代数持久化后通过publishAccountSelection发布事件GUI 可订阅实时刷新。账户感知的认证解析层src/oauth/index.ts是解析层核心单飞锁升级single-flight Map 的键从provider改为provider \u0000 accountId每个 (provider, account) 独立去重刷新getValidAccessToken(provider)解析激活账户后委托给新的getValidAccessTokenForAccount(provider, accountId)读取getAccountCredential过期则发起单飞刷新刷新成功 →saveAccountCredential(provider, accountId, merged)——先落盘再返回 access轮换安全新 refresh token 先写盘与 auth2api manager 的实践一致刷新时保留 identity 字段刷新失败分类响应体含invalid_grant/refresh_token_reused/expired大小写不敏感视为终态→markAccountNeedsReauth(provider, accountId, true)并抛OAuthLoginRequiredError其余错误按瞬时错误重抛kiro 本地 CLI 导入回退仅在accountId activeAccountId时执行避免后台账户被错误导入forceLoginxai / anthropic 传importLocal: off跳过本地 CLI 令牌导入、走真实 OAuth 流使“添加第二个账户”不会复用浏览器会话的第一个账户antigravity 强制select_account提示cursor 的第二个参数是轮询间隔数字不能盲传 opts。Token Guardian为每个账户保活src/oauth/token-guardian.ts负责后台主动刷新遍历每个 Provider 的全部账户listAccounts跳过needsReauth账户终态只有重新登录能修复调用getValidAccessTokenForAccount退避键升级为oauth:provider:accountIdneedsReauth 账户获得永久退避不再反复锤击死掉的刷新令牌安全设计guardian 只触碰有效 refreshPolicy 为proactive的 Provider且全局开关config.tokenGuardian.enabled默认关闭——默认无新增后台流量保活语义呼应“登录不失效”诉求非激活账户仅当 Provider 为 proactive 策略时才由 guardian 保活。Anthropic 默认保持disabledToS 风险其第二个账户只能存活到其刷新令牌自然过期为止。管理 API/api/oauth/accountssrc/server.tsOAuth 端点块新增/修改的接口详见 030_api.mdGET /api/oauth/accounts?providerx→{ activeAccountId, accounts: [{ id, email(掩码), active, needsReauth, expiresAt, health... }] }未知 Provider 返回 400PUT /api/oauth/accounts/activebody{ provider, accountId }→ 切换激活账户账户不存在返回 404成功后使clearProviderQuotaCache()使配额缓存失效并清除该 Provider 的 live-model 缓存配额条与模型列表立即反映新账户DELETE /api/oauth/accounts?providerxidy→ 删除指定账户删除最后一个账户时同时clearLoginState(provider)POST /api/oauth/login接受可选{ addAccount: true }→ 以forceLogin: true启动登录流允许在浏览器中选择新身份原有单账户登录行为不变POST /api/oauth/logout不变删除激活账户。安全不变量邮箱经maskEmail掩码任何响应不含 tokenOAuthAccountSummary与OAuthAccessSnapshot为手写白名单结构从构造上保证机密不出响应。测试tests/oauth/oauth-accounts-api.test.ts验证了GET 列表邮箱被掩码且不含 tokenraw.includes(t1) false、needsReauth 账户投影reauth_required健康状态与ocx login anthropic修复动作、PUT 切换后activeAccountId变更、未知账户 404 / 未知 Provider 400、DELETE 删除激活账户后自动提升剩余账户以及切换 Antigravity 账户后 account-scoped live-model 缓存被清空、在途的旧账户模型发现被丢弃。GUIProvider 卡片上的账户下拉gui/src/pages/Providers.tsx与gui/src/styles.css实现了移除.provider-quota顶部分割线对应“중간선 없애고”需求保留 paddingOAuth 卡片新增细条Accounts (N)折叠行chevron 随展开旋转展开后列出账户圆点 掩码邮箱 激活徽标点击非激活账户 →PUT /api/oauth/accounts/active→ 刷新账户列表 配额 通知每账户提供删除图标末尾 Add account行 →POST /api/oauth/login { addAccount: true }复用既有 loginOAuth 轮询提取为接受 addAccount 标志仅authMode oauth的卡片显示跳过 forward/passthrough 与 chatgpt——Codex 池独立单账户卡片也显示作为添加第二个账户的入口i18n 键en/ko/zhprov.accountsAccounts {n}、prov.accountActive、prov.accountSwitch、prov.accountAdd、prov.accountRemoved、prov.accountSwitched无邮箱的账户如 cursor回退显示短账户 idi18nprov.accountNoLabel。GUI 构建验证tsc -b干净、vite build 通过、浏览器截图确认分割线消失、下拉可打开并切换 Active 徽标、390px 移动宽度无溢出。适用边界与诚实限制multiauth 不是对所有 Provider 一视同仁开发日志的 D 总结050_done.md明确划定了边界有效多账户 Providerxai、anthropic、google-antigravity凭据含稳定身份保持单账户kimi、kiro、cursor刷新令牌轮换、凭据无稳定身份派生 id 会把同一人拆成多个账户。Kiro 第二个账户不支持import-first 流程。不过 kimi 会从 JWT 提取user_id/sub作为 accountId、cursor 提取 JWTsub二者在 multiauth 下可追加带身份的独立账户Anthropic 后台账户保活受限默认 refreshPolicy 为 disabled第二个账户只存活到刷新令牌自然过期本单元不含跨账户 429 自动轮换后续单元设计草稿cooldown Retry-After 下次请求切换跨进程存储竞态被接受单代理假设。验证方式与运行说明开发日志记录的质量门禁可复现验证# 类型检查根目录 GUI bun x tsc --noEmit cd gui bun x tsc -b # 全量测试含 oauth-store-multi、oauth-accounts-api、token-guardian 新断言 bun test ./tests/ # 隐私扫描确认无密钥泄露 bun run privacy:scan # 运行时冒烟隔离 OPENCODEX_HOME 启动代理GET 掩码账户列表、PUT 切换、DELETE 提升存储层测试位于 tests/oauth/oauth-store-multi.test.ts覆盖legacy→新形状往返、新身份追加并激活、同身份替换、setActiveAccount 切换、激活账户删除后提升、末位删除清除 Provider、needsReauth 持久化、非法条目丢弃管理 API 测试位于 tests/oauth/oauth-accounts-api.test.ts。关闭记录999_closed.md确认commit 12aff01 交付多账户 OAuth 存储与 API-key 池支持最新全量套件 1555 通过 / 0 失败。使用提示auth.json位于~/.opencodex/可通过OPENCODEX_HOME环境变量重定向GUI 仪表板默认监听 10100 端口CLI 侧删除账户可用ocx login provider重新登录、管理 API DELETE 精确删除指定账户。【免费下载链接】opencodexUniversal provider proxy for OpenAI Codex Claude Code — use any LLM (Claude, Gemini, Grok, DeepSeek, Ollama…) with Codex CLI, App, SDK, and Claude Code项目地址: https://gitcode.com/gh_mirrors/ope/opencodex创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
企业数字化 ERP 产品动态
相关推荐
UE5第一人称射击游戏开发:从角色移动到AI追击的完整实践 简介:这是一份UE5第一人称射击游戏开发实战教程,适合具备一定UE5基础、希望系统掌握FPS核心玩法的初学者和中级程序员。PDF围绕完整开发流程展开:先进行环境搭建与项目设置,再依次实现第一人称视角、玩家移动与交互、射击与敌人AI… · 2026/9/23 20:37:48
五天四夜原理详解:新手避坑指南,复制代码跑不通?看这篇就通了 五天四夜原理详解:新手避坑指南,复制代码跑不通?看这篇就通了 你刚把网上那段“五天四夜”的逻辑抄进项目,回车一按,终端直接报错,或者跑出来的数据全是乱码。这时候你盯着屏幕发呆,不知道是该改配置还是查依赖。别急,这就是典型的“新手避坑”场景:… · 2026/9/23 20:37:41
医疗影像碎片检测与结构分析:从数据集解压到模型训练全攻略 简介:面向医疗影像算法研究与医学AI教学的碎片检测与结构分析数据集,用于医疗影像碎片化特征区域检测与结构关联分析。数据覆盖多样化医疗影像场景,共1,277张标注图片,其中训练集894张、验证集255张、测试集128张;围绕… · 2026/9/23 23:07:13
razzle-dev-utils 工具集完全指南:从日志、错误美化到 Loader 查找的 Razzle 开发辅助库 前端构建工具前端构建后端 【免费下载链接】razzle ✨ Create server-rendered universal JavaScript applications with no configuration 项目地址: https://gitcode.com/gh_mirrors/ra/razzle 点击查看 免费下载 本指南以 Razzle 仓库中 packages/razzle-dev-ut… · 2026/9/23 23:07:13
医疗AI生成PPT的数据安全与完整性保障方案 1. 医疗场景下AI生成PPT的数据安全挑战在医疗信息化快速发展的今天,医护人员使用AI工具辅助制作学术报告、病例讨论PPT已成为普遍现象。某三甲医院统计显示,2023年有78%的临床科室使用过AI生成演示文档。但随之而来的数据安全问题不容忽视——去年国内医… · 2026/9/23 23:07:13
数据安全与隐私计算技术深度解析与应用实践 1. 活动背景与核心价值解析这场由云创数安创始人兼总经理白云先生主讲的上海站活动,本质上是一场聚焦数据安全领域的行业深度交流会。作为国内数据安全赛道的早期实践者,白云及其团队在金融级数据加密、企业隐私计算架构等领域有多个标杆案例。活动选址上… · 2026/9/23 23:07:13
OSPF课程设计:从配通到可验证的路由决策 简介:本资源是一份面向计算机网络专业本科生的课程设计实践文档,聚焦OSPF路由协议在多局域网互连中的实际应用,帮助学习者系统掌握子网划分、OSPF原理与配置、拓扑设计及Cisco设备实操等核心技能。压缩包为1个1.16MB的Word文档(.d… · 2026/9/23 23:07:13
救援机器人结构设计全解析:从履带底盘、动力计算到样机验证 简介:面向机械设计、机器人工程专业学生及救援机器人相关研发人员撰写的一份结构设计技术文档,围绕救援机器人机身、机械臂、传动系统和运动系统等核心部分展开系统论述。文档以火灾救援为应用背景,分析了国内外救援机器人研究现状与发展趋势… · 2026/9/23 23:07:07
3招搞定手机怎么下载微信面试难题实战项目解析 3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A… · 2026/9/23 0:00:03
你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 面试被问“高并发下如何保证消息不丢失”,你张口就是“用Redis”,结果面试官追问“如果Redis宕机了怎么办”,你瞬间卡壳。这种场景太常见了,很多新手在背八股文时,只记住了技术名词… · 2026/9/23 0:00:29