mirror of
https://github.com/openai/codex.git
synced 2026-11-07 20:30:33 +00:00
Apply runtime authentication to realtime connections (#60003)
## Why Realtime connections bypassed runtime authentication and reused captured authentication headers for sideband handshakes. They need to honor the selected credential source and its transport policy across call creation, retries, and reconnects. ## What changed - Use runtime authentication for realtime WebSocket connections, WebRTC call creation, and sideband attachment when enabled for supported OpenAI destinations. - Resolve authentication on every WebSocket handshake, preserving credential ownership and request scope while generating fresh assertions. Reject authentication failures without falling back to bearer authentication. - Keep call creation and sideband attachment bound to the selected credentials and account network policy, including when inference uses a different provider. - Avoid runtime initialization for local marketplace and MCP operations, plugin commands that do not use the remote catalog, and model debugging with a configured catalog. ## Testing Add coverage for fresh handshake credentials on retries and reconnects, credential and account changes, runtime authentication modes, destination validation, and registration failures. GitOrigin-RevId: 57e53122912fa78a524427b0f51013f76f9f7681
This commit is contained in:
@@ -2189,9 +2189,10 @@ async fn run_debug_models_command(
|
||||
.await?;
|
||||
let auth_manager =
|
||||
AuthManager::shared_from_config(&config, /*enable_codex_api_key_env*/ true).await?;
|
||||
let runtime_auth = if config
|
||||
.features
|
||||
.enabled(codex_features::Feature::RuntimeAgentInstances)
|
||||
let runtime_auth = if config.model_catalog.is_none()
|
||||
&& config
|
||||
.features
|
||||
.enabled(codex_features::Feature::RuntimeAgentInstances)
|
||||
{
|
||||
let installation_id = codex_core::resolve_installation_id(&config.codex_home).await?;
|
||||
codex_core::build_runtime_auth_manager(
|
||||
|
||||
@@ -5,7 +5,7 @@ use clap::Parser;
|
||||
use codex_core::config::Config;
|
||||
use codex_core::config::ConfigOverrides;
|
||||
use codex_core::config::LoaderOverrides;
|
||||
use codex_core::plugins_manager_for_config_with_runtime;
|
||||
use codex_core::plugins_manager_for_config;
|
||||
use codex_core_plugins::PluginMarketplaceUpgradeOutcome;
|
||||
use codex_core_plugins::PluginsConfigInput;
|
||||
use codex_core_plugins::installed_marketplaces::marketplace_install_root;
|
||||
@@ -211,9 +211,7 @@ impl JsonMarketplaceAddOutput {
|
||||
}
|
||||
|
||||
async fn run_list(config: Config, args: ListMarketplaceArgs) -> Result<()> {
|
||||
let manager =
|
||||
plugins_manager_for_config_with_runtime(&config, load_cli_auth_manager(&config).await?)
|
||||
.await?;
|
||||
let manager = plugins_manager_for_config(&config, load_cli_auth_manager(&config).await?);
|
||||
let plugins_input = config.plugins_config_input();
|
||||
let marketplace_listing = manager
|
||||
.discover_marketplaces_for_config(&plugins_input, &[])
|
||||
@@ -375,9 +373,7 @@ async fn run_upgrade(
|
||||
marketplace_name,
|
||||
json,
|
||||
} = args;
|
||||
let manager =
|
||||
plugins_manager_for_config_with_runtime(&config, load_cli_auth_manager(&config).await?)
|
||||
.await?;
|
||||
let manager = plugins_manager_for_config(&config, load_cli_auth_manager(&config).await?);
|
||||
let plugins_input = config.plugins_config_input();
|
||||
let runtime = tokio::runtime::Handle::current();
|
||||
let reload_config: codex_core_plugins::ConfigLayerReload = std::sync::Arc::new(move || {
|
||||
|
||||
@@ -19,7 +19,7 @@ use codex_core::config::LoaderOverrides;
|
||||
use codex_core::config::edit::ConfigEditsBuilder;
|
||||
use codex_core::config::find_codex_home;
|
||||
use codex_core::config::load_global_mcp_servers;
|
||||
use codex_core::plugins_manager_for_config_with_runtime;
|
||||
use codex_core::plugins_manager_for_config;
|
||||
use codex_exec_server::EnvironmentManager;
|
||||
use codex_exec_server::HttpClient;
|
||||
use codex_exec_server::RouteAwareHttpClient;
|
||||
@@ -48,7 +48,6 @@ use codex_utils_redacted_string::RedactedString;
|
||||
use crate::cloud_config;
|
||||
use crate::mcp_login::McpLoginMode;
|
||||
use crate::mcp_login::perform_oauth_login_retry_without_scopes;
|
||||
use crate::plugin_cmd::load_cli_auth_manager;
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "mcp_cmd_tests.rs"]
|
||||
@@ -533,10 +532,10 @@ async fn run_remove(config_overrides: &CliConfigOverrides, remove_args: RemoveAr
|
||||
}
|
||||
|
||||
async fn load_mcp_manager(config: &Config) -> Result<McpManager> {
|
||||
let plugins_manager = Arc::new(
|
||||
plugins_manager_for_config_with_runtime(config, load_cli_auth_manager(config).await?)
|
||||
.await?,
|
||||
);
|
||||
let plugins_manager = Arc::new(plugins_manager_for_config(
|
||||
config,
|
||||
AuthManager::shared_from_config(config, /*enable_codex_api_key_env*/ true).await?,
|
||||
));
|
||||
Ok(McpManager::new(plugins_manager))
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ use codex_app_server_protocol::PluginAuthPolicy;
|
||||
use codex_app_server_protocol::PluginInstallPolicy;
|
||||
use codex_core::config::Config;
|
||||
use codex_core::config::find_codex_home;
|
||||
use codex_core::plugins_manager_for_config;
|
||||
use codex_core::plugins_manager_for_config_with_runtime;
|
||||
use codex_core_plugins::ConfiguredMarketplace;
|
||||
use codex_core_plugins::OPENAI_BUNDLED_MARKETPLACE_NAME;
|
||||
@@ -140,13 +141,13 @@ pub async fn run_plugin_add(
|
||||
overrides: Vec<(String, toml::Value)>,
|
||||
args: AddPluginArgs,
|
||||
) -> Result<()> {
|
||||
let context = load_plugin_command_context(overrides).await?;
|
||||
let AddPluginArgs {
|
||||
plugin,
|
||||
marketplace_name,
|
||||
json,
|
||||
} = args;
|
||||
let selection = parse_plugin_selection(plugin, marketplace_name)?;
|
||||
let context = load_plugin_command_context(overrides, Some(&selection.marketplace_name)).await?;
|
||||
let outcome = if selection.marketplace_name == REMOTE_GLOBAL_MARKETPLACE_NAME {
|
||||
let mut listing = fetch_remote_marketplaces(
|
||||
&context,
|
||||
@@ -247,7 +248,7 @@ pub async fn run_plugin_list(
|
||||
overrides: Vec<(String, toml::Value)>,
|
||||
args: ListPluginsArgs,
|
||||
) -> Result<()> {
|
||||
let context = load_plugin_command_context(overrides).await?;
|
||||
let context = load_plugin_command_context(overrides, args.marketplace_name.as_deref()).await?;
|
||||
let remote_listing = fetch_remote_marketplaces(
|
||||
&context,
|
||||
args.marketplace_name.as_deref(),
|
||||
@@ -682,13 +683,13 @@ pub async fn run_plugin_remove(
|
||||
overrides: Vec<(String, toml::Value)>,
|
||||
args: RemovePluginArgs,
|
||||
) -> Result<()> {
|
||||
let context = load_plugin_command_context(overrides).await?;
|
||||
let RemovePluginArgs {
|
||||
plugin,
|
||||
marketplace_name,
|
||||
json,
|
||||
} = args;
|
||||
let selection = parse_plugin_selection(plugin, marketplace_name)?;
|
||||
let context = load_plugin_command_context(overrides, Some(&selection.marketplace_name)).await?;
|
||||
|
||||
if selection.marketplace_name == REMOTE_GLOBAL_MARKETPLACE_NAME {
|
||||
ensure!(
|
||||
@@ -766,6 +767,7 @@ struct PluginCommandContext {
|
||||
|
||||
async fn load_plugin_command_context(
|
||||
overrides: Vec<(String, toml::Value)>,
|
||||
marketplace_name: Option<&str>,
|
||||
) -> Result<PluginCommandContext> {
|
||||
let codex_home = find_codex_home().context("failed to resolve CODEX_HOME")?;
|
||||
let config = Config::load_with_cli_overrides(overrides)
|
||||
@@ -773,14 +775,20 @@ async fn load_plugin_command_context(
|
||||
.context("failed to load configuration")?;
|
||||
let plugins_input = config.plugins_config_input();
|
||||
let auth_manager = load_cli_auth_manager(&config).await?;
|
||||
let manager = Arc::new(
|
||||
plugins_manager_for_config_with_runtime(&config, Arc::clone(&auth_manager)).await?,
|
||||
);
|
||||
let auth = auth_manager.auth().await;
|
||||
let uses_remote_catalog = plugins_input.plugins_enabled
|
||||
&& auth.as_ref().is_some_and(CodexAuth::uses_codex_backend)
|
||||
&& marketplace_name.is_none_or(|name| name == REMOTE_GLOBAL_MARKETPLACE_NAME);
|
||||
let manager = Arc::new(if uses_remote_catalog {
|
||||
plugins_manager_for_config_with_runtime(&config, Arc::clone(&auth_manager)).await?
|
||||
} else {
|
||||
plugins_manager_for_config(&config, Arc::clone(&auth_manager))
|
||||
});
|
||||
Ok(PluginCommandContext {
|
||||
codex_home: codex_home.to_path_buf(),
|
||||
plugins_input,
|
||||
manager,
|
||||
auth: auth_manager.auth().await,
|
||||
auth,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user