Skip to content

feat(auth): restore multi-account support (fixes #439)#496

Open
dumko2001 wants to merge 7 commits intogoogleworkspace:mainfrom
dumko2001:feat/issue-439-multi-account
Open

feat(auth): restore multi-account support (fixes #439)#496
dumko2001 wants to merge 7 commits intogoogleworkspace:mainfrom
dumko2001:feat/issue-439-multi-account

Conversation

@dumko2001
Copy link

Description

This PR restores multi-account support to the CLI, allowing users to isolate credentials, token caches, and settings (per-account timezones) using a global --account (alias -A) flag.

This addresses the security and auditing needs of AI agents and multi-identity users as requested in #439.

Changes:

  • Account Isolation: Credentials and token caches are saved with account suffixes (e.g., credentials.work.enc).
  • Global Flag: Added --account <name> to the base command surface, enabling multi-account use for all service helpers.
  • Account-Aware Settings: Timezone resolution now correctly caches and isolates values per account.
  • Auth Command Support: Updated auth status, logout, and export to respect the account flag.
  • Test Integrity: Refactored auth.rs tests to ensure perfect isolation using temporary config directories, preventing state leakage and passing with 630+ tests.

Checklist:

  • My code follows the AGENTS.md guidelines (no generated google-* crates).
  • I have run cargo fmt --all to format the code perfectly.
  • I have run cargo clippy -- -D warnings and resolved all warnings.
  • I have added tests that prove my fix is effective or that my feature works.
  • I have provided a Changeset file (.changeset/multi-account-auth.md) to document my changes.

@dumko2001 dumko2001 requested a review from jpoehnelt as a code owner March 15, 2026 06:33
@changeset-bot
Copy link

changeset-bot bot commented Mar 15, 2026

🦋 Changeset detected

Latest commit: 6fed5b8

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@googleworkspace/cli Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@google-cla
Copy link

google-cla bot commented Mar 15, 2026

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request reintroduces and enhances multi-account capabilities within the CLI. It provides a robust mechanism for users to manage multiple Google accounts by isolating their authentication credentials, token caches, and personalized settings. This change significantly improves security and auditing for users managing various identities or AI agents, ensuring that operations are correctly attributed and isolated to the intended account.

Highlights

  • Multi-Account Support: Implemented multi-account authentication, allowing users to isolate credentials, token caches, and settings for different Google accounts using a global --account <name> (alias -A) flag.
  • Credential and Cache Isolation: Credentials and token caches are now saved with account-specific suffixes (e.g., credentials.work.enc, token_cache.work.json), ensuring proper isolation between accounts.
  • Account-Aware Timezone Resolution: Timezone caching and resolution logic has been updated to correctly isolate values per account, preventing cross-account data leakage.
  • Auth Command Updates: The auth status, logout, and export commands have been updated to respect the new --account flag, enabling account-specific operations.
  • Test Suite Refinement: Authentication tests in auth.rs were refactored to use temporary config directories, ensuring robust isolation and preventing state leakage across tests.
Changelog
  • .changeset/multi-account-auth.md
    • Added a new changeset file documenting the implementation of multi-account authentication support.
  • Cargo.lock
    • Updated various dependency versions, including syn, crossterm, darling, instability, itertools, lru, num-conv, ratatui, rustix, strum, time, and unicode-truncate.
  • Cargo.toml
    • Updated the minimum Rust version to 1.87.0.
    • Downgraded the ratatui dependency from 0.30.0 to 0.29.0.
  • src/auth.rs
    • Modified ScopedTokenProvider to include an optional account field, making it account-aware.
    • Updated token_provider to accept an account parameter.
    • Modified get_token to accept an optional account parameter, influencing token cache paths.
    • Refactored load_credentials_inner to accept an optional account parameter, affecting credential file paths.
    • Adjusted test cases to use temporary directories and account parameters for better isolation and accuracy.
  • src/auth_commands.rs
    • Added --account <name> flag to auth login, status, export, and logout commands.
    • Implemented logic to parse the --account flag from command-line arguments.
    • Updated run_login, handle_status, handle_export, and handle_logout functions to accept and utilize the account parameter.
  • src/commands.rs
    • Added a global --account (alias -A) argument to the base CLI command structure, allowing users to specify an account for any command.
  • src/credential_store.rs
    • Modified encrypted_credentials_path to generate account-specific paths for encrypted credentials.
    • Updated save_encrypted and load_encrypted to accept an optional account parameter, enabling account-specific credential storage and retrieval.
  • src/executor.rs
    • Modified handle_json_response to pass the account parameter to the sanitize_text function.
    • Updated execute_method to accept and pass an optional account parameter to relevant sub-functions.
  • src/helpers/calendar.rs
    • Modified handle_calendar_command to retrieve the account from matches and pass it to auth::get_token and resolve_account_timezone.
  • src/helpers/chat.rs
    • Modified handle_chat_command to retrieve the account from matches and pass it to auth::get_token.
  • src/helpers/docs.rs
    • Modified handle_docs_command to retrieve the account from matches and pass it to auth::get_token.
  • src/helpers/drive.rs
    • Modified handle_drive_command to retrieve the account from matches and pass it to auth::get_token.
  • src/helpers/events/renew.rs
    • Modified handle_renew to retrieve the account from matches and pass it to auth::get_token.
  • src/helpers/events/subscribe.rs
    • Modified handle_subscribe to retrieve the account from matches and pass it to auth::token_provider and auth::get_token.
  • src/helpers/gmail/forward.rs
    • Modified handle_forward to retrieve the account from matches and pass it to auth::get_token.
  • src/helpers/gmail/mod.rs
    • Modified send_raw_email to retrieve the account from matches and pass it to auth::get_token.
  • src/helpers/gmail/reply.rs
    • Modified handle_reply to retrieve the account from matches and pass it to auth::get_token.
  • src/helpers/gmail/triage.rs
    • Modified handle_triage to retrieve the account from matches and pass it to auth::get_token.
  • src/helpers/gmail/watch.rs
    • Modified handle_watch to retrieve the account from matches and pass it to auth::token_provider and auth::get_token.
  • src/helpers/modelarmor.rs
    • Modified ModelArmorHelper to retrieve the account from matches and pass it to handle_sanitize and handle_create_template.
    • Updated sanitize_text to accept an optional account parameter for authentication.
    • Modified model_armor_post to accept an optional account parameter for authentication.
    • Updated handle_sanitize and handle_create_template to accept and pass the account parameter.
  • src/helpers/script.rs
    • Modified handle_script_command to retrieve the account from matches and pass it to auth::get_token.
  • src/helpers/sheets.rs
    • Modified handle_sheets_command to retrieve the account from matches and pass it to auth::get_token.
  • src/helpers/workflows.rs
    • Modified workflow handlers (handle_standup_report, handle_meeting_prep, handle_email_to_task, handle_weekly_digest, handle_file_announce) to retrieve the account from matches and pass it to auth::get_token and resolve_account_timezone.
  • src/main.rs
    • Modified run function to retrieve the global account argument and pass it to auth::get_token and executor::execute_method.
  • src/setup.rs
    • Modified stage_configure_oauth to pass None for the account when loading encrypted credentials.
    • Modified run_setup to pass None for the account when calling crate::auth_commands::run_login.
  • src/setup_tui.rs
    • Added Stylize trait import for Ratatui components.
  • src/timezone.rs
    • Modified cache_path to generate account-specific filenames for timezone cache.
    • Updated invalidate_cache to remove the default timezone cache file.
    • Modified read_cache and write_cache to accept an optional account parameter for account-specific caching.
    • Updated fetch_account_timezone to accept an optional account parameter.
    • Modified resolve_account_timezone to accept an optional account parameter and use it for cache operations and API calls.
Activity
  • The pull request introduces multi-account support, a significant feature addressing security and auditing needs.
  • Authentication tests in auth.rs were refactored to use temporary config directories, ensuring perfect isolation and preventing state leakage, with over 630 tests passing.
  • The --account flag was added globally, impacting numerous commands and helper functions across the codebase.
  • Dependency updates were made in Cargo.lock and Cargo.toml, including a ratatui downgrade and a Rust version bump.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Generative AI Prohibited Use Policy, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

The pull request implements multi-account authentication support, allowing users to isolate credentials and token caches using a global --account <name> flag. This involved updating ScopedTokenProvider and get_token to accept an optional account parameter, modifying credential and token cache path resolution to be account-specific, and plumbing the account parameter through various authentication and helper functions across the codebase. The review comments highlight several areas where the multi-account support is not fully consistent: specifically, the handle_status function in src/auth_commands.rs and the invalidate_cache function in src/timezone.rs need to be updated to correctly utilize the account parameter for path resolution and cache invalidation, respectively. Additionally, the account parameter needs to be passed to sanitize_text in src/helpers/gmail/watch.rs to ensure correct credential usage for Model Armor.

@googleworkspace-bot
Copy link
Collaborator

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

The pull request introduces multi-account authentication support, enabling users to specify an account alias via a global --account flag. This involved updating the ScopedTokenProvider and get_token functions to handle account-specific tokens, modifying credential and token cache paths to be account-aware, and propagating the account context through various helper functions for Google services and Model Armor sanitization. A key area for improvement identified in the review is the manual parsing of the --account flag within src/auth_commands.rs, which is complex and brittle, suggesting a refactor to leverage clap for more robust and consistent argument handling.

@googleworkspace-bot
Copy link
Collaborator

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces multi-account support, a significant feature that allows users to manage separate credentials and settings for different Google accounts. The implementation correctly isolates token caches, encrypted credentials, and timezone settings by using an --account flag. The auth-related commands (status, logout, export) and the core CLI command structure have been updated accordingly. However, I've found a critical issue where plaintext credentials are not properly isolated per account, which could lead to incorrect credential usage. This issue appears in two places in the authentication logic. The rest of the changes, including test refactoring for better isolation and migration to clap for argument parsing, are well-executed.

…mezone cache

- Ensure plaintext credentials use account-specific paths (src/auth.rs, src/auth_commands.rs)
- Refactor path helpers into src/credential_store.rs for consistency
- Update timezone::invalidate_cache to clear both account and default caches
- Fix clippy warnings and format code
- Address review comments on PR googleworkspace#496
@googleworkspace-bot
Copy link
Collaborator

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request is a great enhancement, restoring multi-account support to the CLI. The implementation is thorough, with changes propagated correctly through authentication, helpers, and configuration storage. The refactoring in auth_commands.rs to use clap is a significant improvement for maintainability. However, I've identified a critical security vulnerability related to path traversal. The new --account flag's value is used directly to construct file paths, which could allow a malicious user to read or write files outside of the intended configuration directory. I've added a specific comment with a suggested fix.

…tion issues

- Add value_parser to account argument to restrict allowed characters
- Ensure account-specific paths are used consistently for plaintext credentials
- Plumb account parameter down to Gmail watch sanitization
- Fully implement account-aware timezone cache invalidation
- Address all high-priority bot review comments on PR googleworkspace#496
@googleworkspace-bot
Copy link
Collaborator

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request does a great job of restoring multi-account support by isolating credentials and settings per account. The refactoring of command-line argument parsing to use clap is a significant improvement for maintainability. The changes are extensive and have been applied consistently across the codebase. I found one issue where the --account flag is not respected when used with setup --login, which I've detailed in a specific comment.

…flakiness

- Fixed missing account isolation for token caches in `get_token`
- Fixed stale token cache deletion to use account-aware file paths
- Plumbed `--account` through `gws auth setup` to properly isolate post-setup `login` attempts
- Isolated the temporary OAuth credentials file during `login` to prevent concurrent TOCTOU race conditions between different accounts
- Added `#[serial_test::serial]` to all environment-mutating async tests in `auth.rs` to fix random parallel CI failures
@googleworkspace-bot
Copy link
Collaborator

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces multi-account support, a significant and well-implemented feature. The changes are consistent across the codebase, with good refactoring of authentication and configuration path logic to be account-aware. The introduction of clap for argument parsing in auth_commands.rs is a major improvement for robustness.

My review includes one high-severity suggestion for improving maintainability: refactor the new clap-based argument handling to avoid re-parsing arguments in downstream functions.

…ions

- Introduced  and  structs to hold parsed arguments
- Refactored , , and  to accept these structs instead of
- Removed manual command-line parsing logic in favor of -populated data structures
- Updated tests and internal callers to use the new structured data flow
@googleworkspace-bot
Copy link
Collaborator

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces multi-account support, a significant and well-implemented feature. The code is well-structured, especially the centralization of path logic in credential_store.rs and the adoption of clap for argument parsing. I've identified a critical issue in the setup flow where credentials for the wrong account might be loaded, and a high-severity suggestion to improve correctness in the authentication code.

…p idiomatic borrows

- Fixed setup wizard incorrectly loading default account credentials when pre-filling manual OAuth prompts
- Optimized  by removing an unnecessary allocation when reading user secrets
- Verified all 180+ auth/setup unit tests pass
@googleworkspace-bot
Copy link
Collaborator

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces significant and well-implemented multi-account support. The use of a global --account flag to isolate credentials, token caches, and settings is a great feature for security and usability. The refactoring to centralize path logic in credential_store.rs and the adoption of clap for argument parsing in auth_commands.rs are excellent improvements to the codebase's maintainability. The test suite has also been improved with better isolation. Overall this is a solid contribution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: auth area: core Core CLI parsing, commands, error handling, utilities area: distribution area: http area: tui

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants