Isolate MCP OAuth credentials by environment (#36310)

## Why

MCP servers running in an executor must not reuse host-owned OAuth credentials,
even when they have the same configured server name and URL.

## What changed

- Derive environment-scoped credential names for executor-owned MCP servers and
  use them consistently for login, logout, authentication, and connection setup.
- Mark executor-owned entries in the file credential store and fail closed when
  loading or saving an entry could cross the host/executor boundary.
- Preserve compatibility with existing local OAuth credentials, including local
  server names that overlap the new reserved prefixes.

## Testing

- Extend the executor MCP integration test to verify that executor requests use
  the executor token, never send the host token, and persist both credentials
  separately.

GitOrigin-RevId: 4fc92d0533b0fe2e0df34f6d47b81e3d20d07807
This commit is contained in:
jif
2026-07-31 11:23:46 +00:00
committed by copyberry
parent 5e8b22488f
commit 164b3bfeab
12 changed files with 194 additions and 39 deletions
+4 -2
View File
@@ -517,9 +517,10 @@ async fn run_login(config: &Config, login_args: LoginArgs) -> Result<()> {
};
let resolved_scopes =
resolve_oauth_scopes(explicit_scopes, server.scopes.clone(), discovered_scopes);
let credential_name = server.oauth_credential_name(&name);
perform_oauth_login_retry_without_scopes(
&name,
credential_name.as_ref(),
&url,
config.mcp_oauth_credentials_store_mode,
config.auth_keyring_backend_kind(),
@@ -551,9 +552,10 @@ async fn run_logout(config: &Config, logout_args: LogoutArgs) -> Result<()> {
McpServerTransportConfig::StreamableHttp { url, .. } => url.clone(),
_ => bail!("OAuth logout is only supported for streamable_http transports."),
};
let credential_name = server.oauth_credential_name(&name);
match delete_oauth_tokens(
&name,
credential_name.as_ref(),
&url,
config.mcp_oauth_credentials_store_mode,
config.auth_keyring_backend_kind(),