From 696273122009a78f5751bd4b14c001a5e84347f0 Mon Sep 17 00:00:00 2001 From: elky Date: Mon, 7 Sep 2026 10:51:24 +0800 Subject: [PATCH] fix(antigravity): restore default OAuth client compatibility --- .env.example | 5 +- .../src/provider/providers/generic.rs | 68 ++++++++++++++++++- 2 files changed, 70 insertions(+), 3 deletions(-) diff --git a/.env.example b/.env.example index e9aba1428..5bbbd62a1 100644 --- a/.env.example +++ b/.env.example @@ -111,8 +111,9 @@ ADMIN_USERNAME=admin123456 # AETHER_BARK_ALLOW_HTTP=false # AETHER_BARK_ALLOW_PRIVATE_TARGETS=false -# 可选 Provider OAuth 客户端。使用 Gemini CLI / Antigravity 浏览器授权时必须配置 -# 对应的 client secret;client ID 未配置时使用内置的公开 native-app client ID。 +# 可选 Provider OAuth 客户端。Gemini CLI 授权及刷新必须配置 client secret。 +# Antigravity 默认使用内置 native-app 客户端凭据;自定义 client ID 时必须同时配置 +# 对应的 client secret。未配置 client ID 时使用内置的公开 native-app client ID。 # AETHER_GEMINI_CLI_OAUTH_CLIENT_ID= # AETHER_GEMINI_CLI_OAUTH_CLIENT_SECRET= # AETHER_ANTIGRAVITY_OAUTH_CLIENT_ID= diff --git a/crates/aether-oauth/src/provider/providers/generic.rs b/crates/aether-oauth/src/provider/providers/generic.rs index 943ba3e31..e51be4454 100644 --- a/crates/aether-oauth/src/provider/providers/generic.rs +++ b/crates/aether-oauth/src/provider/providers/generic.rs @@ -238,7 +238,22 @@ impl GenericProviderOAuthAdapter { return required_client_secret(env_name, non_empty_owned(value)).map(Some); } - required_client_secret(env_name, non_empty_environment_value(env_name)).map(Some) + let configured = non_empty_environment_value(env_name); + self.resolve_client_secret(configured).map(Some) + } + + fn resolve_client_secret(&self, configured: Option) -> Result { + let configured = configured.or_else(|| { + (self.template.provider_type == "antigravity" + && self.client_id() == self.template.client_id) + .then(|| "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".to_string()) + }); + required_client_secret( + self.template + .client_secret_env + .unwrap_or(ANTIGRAVITY_OAUTH_CLIENT_SECRET_ENV), + configured, + ) } async fn exchange_grant( @@ -957,6 +972,57 @@ mod tests { ); } + #[tokio::test] + async fn antigravity_default_credentials_support_authorization_and_refresh() { + let mut template = template_for_provider_type("antigravity").expect("template"); + template.client_id_env = None; + template.client_secret_env = Some("AETHER_TEST_UNUSED_ANTIGRAVITY_SECRET"); + let adapter = GenericProviderOAuthAdapter::new(template); + let ctx = transport_context("antigravity"); + adapter + .build_authorize_url(&ctx, "state", None) + .expect("authorize"); + let seen_request = Arc::new(Mutex::new(None)); + let executor = StaticExecutor { + seen_request: Arc::clone(&seen_request), + response_payload: json!({"access_token": "new-token", "expires_in": 3600}), + }; + adapter + .refresh(&executor, &ctx, &oauth_account("antigravity")) + .await + .expect("refresh"); + let seen = seen_request.lock().expect("lock").clone().expect("request"); + let body = seen.body_bytes.expect("body"); + let fields = url::form_urlencoded::parse(&body) + .into_owned() + .collect::>(); + assert_eq!(fields["client_id"], template.client_id); + assert_eq!( + fields["client_secret"], + adapter.resolve_client_secret(None).expect("default") + ); + assert_eq!(fields["refresh_token"], "old-refresh-token"); + assert!(!format!("{adapter:?}").contains(&fields["client_secret"])); + } + + #[test] + fn antigravity_custom_client_requires_its_own_secret() { + let adapter = GenericProviderOAuthAdapter::for_provider_type("antigravity") + .expect("adapter") + .with_oauth_credentials_for_tests("custom-client", "custom-secret"); + assert!(adapter.resolve_client_secret(None).is_err()); + assert_eq!( + adapter + .resolve_client_secret(Some("custom-secret".to_string())) + .expect("configured secret"), + "custom-secret" + ); + assert_eq!( + adapter.client_secret().expect("override"), + Some("custom-secret".to_string()) + ); + } + #[test] fn generic_adapter_debug_redacts_oauth_credentials() { let adapter = GenericProviderOAuthAdapter::for_provider_type("gemini_cli")