From 0eb407d20e37a6061a421e0031d8fcf0db015a04 Mon Sep 17 00:00:00 2001 From: Lubrsy706 Date: Thu, 14 May 2026 10:26:34 +0800 Subject: [PATCH] fix(auth): avoid forcing userinfo profile scope --- .../google-workspace-cli/src/auth_commands.rs | 43 +++++++++++++------ 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/crates/google-workspace-cli/src/auth_commands.rs b/crates/google-workspace-cli/src/auth_commands.rs index d7571e74..304d88ad 100644 --- a/crates/google-workspace-cli/src/auth_commands.rs +++ b/crates/google-workspace-cli/src/auth_commands.rs @@ -235,6 +235,14 @@ fn urlencoding(s: &str) -> String { percent_encoding::utf8_percent_encode(s, percent_encoding::NON_ALPHANUMERIC).to_string() } +fn ensure_login_identity_scopes(scopes: &mut Vec) { + for s in LOGIN_IDENTITY_SCOPES { + if !scopes.iter().any(|existing| existing == s) { + scopes.push((*s).to_string()); + } + } +} + /// Mask a secret string by showing only the first 4 and last 4 characters. /// Strings with 8 or fewer characters are fully replaced with "***". /// @@ -279,6 +287,9 @@ pub const MINIMAL_SCOPES: &[&str] = &[ /// have a verified app or a GCP project with the APIs enabled and approved. pub const DEFAULT_SCOPES: &[&str] = MINIMAL_SCOPES; +const LOGIN_IDENTITY_SCOPES: &[&str] = + &["openid", "https://www.googleapis.com/auth/userinfo.email"]; + /// Full scopes — all common Workspace APIs plus GCP platform access. /// /// Use `gws auth login --full` to request these. Unverified OAuth apps will @@ -598,20 +609,9 @@ async fn handle_login_inner( // Remove restrictive scopes when broader alternatives are present. let mut scopes = filter_redundant_restrictive_scopes(scopes); - // Ensure openid + email + profile scopes are always present so we can - // identify the user via the userinfo endpoint after login, and so the - // Gmail helpers can fall back to the People API to populate the From - // display name when the send-as identity lacks one (Workspace accounts). - let identity_scopes = [ - "openid", - "https://www.googleapis.com/auth/userinfo.email", - "https://www.googleapis.com/auth/userinfo.profile", - ]; - for s in &identity_scopes { - if !scopes.iter().any(|existing| existing == s) { - scopes.push(s.to_string()); - } - } + // Ensure the scopes needed to identify the signed-in account are present. + // Avoid forcing userinfo.profile because some OAuth clients cannot request it. + ensure_login_identity_scopes(&mut scopes); // Ensure config directory exists let config = config_dir(); @@ -2481,6 +2481,21 @@ mod tests { assert!(result.is_empty()); } + #[test] + fn ensure_login_identity_scopes_does_not_force_profile_scope() { + let mut scopes = vec!["https://www.googleapis.com/auth/gmail.modify".to_string()]; + + ensure_login_identity_scopes(&mut scopes); + + assert!(scopes.iter().any(|scope| scope == "openid")); + assert!(scopes + .iter() + .any(|scope| scope == "https://www.googleapis.com/auth/userinfo.email")); + assert!(!scopes + .iter() + .any(|scope| scope == "https://www.googleapis.com/auth/userinfo.profile")); + } + #[test] fn build_proxy_auth_url_encodes_scope_and_redirect_uri() { let scopes = vec![