mirror of
https://github.com/openai/codex.git
synced 2026-09-06 15:29:32 +00:00
[Codex Thread 019f2408-dc59-79f2-b245-4c11debd1a61](https://codex-thread-link.openai.chatgpt-team.site/thread/019f2408-dc59-79f2-b245-4c11debd1a61) ## Why Long-lived Codex sessions can outlive the ChatGPT bearer token that was present when the MCP runtime started. The Responses path already recovers from token expiration by refreshing or reloading the shared `AuthManager`. The reserved `codex_apps` hosted-plugin client did not observe that update: `McpConnectionManager` built its `/ps/mcp` HTTP auth once from a `CodexAuth` snapshot, and `auth_provider_from_auth` copied that snapshot bearer into a static `BearerAuthProvider`. After the copied bearer expired, `/ps/mcp` kept sending it even though Responses had a newer token in the same `AuthManager`. The failure occurred before downstream connector execution, so unrelated apps such as Gmail, Slack, and Google Calendar could all fail with the same transport-level `401 token_expired`. This replaces [openai/codex#29474](https://github.com/openai/codex/pull/29474), which was closed for inactivity without being merged. A new long-lived-session report reproduced the same simultaneous `/ps/mcp` expiry pattern across unrelated apps. ## What changed - Add an `AuthManager`-backed request-header provider in `codex-model-provider`. It keeps an `Arc<AuthManager>` and reads `auth_cached()` for each outbound request, so the next `/ps/mcp` call sees a token refreshed by the existing Responses/auth-recovery flow. - Scope that provider to the startup account, ChatGPT user, and workspace identity. Same-identity token reloads are followed; an account switch emits no ambient auth until account-scoped MCP state is rebuilt. - Have `McpConnectionManager` construct the dynamic provider only for the reserved `codex_apps` registration used by the hosted-plugin `/ps/mcp` path. | MCP path | Auth behavior after this change | | --- | --- | | Reserved `codex_apps` hosted-plugin `/ps/mcp` | Read current same-identity auth from the shared `AuthManager` per request | | `codex_apps` with `CODEX_CONNECTORS_TOKEN` | Keep the environment bearer-token override | | User-configured/direct MCP registrations | Keep their existing configured auth path | ## Non-goals - No plugin-service changes. - No downstream Slack, Gmail, Calendar, or other connector OAuth/link-refresh changes. - No auth UI changes. - No behavior change for user-configured/direct MCP registrations. - No new `/ps/mcp`-initiated token refresh; this makes `/ps/mcp` observe refreshes already performed through the shared `AuthManager`. ## Tests - `just test -p codex-model-provider` - Covers same-identity token reloads and refuses a changed startup identity. - `just test -p codex-mcp` - `just test -p codex-core mcp_auth_refresh` - Creates the reserved hosted-plugin `codex_apps` `/ps/mcp` client before the shared `AuthManager` changes, updates that same manager through its public external-auth path, performs a real `tools/call`, and asserts the request uses the current bearer.
145 lines
3.6 KiB
Rust
145 lines
3.6 KiB
Rust
// Aggregates all former standalone integration tests as modules.
|
|
use codex_apply_patch::CODEX_CORE_APPLY_PATCH_ARG1;
|
|
use codex_exec_server::CODEX_FS_HELPER_ARG1;
|
|
use codex_sandboxing::landlock::CODEX_LINUX_SANDBOX_ARG0;
|
|
use codex_test_binary_support::TestBinaryDispatchGuard;
|
|
use codex_test_binary_support::TestBinaryDispatchMode;
|
|
use codex_test_binary_support::configure_test_binary_dispatch;
|
|
use ctor::ctor;
|
|
|
|
// This code runs before any other tests are run.
|
|
// It allows the test binary to behave like codex and dispatch to apply_patch and codex-linux-sandbox
|
|
// based on the arg0.
|
|
// NOTE: this doesn't work on ARM
|
|
#[ctor]
|
|
pub static CODEX_ALIASES_TEMP_DIR: Option<TestBinaryDispatchGuard> = {
|
|
configure_test_binary_dispatch("codex-core-tests", |exe_name, argv1| {
|
|
if argv1 == Some(CODEX_CORE_APPLY_PATCH_ARG1) {
|
|
return TestBinaryDispatchMode::DispatchArg0Only;
|
|
}
|
|
if argv1 == Some(CODEX_FS_HELPER_ARG1) {
|
|
return TestBinaryDispatchMode::DispatchArg0Only;
|
|
}
|
|
if exe_name == CODEX_LINUX_SANDBOX_ARG0 {
|
|
return TestBinaryDispatchMode::DispatchArg0Only;
|
|
}
|
|
TestBinaryDispatchMode::InstallAliases
|
|
})
|
|
};
|
|
|
|
#[cfg(not(target_os = "windows"))]
|
|
mod abort_tasks;
|
|
mod additional_context;
|
|
mod agent_execution;
|
|
mod agent_jobs;
|
|
mod agent_websocket;
|
|
mod agents_md;
|
|
mod apply_patch_cli;
|
|
#[cfg(not(target_os = "windows"))]
|
|
mod approvals;
|
|
mod auto_review;
|
|
mod cli_stream;
|
|
mod client;
|
|
mod client_websockets;
|
|
mod code_mode;
|
|
mod code_mode_elicitation;
|
|
mod codex_delegate;
|
|
mod collaboration_instructions;
|
|
mod compact;
|
|
mod compact_remote;
|
|
mod compact_remote_parity;
|
|
mod compact_resume_fork;
|
|
mod current_time_reminder;
|
|
mod deprecation_notice;
|
|
mod exec;
|
|
mod exec_policy;
|
|
#[cfg(not(target_os = "windows"))]
|
|
mod extension_sandbox;
|
|
mod external_auth;
|
|
mod fork_thread;
|
|
#[cfg(not(target_os = "windows"))]
|
|
mod guardian_review;
|
|
#[cfg(not(target_os = "windows"))]
|
|
mod hooks;
|
|
#[cfg(not(target_os = "windows"))]
|
|
mod hooks_mcp;
|
|
mod image_rollout;
|
|
mod items;
|
|
mod json_result;
|
|
mod live_cli;
|
|
mod mcp_auth_elicitation;
|
|
mod mcp_auth_refresh;
|
|
#[cfg(unix)]
|
|
mod mcp_refresh_cleanup;
|
|
mod mcp_tool_exposure;
|
|
mod mcp_turn_metadata;
|
|
mod model_overrides;
|
|
mod model_runtime_selectors;
|
|
mod model_switching;
|
|
mod model_visible_layout;
|
|
mod models_cache_ttl;
|
|
mod models_etag_responses;
|
|
mod multi_agent_mode;
|
|
mod network_approval;
|
|
mod openai_file_mcp;
|
|
mod otel;
|
|
mod override_updates;
|
|
mod pending_input;
|
|
mod permissions_messages;
|
|
mod personality;
|
|
mod personality_migration;
|
|
mod plugins;
|
|
mod prompt_caching;
|
|
mod prompt_debug_tests;
|
|
mod quota_exceeded;
|
|
mod realtime_conversation;
|
|
mod remote_env;
|
|
mod remote_models;
|
|
mod request_compression;
|
|
#[cfg(not(target_os = "windows"))]
|
|
mod request_permissions;
|
|
#[cfg(not(target_os = "windows"))]
|
|
mod request_permissions_tool;
|
|
mod request_plugin_install;
|
|
mod request_user_input;
|
|
mod responses_api_proxy_headers;
|
|
mod responses_lite;
|
|
mod resume;
|
|
mod resume_warning;
|
|
mod review;
|
|
mod rmcp_client;
|
|
mod rollout_budget;
|
|
mod rollout_list_find;
|
|
mod safety_buffering;
|
|
mod safety_check_downgrade;
|
|
mod search_tool;
|
|
mod shell_command;
|
|
mod shell_serialization;
|
|
mod shell_snapshot;
|
|
mod skill_approval;
|
|
mod skills;
|
|
mod spawn_agent_description;
|
|
mod sqlite_state;
|
|
mod stream_error_allows_next_turn;
|
|
mod stream_no_completed;
|
|
mod subagent_notifications;
|
|
mod token_budget;
|
|
mod tool_harness;
|
|
mod tool_parallelism;
|
|
mod tools;
|
|
mod truncation;
|
|
mod turn_state;
|
|
mod unified_exec;
|
|
mod unified_exec_process_events;
|
|
#[cfg(unix)]
|
|
mod unified_exec_zsh_fork_approvals;
|
|
mod unstable_features_warning;
|
|
mod user_notification;
|
|
mod user_shell_cmd;
|
|
mod view_image;
|
|
mod web_search;
|
|
mod websocket_fallback;
|
|
mod window_headers;
|
|
#[cfg(target_os = "windows")]
|
|
mod windows_sandbox;
|