mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
Preserve ChatGPT auth for trusted staging MCP servers (#36983)
## What changed - Treat an MCP server as trusted for ChatGPT authentication when its origin matches the configured HTTPS `chatgpt-staging.com` host or one of its subdomains. - Continue trusting the production ChatGPT origin and falling back to OAuth for other transports and origins. ## Testing - Cover both the staging apex domain and a staging subdomain. GitOrigin-RevId: 1b1d06ab214141d39eb38d46de9dfb74e6fedb3e
This commit is contained in:
1 parent
b9ba969f39
commit
bf05737da4
2 files changed
+52
-13
No files matched your search
@@ -269,6 +269,38 @@ pub fn effective_mcp_servers(
|
|||||||
effective_mcp_servers_from_configured(configured_mcp_servers(config), config, auth)
|
effective_mcp_servers_from_configured(configured_mcp_servers(config), config, auth)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_trusted_chatgpt_mcp_server(
|
||||||
|
transport: &McpServerTransportConfig,
|
||||||
|
chatgpt_base_url: &str,
|
||||||
|
) -> bool {
|
||||||
|
let McpServerTransportConfig::StreamableHttp { url, .. } = transport else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
let Ok(server_url) = url::Url::parse(url) else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
if !matches!(server_url.scheme(), "http" | "https") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if url::Url::parse(CHATGPT_CODEX_BASE_URL)
|
||||||
|
.ok()
|
||||||
|
.is_some_and(|chatgpt_url| server_url.origin() == chatgpt_url.origin())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
url::Url::parse(chatgpt_base_url)
|
||||||
|
.ok()
|
||||||
|
.is_some_and(|staging_url| {
|
||||||
|
staging_url.scheme() == "https"
|
||||||
|
&& staging_url.domain().is_some_and(|host| {
|
||||||
|
host == "chatgpt-staging.com" || host.ends_with(".chatgpt-staging.com")
|
||||||
|
})
|
||||||
|
&& server_url.origin() == staging_url.origin()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Converts a materialized server map to its auth-gated runtime view.
|
/// Converts a materialized server map to its auth-gated runtime view.
|
||||||
///
|
///
|
||||||
/// Compatibility built-ins and extension overlays must already be reflected in
|
/// Compatibility built-ins and extension overlays must already be reflected in
|
||||||
@@ -278,24 +310,12 @@ pub fn effective_mcp_servers_from_configured(
|
|||||||
config: &McpConfig,
|
config: &McpConfig,
|
||||||
auth: Option<&CodexAuth>,
|
auth: Option<&CodexAuth>,
|
||||||
) -> HashMap<String, EffectiveMcpServer> {
|
) -> HashMap<String, EffectiveMcpServer> {
|
||||||
let chatgpt_origin = url::Url::parse(CHATGPT_CODEX_BASE_URL)
|
|
||||||
.ok()
|
|
||||||
.map(|url| url.origin());
|
|
||||||
let mut servers = configured_servers
|
let mut servers = configured_servers
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(name, mut server)| {
|
.map(|(name, mut server)| {
|
||||||
match server.auth.clone() {
|
match server.auth.clone() {
|
||||||
McpServerAuth::ChatGpt => {
|
McpServerAuth::ChatGpt => {
|
||||||
let server_origin = match &server.transport {
|
if !is_trusted_chatgpt_mcp_server(&server.transport, &config.chatgpt_base_url) {
|
||||||
McpServerTransportConfig::StreamableHttp { url, .. } => {
|
|
||||||
url::Url::parse(url)
|
|
||||||
.ok()
|
|
||||||
.filter(|url| matches!(url.scheme(), "http" | "https"))
|
|
||||||
.map(|url| url.origin())
|
|
||||||
}
|
|
||||||
McpServerTransportConfig::Stdio { .. } => None,
|
|
||||||
};
|
|
||||||
if server_origin.as_ref() != chatgpt_origin.as_ref() {
|
|
||||||
server.auth = McpServerAuth::OAuth;
|
server.auth = McpServerAuth::OAuth;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -362,6 +362,25 @@ fn codex_apps_server_config_forwards_originator_and_configured_product_sku_heade
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn effective_mcp_servers_preserve_chatgpt_auth_for_staging() {
|
||||||
|
for url in [
|
||||||
|
"https://chatgpt-staging.com",
|
||||||
|
"https://preview.chatgpt-staging.com",
|
||||||
|
] {
|
||||||
|
let mut config = test_mcp_config(PathBuf::new());
|
||||||
|
config.chatgpt_base_url = url.to_string();
|
||||||
|
let server = codex_apps_mcp_server_config(
|
||||||
|
url, /*apps_mcp_product_sku*/ None, /*originator*/ None,
|
||||||
|
);
|
||||||
|
let configured = HashMap::from([("staging".to_string(), server)]);
|
||||||
|
let effective =
|
||||||
|
effective_mcp_servers_from_configured(configured, &config, /*auth*/ None);
|
||||||
|
|
||||||
|
assert_eq!(effective["staging"].config().auth, McpServerAuth::ChatGpt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn effective_mcp_servers_preserve_runtime_servers() {
|
async fn effective_mcp_servers_preserve_runtime_servers() {
|
||||||
let codex_home = tempfile::tempdir().expect("tempdir");
|
let codex_home = tempfile::tempdir().expect("tempdir");
|
||||||
|
|||||||
Reference in new issue
Block a user