mirror of
https://github.com/openai/codex.git
synced 2026-11-07 20:30:33 +00:00
## Why Gateway OAuth reads and logins previously used only the current provider, preventing clients from authorizing another configured provider without changing the default. ## What changed - Add optional `modelProvider` params to `account/gatewayOAuth/read` and `account/gatewayOAuth/login`, preserving current-provider behavior for omitted or null params and selectors. - Validate explicit providers against current managed policy without changing the default or any thread's provider. - Retain readiness state across providers and send `account/gatewayOAuth/changed` notifications for every configured provider sharing the changed credential. - Update protocol schemas, TypeScript types, Python models, and documentation. ## Testing Add coverage for non-default provider login, retained readiness when alternating providers, notifications for shared credentials without starting login, and legacy TypeScript request compatibility. GitOrigin-RevId: cfd472c322b821fe36b8c133a8de774f4ba48534
69 lines
2.7 KiB
Rust
69 lines
2.7 KiB
Rust
//! Forward OAuth progress for every configured provider sharing the changed grant.
|
|
|
|
use crate::config_manager::ConfigManager;
|
|
use crate::outgoing_message::OutgoingMessageSender;
|
|
use codex_app_server_protocol::GatewayOAuthChangedNotification;
|
|
use codex_app_server_protocol::GatewayOAuthStatus;
|
|
use codex_app_server_protocol::ServerNotification;
|
|
use codex_login::AuthManager;
|
|
use codex_login::GatewayAuthStatus;
|
|
use std::sync::Arc;
|
|
use tokio::sync::broadcast::error::RecvError;
|
|
use tokio_util::task::AbortOnDropHandle;
|
|
|
|
pub(crate) fn status_fields(status: GatewayAuthStatus) -> (GatewayOAuthStatus, Option<String>) {
|
|
match status {
|
|
GatewayAuthStatus::NotReady => (GatewayOAuthStatus::NotReady, None),
|
|
GatewayAuthStatus::Started => (GatewayOAuthStatus::Started, None),
|
|
GatewayAuthStatus::Succeeded => (GatewayOAuthStatus::Succeeded, None),
|
|
GatewayAuthStatus::Failed { message } => (GatewayOAuthStatus::Failed, Some(message)),
|
|
}
|
|
}
|
|
|
|
pub(crate) fn spawn(
|
|
auth_manager: Arc<AuthManager>,
|
|
config_manager: ConfigManager,
|
|
outgoing: Arc<OutgoingMessageSender>,
|
|
) -> AbortOnDropHandle<()> {
|
|
let mut events = codex_login::subscribe_gateway_auth_status(&auth_manager.runtime_config());
|
|
AbortOnDropHandle::new(tokio::spawn(async move {
|
|
loop {
|
|
let change = match events.recv().await {
|
|
Ok(change) => change,
|
|
Err(RecvError::Lagged(_)) => continue,
|
|
Err(RecvError::Closed) => break,
|
|
};
|
|
let Ok(config) = config_manager
|
|
.load_latest_config(/*fallback_cwd*/ None)
|
|
.await
|
|
else {
|
|
continue;
|
|
};
|
|
for (provider_id, provider) in &config.model_providers {
|
|
let Ok(Some(manager)) = codex_model_provider::create_model_provider(
|
|
provider.clone(),
|
|
Some(Arc::clone(&auth_manager)),
|
|
)
|
|
.gateway_auth_manager() else {
|
|
continue;
|
|
};
|
|
if !matches!(manager.oauth_session(), Some(oauth) if oauth.config() == &change.config)
|
|
{
|
|
continue;
|
|
}
|
|
let (status, error) = status_fields(change.status.clone());
|
|
outgoing
|
|
.send_server_notification(ServerNotification::GatewayOAuthChanged(
|
|
GatewayOAuthChangedNotification {
|
|
auth_url: None,
|
|
provider_id: provider_id.clone(),
|
|
status,
|
|
error,
|
|
},
|
|
))
|
|
.await;
|
|
}
|
|
}
|
|
}))
|
|
}
|