diff --git a/codex-rs/cli/src/lib.rs b/codex-rs/cli/src/lib.rs index 6750cbf39e..5bea8ce78d 100644 --- a/codex-rs/cli/src/lib.rs +++ b/codex-rs/cli/src/lib.rs @@ -10,10 +10,10 @@ use std::path::PathBuf; pub use debug_sandbox::run_command_under_landlock; pub use debug_sandbox::run_command_under_seatbelt; pub use debug_sandbox::run_command_under_windows; -pub use login::read_agent_identity_from_stdin; +pub use login::read_access_token_from_stdin; pub use login::read_api_key_from_stdin; pub use login::run_login_status; -pub use login::run_login_with_agent_identity; +pub use login::run_login_with_access_token; pub use login::run_login_with_api_key; pub use login::run_login_with_chatgpt; pub use login::run_login_with_device_code; diff --git a/codex-rs/cli/src/login.rs b/codex-rs/cli/src/login.rs index 1baa344b8d..16add7ac90 100644 --- a/codex-rs/cli/src/login.rs +++ b/codex-rs/cli/src/login.rs @@ -13,7 +13,7 @@ use codex_core::config::Config; use codex_login::CLIENT_ID; use codex_login::CodexAuth; use codex_login::ServerOptions; -use codex_login::login_with_agent_identity; +use codex_login::login_with_access_token; use codex_login::login_with_api_key; use codex_login::logout_with_revoke; use codex_login::run_device_code_login; @@ -35,8 +35,8 @@ const CHATGPT_LOGIN_DISABLED_MESSAGE: &str = "ChatGPT login is disabled. Use API key login instead."; const API_KEY_LOGIN_DISABLED_MESSAGE: &str = "API key login is disabled. Use ChatGPT login instead."; -const AGENT_IDENTITY_LOGIN_DISABLED_MESSAGE: &str = - "Agent Identity login is disabled. Use API key login instead."; +const ACCESS_TOKEN_LOGIN_DISABLED_MESSAGE: &str = + "Access token login is disabled. Use API key login instead."; const LOGIN_SUCCESS_MESSAGE: &str = "Successfully logged in"; /// Installs a small file-backed tracing layer for direct `codex login` flows. @@ -190,22 +190,22 @@ pub async fn run_login_with_api_key( } } -pub async fn run_login_with_agent_identity( +pub async fn run_login_with_access_token( cli_config_overrides: CliConfigOverrides, - agent_identity: String, + access_token: String, ) -> ! { let config = load_config_or_exit(cli_config_overrides).await; let _login_log_guard = init_login_file_logging(&config); - tracing::info!("starting agent identity login flow"); + tracing::info!("starting access token login flow"); if matches!(config.forced_login_method, Some(ForcedLoginMethod::Api)) { - eprintln!("{AGENT_IDENTITY_LOGIN_DISABLED_MESSAGE}"); + eprintln!("{ACCESS_TOKEN_LOGIN_DISABLED_MESSAGE}"); std::process::exit(1); } - match login_with_agent_identity( + match login_with_access_token( &config.codex_home, - &agent_identity, + &access_token, config.cli_auth_credentials_store_mode, Some(&config.chatgpt_base_url), ) @@ -216,7 +216,7 @@ pub async fn run_login_with_agent_identity( std::process::exit(0); } Err(e) => { - eprintln!("Error logging in with Agent Identity: {e}"); + eprintln!("Error logging in with access token: {e}"); std::process::exit(1); } } @@ -230,11 +230,11 @@ pub fn read_api_key_from_stdin() -> String { ) } -pub fn read_agent_identity_from_stdin() -> String { +pub fn read_access_token_from_stdin() -> String { read_stdin_secret( - "--with-agent-identity expects the Agent Identity token on stdin. Try piping it, e.g. `printenv CODEX_AGENT_IDENTITY | codex login --with-agent-identity`.", - "Reading Agent Identity token from stdin...", - "No Agent Identity token provided via stdin.", + "--with-access-token expects the access token on stdin. Try piping it, e.g. `printenv CODEX_ACCESS_TOKEN | codex login --with-access-token`.", + "Reading access token from stdin...", + "No access token provided via stdin.", ) } @@ -388,7 +388,7 @@ pub async fn run_login_status(cli_config_overrides: CliConfigOverrides) -> ! { std::process::exit(0); } AuthMode::AgentIdentity => { - eprintln!("Logged in using Agent Identity"); + eprintln!("Logged in using access token"); std::process::exit(0); } }, diff --git a/codex-rs/cli/src/main.rs b/codex-rs/cli/src/main.rs index c56055ea2d..48b6886382 100644 --- a/codex-rs/cli/src/main.rs +++ b/codex-rs/cli/src/main.rs @@ -10,10 +10,10 @@ use codex_chatgpt::apply_command::run_apply_command; use codex_cli::LandlockCommand; use codex_cli::SeatbeltCommand; use codex_cli::WindowsCommand; -use codex_cli::read_agent_identity_from_stdin; +use codex_cli::read_access_token_from_stdin; use codex_cli::read_api_key_from_stdin; use codex_cli::run_login_status; -use codex_cli::run_login_with_agent_identity; +use codex_cli::run_login_with_access_token; use codex_cli::run_login_with_api_key; use codex_cli::run_login_with_chatgpt; use codex_cli::run_login_with_device_code; @@ -364,10 +364,10 @@ struct LoginCommand { with_api_key: bool, #[arg( - long = "with-agent-identity", - help = "Read the experimental Agent Identity token from stdin (e.g. `printenv CODEX_AGENT_IDENTITY | codex login --with-agent-identity`)" + long = "with-access-token", + help = "Read the access token from stdin (e.g. `printenv CODEX_ACCESS_TOKEN | codex login --with-access-token`)" )] - with_agent_identity: bool, + with_access_token: bool, #[arg( long = "api-key", @@ -966,9 +966,9 @@ async fn cli_main(arg0_paths: Arg0DispatchPaths) -> anyhow::Result<()> { run_login_status(login_cli.config_overrides).await; } None => { - if login_cli.with_api_key && login_cli.with_agent_identity { + if login_cli.with_api_key && login_cli.with_access_token { eprintln!( - "Choose one login credential source: --with-api-key or --with-agent-identity." + "Choose one login credential source: --with-api-key or --with-access-token." ); std::process::exit(1); } else if login_cli.use_device_code { @@ -986,10 +986,9 @@ async fn cli_main(arg0_paths: Arg0DispatchPaths) -> anyhow::Result<()> { } else if login_cli.with_api_key { let api_key = read_api_key_from_stdin(); run_login_with_api_key(login_cli.config_overrides, api_key).await; - } else if login_cli.with_agent_identity { - let agent_identity = read_agent_identity_from_stdin(); - run_login_with_agent_identity(login_cli.config_overrides, agent_identity) - .await; + } else if login_cli.with_access_token { + let access_token = read_access_token_from_stdin(); + run_login_with_access_token(login_cli.config_overrides, access_token).await; } else { run_login_with_chatgpt(login_cli.config_overrides).await; } diff --git a/codex-rs/cli/tests/login.rs b/codex-rs/cli/tests/login.rs index 7fd9f7af27..e290d05939 100644 --- a/codex-rs/cli/tests/login.rs +++ b/codex-rs/cli/tests/login.rs @@ -51,16 +51,16 @@ fn login_with_api_key_reads_stdin_and_writes_auth_json() -> Result<()> { } #[test] -fn login_with_agent_identity_rejects_invalid_jwt() -> Result<()> { +fn login_with_access_token_rejects_invalid_jwt() -> Result<()> { let codex_home = TempDir::new()?; write_file_auth_config(codex_home.path())?; let mut cmd = codex_command(codex_home.path())?; - cmd.args(["login", "--with-agent-identity"]) + cmd.args(["login", "--with-access-token"]) .write_stdin("not-a-jwt\n") .assert() .failure() - .stderr(contains("Error logging in with Agent Identity")); + .stderr(contains("Error logging in with access token")); Ok(()) } diff --git a/codex-rs/login/src/auth/auth_tests.rs b/codex-rs/login/src/auth/auth_tests.rs index 80ec9d07a4..fe57be06fa 100644 --- a/codex-rs/login/src/auth/auth_tests.rs +++ b/codex-rs/login/src/auth/auth_tests.rs @@ -84,7 +84,7 @@ fn login_with_api_key_overwrites_existing_auth_json() { } #[tokio::test] -async fn login_with_agent_identity_writes_only_token() { +async fn login_with_access_token_writes_only_token() { let dir = tempdir().unwrap(); let auth_path = dir.path().join("auth.json"); let record = agent_identity_record("account-123"); @@ -99,14 +99,14 @@ async fn login_with_agent_identity_writes_only_token() { .await; let chatgpt_base_url = format!("{}/backend-api", server.uri()); - super::login_with_agent_identity( + super::login_with_access_token( dir.path(), &agent_identity, AuthCredentialsStoreMode::File, Some(&chatgpt_base_url), ) .await - .expect("login_with_agent_identity should succeed"); + .expect("login_with_access_token should succeed"); let storage = FileAuthStorage::new(dir.path().to_path_buf()); let auth = storage @@ -123,27 +123,27 @@ async fn login_with_agent_identity_writes_only_token() { } #[tokio::test] -async fn login_with_agent_identity_rejects_invalid_jwt() { +async fn login_with_access_token_rejects_invalid_jwt() { let dir = tempdir().unwrap(); - let err = super::login_with_agent_identity( + let err = super::login_with_access_token( dir.path(), "not-a-jwt", AuthCredentialsStoreMode::File, /*chatgpt_base_url*/ None, ) .await - .expect_err("invalid Agent Identity token should fail"); + .expect_err("invalid access token should fail"); assert_eq!(err.kind(), std::io::ErrorKind::Other); assert!( !get_auth_file(dir.path()).exists(), - "invalid Agent Identity token should not write auth.json" + "invalid access token should not write auth.json" ); } #[tokio::test] -async fn login_with_agent_identity_rejects_unsigned_jwt() { +async fn login_with_access_token_rejects_unsigned_jwt() { let dir = tempdir().unwrap(); let record = agent_identity_record("account-123"); let agent_identity = fake_agent_identity_jwt(&record).expect("fake agent identity"); @@ -156,18 +156,18 @@ async fn login_with_agent_identity_rejects_unsigned_jwt() { .await; let chatgpt_base_url = format!("{}/backend-api", server.uri()); - super::login_with_agent_identity( + super::login_with_access_token( dir.path(), &agent_identity, AuthCredentialsStoreMode::File, Some(&chatgpt_base_url), ) .await - .expect_err("unsigned Agent Identity token should fail"); + .expect_err("unsigned access token should fail"); assert!( !get_auth_file(dir.path()).exists(), - "unsigned Agent Identity token should not write auth.json" + "unsigned access token should not write auth.json" ); server.verify().await; } @@ -176,7 +176,7 @@ async fn login_with_agent_identity_rejects_unsigned_jwt() { #[serial(codex_auth_env)] async fn missing_auth_json_returns_none() { let dir = tempdir().unwrap(); - let _agent_guard = EnvVarGuard::remove(CODEX_AGENT_IDENTITY_ENV_VAR); + let _access_token_guard = remove_access_token_env_var(); let auth = CodexAuth::from_auth_storage( dir.path(), AuthCredentialsStoreMode::File, @@ -191,7 +191,7 @@ async fn missing_auth_json_returns_none() { #[serial(codex_auth_env)] async fn pro_account_with_no_api_key_uses_chatgpt_auth() { let codex_home = tempdir().unwrap(); - let _agent_guard = EnvVarGuard::remove(CODEX_AGENT_IDENTITY_ENV_VAR); + let _access_token_guard = remove_access_token_env_var(); let fake_jwt = write_auth_file( AuthFileParams { openai_api_key: None, @@ -250,7 +250,7 @@ async fn pro_account_with_no_api_key_uses_chatgpt_auth() { #[serial(codex_auth_env)] async fn loads_api_key_from_auth_json() { let dir = tempdir().unwrap(); - let _agent_guard = EnvVarGuard::remove(CODEX_AGENT_IDENTITY_ENV_VAR); + let _access_token_guard = remove_access_token_env_var(); let auth_file = dir.path().join("auth.json"); std::fs::write( auth_file, @@ -324,7 +324,7 @@ async fn unauthorized_recovery_reports_mode_and_step_names() { #[serial(codex_auth_env)] async fn refresh_failure_is_scoped_to_the_matching_auth_snapshot() { let codex_home = tempdir().unwrap(); - let _agent_guard = EnvVarGuard::remove(CODEX_AGENT_IDENTITY_ENV_VAR); + let _access_token_guard = remove_access_token_env_var(); write_auth_file( AuthFileParams { openai_api_key: None, @@ -704,9 +704,13 @@ impl Drop for EnvVarGuard { } } +fn remove_access_token_env_var() -> EnvVarGuard { + EnvVarGuard::remove(CODEX_ACCESS_TOKEN_ENV_VAR) +} + #[tokio::test] #[serial(codex_auth_env)] -async fn load_auth_reads_agent_identity_from_env() { +async fn load_auth_reads_access_token_from_env() { let codex_home = tempdir().unwrap(); let expected_record = agent_identity_record("account-123"); let agent_identity = @@ -727,7 +731,7 @@ async fn load_auth_reads_agent_identity_from_env() { .expect(1) .mount(&server) .await; - let _agent_guard = EnvVarGuard::set(CODEX_AGENT_IDENTITY_ENV_VAR, &agent_identity); + let _access_token_guard = EnvVarGuard::set(CODEX_ACCESS_TOKEN_ENV_VAR, &agent_identity); let chatgpt_base_url = format!("{}/backend-api", server.uri()); let _authapi_guard = @@ -760,7 +764,7 @@ async fn load_auth_keeps_codex_api_key_env_precedence() { let codex_home = tempdir().unwrap(); let record = agent_identity_record("account-123"); let agent_identity = fake_agent_identity_jwt(&record).expect("fake agent identity"); - let _agent_guard = EnvVarGuard::set(CODEX_AGENT_IDENTITY_ENV_VAR, &agent_identity); + let _access_token_guard = EnvVarGuard::set(CODEX_ACCESS_TOKEN_ENV_VAR, &agent_identity); let _api_key_guard = EnvVarGuard::set(CODEX_API_KEY_ENV_VAR, "sk-env"); let auth = super::load_auth( @@ -780,7 +784,7 @@ async fn load_auth_keeps_codex_api_key_env_precedence() { #[serial(codex_auth_env)] async fn enforce_login_restrictions_logs_out_for_method_mismatch() { let codex_home = tempdir().unwrap(); - let _agent_guard = EnvVarGuard::remove(CODEX_AGENT_IDENTITY_ENV_VAR); + let _access_token_guard = remove_access_token_env_var(); login_with_api_key(codex_home.path(), "sk-test", AuthCredentialsStoreMode::File) .expect("seed api key"); @@ -805,7 +809,7 @@ async fn enforce_login_restrictions_logs_out_for_method_mismatch() { #[serial(codex_auth_env)] async fn enforce_login_restrictions_logs_out_for_workspace_mismatch() { let codex_home = tempdir().unwrap(); - let _agent_guard = EnvVarGuard::remove(CODEX_AGENT_IDENTITY_ENV_VAR); + let _access_token_guard = remove_access_token_env_var(); let _jwt = write_auth_file( AuthFileParams { openai_api_key: None, @@ -837,7 +841,7 @@ async fn enforce_login_restrictions_logs_out_for_workspace_mismatch() { #[serial(codex_auth_env)] async fn enforce_login_restrictions_allows_matching_workspace() { let codex_home = tempdir().unwrap(); - let _agent_guard = EnvVarGuard::remove(CODEX_AGENT_IDENTITY_ENV_VAR); + let _access_token_guard = remove_access_token_env_var(); let _jwt = write_auth_file( AuthFileParams { openai_api_key: None, @@ -869,7 +873,7 @@ async fn enforce_login_restrictions_allows_matching_workspace() { async fn enforce_login_restrictions_allows_api_key_if_login_method_not_set_but_forced_chatgpt_workspace_id_is_set() { let codex_home = tempdir().unwrap(); - let _agent_guard = EnvVarGuard::remove(CODEX_AGENT_IDENTITY_ENV_VAR); + let _access_token_guard = remove_access_token_env_var(); login_with_api_key(codex_home.path(), "sk-test", AuthCredentialsStoreMode::File) .expect("seed api key"); @@ -893,7 +897,7 @@ async fn enforce_login_restrictions_allows_api_key_if_login_method_not_set_but_f #[serial(codex_auth_env)] async fn enforce_login_restrictions_blocks_env_api_key_when_chatgpt_required() { let _guard = EnvVarGuard::set(CODEX_API_KEY_ENV_VAR, "sk-env"); - let _agent_guard = EnvVarGuard::remove(CODEX_AGENT_IDENTITY_ENV_VAR); + let _access_token_guard = remove_access_token_env_var(); let codex_home = tempdir().unwrap(); let config = build_config( @@ -1069,7 +1073,7 @@ async fn assert_agent_identity_plan_alias( #[serial(codex_auth_env)] async fn plan_type_maps_known_plan() { let codex_home = tempdir().unwrap(); - let _agent_guard = EnvVarGuard::remove(CODEX_AGENT_IDENTITY_ENV_VAR); + let _access_token_guard = remove_access_token_env_var(); let _jwt = write_auth_file( AuthFileParams { openai_api_key: None, @@ -1097,7 +1101,7 @@ async fn plan_type_maps_known_plan() { #[serial(codex_auth_env)] async fn plan_type_maps_self_serve_business_usage_based_plan() { let codex_home = tempdir().unwrap(); - let _agent_guard = EnvVarGuard::remove(CODEX_AGENT_IDENTITY_ENV_VAR); + let _access_token_guard = remove_access_token_env_var(); let _jwt = write_auth_file( AuthFileParams { openai_api_key: None, @@ -1128,7 +1132,7 @@ async fn plan_type_maps_self_serve_business_usage_based_plan() { #[serial(codex_auth_env)] async fn plan_type_maps_enterprise_cbp_usage_based_plan() { let codex_home = tempdir().unwrap(); - let _agent_guard = EnvVarGuard::remove(CODEX_AGENT_IDENTITY_ENV_VAR); + let _access_token_guard = remove_access_token_env_var(); let _jwt = write_auth_file( AuthFileParams { openai_api_key: None, @@ -1159,7 +1163,7 @@ async fn plan_type_maps_enterprise_cbp_usage_based_plan() { #[serial(codex_auth_env)] async fn plan_type_maps_unknown_to_unknown() { let codex_home = tempdir().unwrap(); - let _agent_guard = EnvVarGuard::remove(CODEX_AGENT_IDENTITY_ENV_VAR); + let _access_token_guard = remove_access_token_env_var(); let _jwt = write_auth_file( AuthFileParams { openai_api_key: None, @@ -1187,7 +1191,7 @@ async fn plan_type_maps_unknown_to_unknown() { #[serial(codex_auth_env)] async fn missing_plan_type_maps_to_unknown() { let codex_home = tempdir().unwrap(); - let _agent_guard = EnvVarGuard::remove(CODEX_AGENT_IDENTITY_ENV_VAR); + let _access_token_guard = remove_access_token_env_var(); let _jwt = write_auth_file( AuthFileParams { openai_api_key: None, diff --git a/codex-rs/login/src/auth/manager.rs b/codex-rs/login/src/auth/manager.rs index 29897db7be..08d4a21c50 100644 --- a/codex-rs/login/src/auth/manager.rs +++ b/codex-rs/login/src/auth/manager.rs @@ -464,7 +464,7 @@ impl ChatgptAuth { pub const OPENAI_API_KEY_ENV_VAR: &str = "OPENAI_API_KEY"; pub const CODEX_API_KEY_ENV_VAR: &str = "CODEX_API_KEY"; -pub const CODEX_AGENT_IDENTITY_ENV_VAR: &str = "CODEX_AGENT_IDENTITY"; +pub const CODEX_ACCESS_TOKEN_ENV_VAR: &str = "CODEX_ACCESS_TOKEN"; pub fn read_openai_api_key_from_env() -> Option { env::var(OPENAI_API_KEY_ENV_VAR) @@ -474,14 +474,15 @@ pub fn read_openai_api_key_from_env() -> Option { } pub fn read_codex_api_key_from_env() -> Option { - env::var(CODEX_API_KEY_ENV_VAR) - .ok() - .map(|value| value.trim().to_string()) - .filter(|value| !value.is_empty()) + read_non_empty_env_var(CODEX_API_KEY_ENV_VAR) } -pub fn read_codex_agent_identity_from_env() -> Option { - env::var(CODEX_AGENT_IDENTITY_ENV_VAR) +pub fn read_codex_access_token_from_env() -> Option { + read_non_empty_env_var(CODEX_ACCESS_TOKEN_ENV_VAR) +} + +fn read_non_empty_env_var(key: &str) -> Option { + env::var(key) .ok() .map(|value| value.trim().to_string()) .filter(|value| !value.is_empty()) @@ -540,10 +541,10 @@ pub fn login_with_api_key( save_auth(codex_home, &auth_dot_json, auth_credentials_store_mode) } -/// Writes an `auth.json` that contains only the Agent Identity token. -pub async fn login_with_agent_identity( +/// Writes an `auth.json` that contains only the access token. +pub async fn login_with_access_token( codex_home: &Path, - agent_identity: &str, + access_token: &str, auth_credentials_store_mode: AuthCredentialsStoreMode, chatgpt_base_url: Option<&str>, ) -> std::io::Result<()> { @@ -551,13 +552,13 @@ pub async fn login_with_agent_identity( .unwrap_or(DEFAULT_CHATGPT_BACKEND_BASE_URL) .trim_end_matches('/') .to_string(); - verified_agent_identity_record(agent_identity, &base_url).await?; + verified_agent_identity_record(access_token, &base_url).await?; let auth_dot_json = AuthDotJson { auth_mode: Some(ApiAuthMode::AgentIdentity), openai_api_key: None, tokens: None, last_refresh: None, - agent_identity: Some(agent_identity.to_string()), + agent_identity: Some(access_token.to_string()), }; save_auth(codex_home, &auth_dot_json, auth_credentials_store_mode) } @@ -753,7 +754,7 @@ async fn load_auth( return Ok(None); } - if let Some(agent_identity) = read_codex_agent_identity_from_env() { + if let Some(agent_identity) = read_codex_access_token_from_env() { return CodexAuth::from_agent_identity_jwt(&agent_identity, chatgpt_base_url) .await .map(Some); diff --git a/codex-rs/login/src/lib.rs b/codex-rs/login/src/lib.rs index 3049b6f6bc..990cf8b80e 100644 --- a/codex-rs/login/src/lib.rs +++ b/codex-rs/login/src/lib.rs @@ -22,7 +22,7 @@ pub use auth::AuthDotJson; pub use auth::AuthManager; pub use auth::AuthManagerConfig; pub use auth::CLIENT_ID; -pub use auth::CODEX_AGENT_IDENTITY_ENV_VAR; +pub use auth::CODEX_ACCESS_TOKEN_ENV_VAR; pub use auth::CODEX_API_KEY_ENV_VAR; pub use auth::CodexAuth; pub use auth::ExternalAuth; @@ -38,11 +38,11 @@ pub use auth::UnauthorizedRecovery; pub use auth::default_client; pub use auth::enforce_login_restrictions; pub use auth::load_auth_dot_json; -pub use auth::login_with_agent_identity; +pub use auth::login_with_access_token; pub use auth::login_with_api_key; pub use auth::logout; pub use auth::logout_with_revoke; -pub use auth::read_codex_agent_identity_from_env; +pub use auth::read_codex_access_token_from_env; pub use auth::read_openai_api_key_from_env; pub use auth::save_auth; pub use auth_env_telemetry::AuthEnvTelemetry;