mirror of
https://github.com/openai/codex.git
synced 2026-11-11 21:10:39 +00:00
Use runtime authentication for OpenAI MCP and app requests (#59749)
## What changed - Select fresh authentication for each HTTP operation on eligible OpenAI MCP connections while preserving the connection's credential source and account network policy. Stop redirects when requests carry runtime assertions. - Pass the owning thread's authentication and runtime context through app discovery, connector metadata, and trusted-access requests. Include the runtime authentication mode in MCP connection and tool-cache identities. - Give resumed actors analytics clients bound to their own authentication context, and serialize stored-credential reloads with token refresh while preserving host-provided credentials. ## Testing Add coverage for fresh request assertions, revoked account policies, redirect handling, resumed-actor isolation, and MCP uploads in dual-header and assertion-only modes. GitOrigin-RevId: f06900a6db61cd6cf53c3aa8075afeec4d5706d9
This commit is contained in:
@@ -1113,6 +1113,7 @@ impl PluginRequestProcessor {
|
||||
None => None,
|
||||
};
|
||||
let app_summaries = load_plugin_app_summaries(
|
||||
&self.thread_manager,
|
||||
&config,
|
||||
auth.as_ref(),
|
||||
&outcome.plugin.apps,
|
||||
@@ -1219,6 +1220,7 @@ impl PluginRequestProcessor {
|
||||
.map(plugin_app_category_by_id_from_value)
|
||||
.unwrap_or_default();
|
||||
let app_summaries = load_plugin_app_summaries(
|
||||
&self.thread_manager,
|
||||
&config,
|
||||
auth.as_ref(),
|
||||
&plugin_apps,
|
||||
@@ -1738,37 +1740,42 @@ impl PluginRequestProcessor {
|
||||
}
|
||||
|
||||
let is_chatgpt_auth = auth.as_ref().is_some_and(CodexAuth::is_chatgpt_auth);
|
||||
let apps_needing_auth = if let Some(app_ids_needing_auth) =
|
||||
installation.app_ids_needing_auth
|
||||
{
|
||||
if app_ids_needing_auth.is_empty()
|
||||
|| !config.features.apps_enabled_for_auth(is_chatgpt_auth)
|
||||
{
|
||||
Vec::new()
|
||||
} else {
|
||||
let plugin_apps = app_ids_needing_auth
|
||||
.into_iter()
|
||||
.map(codex_plugin::AppConnectorId)
|
||||
.collect::<Vec<_>>();
|
||||
let app_category_by_id = remote_detail
|
||||
.app_manifest
|
||||
.as_ref()
|
||||
.map(plugin_app_category_by_id_from_value)
|
||||
.unwrap_or_default();
|
||||
load_plugin_app_summaries(&config, auth.as_ref(), &plugin_apps, &app_category_by_id)
|
||||
let apps_needing_auth =
|
||||
if let Some(app_ids_needing_auth) = installation.app_ids_needing_auth {
|
||||
if app_ids_needing_auth.is_empty()
|
||||
|| !config.features.apps_enabled_for_auth(is_chatgpt_auth)
|
||||
{
|
||||
Vec::new()
|
||||
} else {
|
||||
let plugin_apps = app_ids_needing_auth
|
||||
.into_iter()
|
||||
.map(codex_plugin::AppConnectorId)
|
||||
.collect::<Vec<_>>();
|
||||
let app_category_by_id = remote_detail
|
||||
.app_manifest
|
||||
.as_ref()
|
||||
.map(plugin_app_category_by_id_from_value)
|
||||
.unwrap_or_default();
|
||||
load_plugin_app_summaries(
|
||||
&self.thread_manager,
|
||||
&config,
|
||||
auth.as_ref(),
|
||||
&plugin_apps,
|
||||
&app_category_by_id,
|
||||
)
|
||||
.await
|
||||
}
|
||||
} else {
|
||||
let plugin_app_declarations =
|
||||
load_plugin_apps(result.installed_path.as_path(), &result.plugin_id).await;
|
||||
self.plugin_apps_needing_auth_for_install(
|
||||
&config,
|
||||
auth.as_ref(),
|
||||
&result.plugin_id.as_key(),
|
||||
&plugin_app_declarations,
|
||||
)
|
||||
.await
|
||||
};
|
||||
}
|
||||
} else {
|
||||
let plugin_app_declarations =
|
||||
load_plugin_apps(result.installed_path.as_path(), &result.plugin_id).await;
|
||||
self.plugin_apps_needing_auth_for_install(
|
||||
&config,
|
||||
auth.as_ref(),
|
||||
&result.plugin_id.as_key(),
|
||||
&plugin_app_declarations,
|
||||
)
|
||||
.await
|
||||
};
|
||||
|
||||
Ok(PluginInstallResponse {
|
||||
auth_policy: remote_detail.summary.auth_policy,
|
||||
@@ -1839,7 +1846,13 @@ impl PluginRequestProcessor {
|
||||
.collect();
|
||||
let environment_manager = self.thread_manager.environment_manager();
|
||||
let (app_summaries, accessible_connectors_result) = tokio::join!(
|
||||
load_plugin_app_summaries(config, auth, &plugin_apps, &app_category_by_id),
|
||||
load_plugin_app_summaries(
|
||||
&self.thread_manager,
|
||||
config,
|
||||
auth,
|
||||
&plugin_apps,
|
||||
&app_category_by_id
|
||||
),
|
||||
connectors::list_accessible_connectors_from_mcp_tools_with_mcp_manager(
|
||||
config,
|
||||
/*force_refetch*/ true,
|
||||
@@ -1856,8 +1869,7 @@ impl PluginRequestProcessor {
|
||||
"failed to load accessible apps after plugin install: {err:#}"
|
||||
);
|
||||
(
|
||||
connectors::list_cached_accessible_connectors_from_mcp_tools(config)
|
||||
.await
|
||||
connectors::list_cached_accessible_connectors_from_mcp_tools(config, auth)
|
||||
.unwrap_or_default(),
|
||||
false,
|
||||
)
|
||||
@@ -2159,6 +2171,7 @@ impl PluginRequestProcessor {
|
||||
}
|
||||
|
||||
async fn load_plugin_app_summaries(
|
||||
thread_manager: &ThreadManager,
|
||||
config: &Config,
|
||||
auth: Option<&CodexAuth>,
|
||||
plugin_apps: &[codex_plugin::AppConnectorId],
|
||||
@@ -2185,9 +2198,17 @@ async fn load_plugin_app_summaries(
|
||||
)
|
||||
.fresh_records(&app_ids, /*include_tools*/ false),
|
||||
);
|
||||
let runtime = thread_manager.runtime_auth_for_config(config);
|
||||
for app_ids in app_ids.chunks(APP_READ_MAX_IDS) {
|
||||
let runtime = match &runtime {
|
||||
Ok(runtime) => runtime.as_ref(),
|
||||
Err(error) => {
|
||||
warn!("failed to initialize app metadata authentication: {error}");
|
||||
break;
|
||||
}
|
||||
};
|
||||
match connectors::read_connector_metadata(
|
||||
config, auth, app_ids, /*include_tools*/ false,
|
||||
config, auth, runtime, app_ids, /*include_tools*/ false,
|
||||
)
|
||||
.await
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user