认证系统的多策略架构
认证系统的多策略架构
学习目标
- 理解 Codex 的
CodexAuth枚举和AuthProvidertrait 抽象 - 掌握 Codex 的 OAuth PKCE 流程和自动刷新机制
- 分析 Codex 的
UnauthorizedRecovery状态机和多账户安全
项目实践
认证架构
Codex 的认证系统分布在 codex-rs/login/src/auth/ 和 model-provider/:
login/src/auth/- manager.rs # AuthManager、CodexAuth 枚举- api_key.rs # API Key 认证- chatgpt.rs # OAuth (ChatGPT) 认证- agent_identity.rs # JWT (Ed25519) 认证- bearer.rs # Bearer token 通用实现- recovery.rs # UnauthorizedRecovery 状态机
model-provider/src/- provider.rs # ModelProvider trait(含 auth 方法)- ...CodexAuth 枚举
login/src/auth/manager.rs 定义了所有认证策略:
pub enum CodexAuth { ApiKey(ApiKeyAuth), Chatgpt(ChatgptAuth), // OAuth + refresh_token ChatgptAuthTokens(ChatgptAuthTokens), // 外部传入的 token AgentIdentity(AgentIdentityAuth), // JWT + Ed25519}统一转换:auth_provider_from_auth() 将 CodexAuth 转换为 SharedAuthProvider(Arc<dyn AuthProvider>),供 HTTP 客户端使用。
OAuth PKCE 流程
login/src/auth/chatgpt.rs 实现 ChatGPT OAuth:
pub struct ChatgptAuth { pub access_token: String, pub refresh_token: Option<String>, pub expires_at: Option<DateTime<Utc>>, pub account_id: String,}流程:
- 生成
code_verifier+code_challenge(PKCE) - 打开浏览器,用户授权
- 本地临时 HTTP 服务器接收
authorization_code - 交换
access_token+refresh_token - Token 过期前用
refresh_token自动续期
Agent Identity (JWT + Ed25519)
login/src/auth/agent_identity.rs 实现服务间调用认证:
pub struct AgentIdentityAuth { pub private_key: Ed25519PrivateKey, pub key_id: String, // kid}签名流程:
- 使用 Ed25519 私钥对请求进行签名
- 将 JWT(含
kid)放入Authorization头部 - 服务端使用对应的公钥验证签名
优势:无需与授权服务器交互,完全本地验证,适合高并发服务间调用。
AWS SigV4
model-provider/src/bedrock_mantle.rs 实现 AWS SigV4 签名:
impl BedrockMantleSigV4AuthProvider { async fn sign_request(&self, req: &mut Request, ) -> Result<> { // 1. 剥离 Bedrock Mantle 不保留的 snake_case 头部 // 2. 使用 AWS SigV4 算法签名 // 3. 添加签名头部 }}关键细节:签名前剥离不保留的头部,避免签名失败。这是 AWS 生态集成的常见陷阱。
UnauthorizedRecovery 状态机
login/src/auth/recovery.rs 实现认证恢复:
pub struct UnauthorizedRecovery { manager: Arc<AuthManager>, step: UnauthorizedRecoveryStep, expected_account_id: Option<String>, mode: UnauthorizedRecoveryMode,}
enum UnauthorizedRecoveryStep { CheckRefreshToken, RefreshToken, Reauth, Fail,}恢复流程:
- 检查是否有
refresh_token - 尝试刷新
access_token - 如果刷新失败,进入交互式重新认证
- 验证
expected_account_id,防止账户切换攻击
问题与规避
Token 泄露风险
Codex 的缓解措施:
- OAuth token 存储在系统 keyring 中(而非明文文件)
refresh_token持久化时加密- 提供
logout命令彻底清除认证状态
多账户切换
expected_account_id 防止攻击者通过刷新 token 切换到不同账户。如果刷新后的 token 属于不同账户,认证恢复失败。
设计取舍
枚举 vs trait 对象
Codex 在内部使用 CodexAuth 枚举,但对外暴露 Arc<dyn AuthProvider>。这种”内枚举外 trait”的设计:
- 内部处理方便(模式匹配)
- 对外扩展灵活(可添加新的 AuthProvider 实现)
本地存储 vs 系统 keyring
Codex 优先使用系统 keyring(macOS Keychain、Windows Credential Manager、Linux Secret Service)。当 keyring 不可用时回退到文件存储(加密后)。