mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
fix: configure AgentIdentity AuthAPI base URL (#19904)
## Summary AgentIdentity runtime loading currently registers tasks against a single hardcoded AuthAPI base URL. That works for production, but local and staging validation may need registration to target a different authapi-login-provider without baking internal staging service URLs into the OSS binary. This PR adds a small config surface for `agent_identity_authapi_base_url` and threads it through the existing auth-loading path as a direct argument. Explicit config wins. Without config, task registration keeps using the production AuthAPI URL, matching the current default behavior. ## Stack 1. openai/codex#19762 - `refactor: make auth loading async` (merged) 2. openai/codex#19763 - `refactor: load agent identity runtime eagerly` 3. This PR - `fix: configure AgentIdentity AuthAPI base URL` 4. openai/codex#19764 - `feat: verify agent identity JWTs with JWKS` ## Design decisions - Keep the existing auth-loading shape and pass the new value as an argument. This avoids another wrapper loader and keeps the call path readable. - Add config instead of embedding internal staging URLs. Environments that need a non-production AuthAPI can configure it explicitly. - Keep the default AuthAPI registration URL as production. `chatgpt_base_url` remains separate and is used by the follow-up JWKS verification PR for fetching public keys from the ChatGPT backend route. - Resolve the AuthAPI base URL inside AgentIdentity loading, because task registration is the only consumer of this value. ## Testing Tests: targeted Rust checks, AgentIdentity auth tests, config schema regeneration, formatter/fix pass, and whitespace diff check.
This commit is contained in:
committed by
GitHub
Unverified
parent
a9e5c34083
commit
0e8d6b8765
@@ -1,12 +1,14 @@
|
||||
use codex_agent_identity::AgentIdentityKey;
|
||||
use codex_agent_identity::register_agent_task;
|
||||
use codex_protocol::account::PlanType as AccountPlanType;
|
||||
use std::env;
|
||||
|
||||
use crate::default_client::build_reqwest_client;
|
||||
|
||||
use super::storage::AgentIdentityAuthRecord;
|
||||
|
||||
const AGENT_IDENTITY_AUTHAPI_BASE_URL: &str = "https://auth.openai.com/api/accounts";
|
||||
const PROD_AGENT_IDENTITY_AUTHAPI_BASE_URL: &str = "https://auth.openai.com/api/accounts";
|
||||
const CODEX_AGENT_IDENTITY_AUTHAPI_BASE_URL_ENV_VAR: &str = "CODEX_AGENT_IDENTITY_AUTHAPI_BASE_URL";
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct AgentIdentityAuth {
|
||||
@@ -16,9 +18,10 @@ pub struct AgentIdentityAuth {
|
||||
|
||||
impl AgentIdentityAuth {
|
||||
pub async fn load(record: AgentIdentityAuthRecord) -> std::io::Result<Self> {
|
||||
let agent_identity_authapi_base_url = agent_identity_authapi_base_url();
|
||||
let process_task_id = register_agent_task(
|
||||
&build_reqwest_client(),
|
||||
AGENT_IDENTITY_AUTHAPI_BASE_URL,
|
||||
&agent_identity_authapi_base_url,
|
||||
key(&record),
|
||||
)
|
||||
.await
|
||||
@@ -58,9 +61,80 @@ impl AgentIdentityAuth {
|
||||
}
|
||||
}
|
||||
|
||||
fn agent_identity_authapi_base_url() -> String {
|
||||
env::var(CODEX_AGENT_IDENTITY_AUTHAPI_BASE_URL_ENV_VAR)
|
||||
.ok()
|
||||
.map(|base_url| base_url.trim().trim_end_matches('/').to_string())
|
||||
.filter(|base_url| !base_url.is_empty())
|
||||
.unwrap_or_else(|| PROD_AGENT_IDENTITY_AUTHAPI_BASE_URL.to_string())
|
||||
}
|
||||
|
||||
fn key(record: &AgentIdentityAuthRecord) -> AgentIdentityKey<'_> {
|
||||
AgentIdentityKey {
|
||||
agent_runtime_id: &record.agent_runtime_id,
|
||||
private_key_pkcs8_base64: &record.agent_private_key,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use serial_test::serial;
|
||||
|
||||
#[test]
|
||||
#[serial(agent_identity_authapi_base_url_env)]
|
||||
fn agent_identity_authapi_base_url_prefers_env_value() {
|
||||
let _guard = EnvVarGuard::set(
|
||||
CODEX_AGENT_IDENTITY_AUTHAPI_BASE_URL_ENV_VAR,
|
||||
"https://authapi.example.test/api/accounts/",
|
||||
);
|
||||
assert_eq!(
|
||||
agent_identity_authapi_base_url(),
|
||||
"https://authapi.example.test/api/accounts"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial(agent_identity_authapi_base_url_env)]
|
||||
fn agent_identity_authapi_base_url_uses_prod_authapi_by_default() {
|
||||
let _guard = EnvVarGuard::remove(CODEX_AGENT_IDENTITY_AUTHAPI_BASE_URL_ENV_VAR);
|
||||
assert_eq!(
|
||||
agent_identity_authapi_base_url(),
|
||||
PROD_AGENT_IDENTITY_AUTHAPI_BASE_URL
|
||||
);
|
||||
}
|
||||
|
||||
struct EnvVarGuard {
|
||||
key: &'static str,
|
||||
original: Option<std::ffi::OsString>,
|
||||
}
|
||||
|
||||
impl EnvVarGuard {
|
||||
fn set(key: &'static str, value: &str) -> Self {
|
||||
let original = env::var_os(key);
|
||||
unsafe {
|
||||
env::set_var(key, value);
|
||||
}
|
||||
Self { key, original }
|
||||
}
|
||||
|
||||
fn remove(key: &'static str) -> Self {
|
||||
let original = env::var_os(key);
|
||||
unsafe {
|
||||
env::remove_var(key);
|
||||
}
|
||||
Self { key, original }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for EnvVarGuard {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
match &self.original {
|
||||
Some(value) => env::set_var(self.key, value),
|
||||
None => env::remove_var(self.key),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user