Skip to content

Conversation

fer
Copy link

@fer fer commented Oct 6, 2025

🎟️ Tracking

https://bitwarden.atlassian.net/browse/PM-26542

📔 Objective

Implements session-based authentication for the Rust Bitwarden CLI, enabling stateless command execution similar to the Node.js CLI. Users can now authenticate once with bw login api-key and reuse the session for subsequent commands.

Added environment variable support (BW_CLIENTID, BW_CLIENTSECRET, BW_PASSWORD) to the bw login api-key command and made it return a base64-encoded session key (like the Node.js CLI, although this one is reaally long) that can be potentially used with --session (or BW_SESSION) for subsequent vault operations.

Session Management

  • Session Export: Added export_session() to serialize full client state
  • Session Import: Added import_session() to restore complete authenticated state from session string
  • Session Format: Base64-encoded JSON containing all crypto keys and OAuth tokens needed for vault operations

Environment Variable Support

Added support for environment variables in bw login api-key:

  • BW_CLIENTID (or BW_CLIENT_ID): API client ID
  • BW_CLIENTSECRET (or BW_CLIENT_SECRET): API client secret
  • BW_PASSWORD: Master password
  • Environment variables take precedence over interactive prompts

List Command Implementation

  • Implemented bw list items with filtering options:
    • --search: Text search across items
    • --folderid: Filter by folder
    • --collectionid: Filter by collection
    • --organizationid: Filter by organization
    • --trash: Show deleted items
  • Returns decrypted vault items as JSON

Session Usage

The global --session flag and BW_SESSION environment variable now work across all commands, automatically restoring client state before execution.

Usage Example

# Set credentials via environment variables
export BW_CLIENTID="user.xxx"
export BW_CLIENTSECRET="xxx"
export BW_PASSWORD="xxx"

# Login and capture session
SESSION=$(bw login api-key)

# Use session for subsequent commands
bw list items --session "$SESSION"

# Or via environment variable
export BW_SESSION="$SESSION"
bw list items

⏰ Reminders before review

  • Contributor guidelines followed
  • All formatters and local linters executed and passed
  • Written new unit and / or integration tests where applicable
  • Protected functional changes with optionality (feature flags)
  • Used internationalization (i18n) for all UI strings
  • CI builds passed
  • Communicated to DevOps any deployment requirements
  • Updated any necessary documentation (Confluence, contributing docs) or informed the documentation
    team

🦮 Reviewer guidelines

  • 👍 (:+1:) or similar for great changes
  • 📝 (:memo:) or ℹ️ (:information_source:) for notes or general info
  • ❓ (:question:) for questions
  • 🤔 (:thinking:) or 💭 (:thought_balloon:) for more open inquiry that's not quite a confirmed
    issue and could potentially benefit from discussion
  • 🎨 (:art:) for suggestions / improvements
  • ❌ (:x:) or ⚠️ (:warning:) for more significant problems or concerns needing attention
  • 🌱 (:seedling:) or ♻️ (:recycle:) for future improvements or indications of technical debt
  • ⛏ (:pick:) for minor or nitpick changes

@fer fer requested a review from a team as a code owner October 6, 2025 14:10
@fer fer requested a review from addisonbeck October 6, 2025 14:10
@fer fer changed the title read env vars for client id/secret password when using api-key and re… env vars for client id/secret password when using api-key, return SESSION token Oct 6, 2025
@bitwarden-bot
Copy link

Thank you for your contribution! We've added this to our internal tracking system for review.
ID: PM-26542
Link: https://bitwarden.atlassian.net/browse/PM-26542

Details on our contribution process can be found here: https://contributing.bitwarden.com/contributing/pull-requests/community-pr-process.

Copy link

codecov bot commented Oct 6, 2025

Codecov Report

❌ Patch coverage is 0% with 200 lines in your changes missing coverage. Please review.
✅ Project coverage is 77.57%. Comparing base (ae9b8b5) to head (398c69d).

Files with missing lines Patch % Lines
crates/bw/src/vault/list.rs 0.00% 71 Missing ⚠️
crates/bitwarden-core/src/client/internal.rs 0.00% 59 Missing ⚠️
crates/bw/src/main.rs 0.00% 27 Missing ⚠️
crates/bw/src/auth/login.rs 0.00% 21 Missing ⚠️
crates/bitwarden-cli/src/lib.rs 0.00% 16 Missing ⚠️
crates/bw/src/auth/mod.rs 0.00% 4 Missing ⚠️
crates/bw/src/command.rs 0.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #492      +/-   ##
==========================================
- Coverage   78.10%   77.57%   -0.54%     
==========================================
  Files         283      284       +1     
  Lines       27628    27818     +190     
==========================================
  Hits        21579    21579              
- Misses       6049     6239     +190     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@fer fer changed the title env vars for client id/secret password when using api-key, return SESSION token Add listing items functionality with session-based authentication with environment variable support for API key login Oct 6, 2025
fer added 2 commits October 6, 2025 22:05
Apply cargo fmt to fix import ordering and line wrapping to comply
with CI style checks.
Separate external crate imports from internal crate imports with
blank lines to comply with nightly rustfmt group_imports feature
used in CI.
@fer fer changed the title Add listing items functionality with session-based authentication with environment variable support for API key login [PM-26542] Add listing items functionality with session-based authentication with environment variable support for API key login Oct 6, 2025
addisonbeck
addisonbeck previously approved these changes Oct 16, 2025
Copy link
Contributor

@addisonbeck addisonbeck left a comment

Choose a reason for hiding this comment

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

This looks good to me. Will re-approve if you decide to rename text_or_env_prompt, but that's not blocking.

Copy link
Contributor

Logo
Checkmarx One – Scan Summary & Details605789bf-c365-45ff-aab7-d841638071ef

Great job! No new security vulnerabilities introduced in this pull request

Copy link

Copy link
Contributor

@nick-livefront nick-livefront left a comment

Choose a reason for hiding this comment

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

Let me know if there is future work slated to flush out the implementation of the vault related items. If list is just being used as an easy implementation to test against, the changes are good with me.


#[derive(Debug)]
pub struct ListOptions {
pub object: String,
Copy link
Contributor

Choose a reason for hiding this comment

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

⛏️ With their only being a finite amount of options an enum can narrow the available options here.

pub enum ObjectType {
    #[value(name = "items")]
    Items,
    #[value(name = "folders")]
    Folders,
    #[value(name = "collections")]
    Collections,
    #[value(name = "organizations")]
    Organizations,
    #[value(name = "org-collections")]
    OrgCollections,
    #[value(name = "org-members")]
    OrgMembers,
}

Copy link
Author

@fer fer Oct 17, 2025

Choose a reason for hiding this comment

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

Changes:

  • Added ObjectType enum with ValueEnum derive for clap integration
  • Updated ListOptions.object field from String to ObjectType
  • Replaced string matching with enum pattern matching in list()
  • Removed manual error handling for invalid object types

The enum uses kebab-case naming to maintain CLI compatibility.

Copy link
Author

Choose a reason for hiding this comment

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

The ListOptions struct is still needed because it contains the filtering parameters (search, folderid, collectionid, organizationid, trash) that apply to list operations.

The CLI now provides type-safe validation and shows available options in help output.

pub collectionid: Option<String>,
pub organizationid: Option<String>,
pub trash: bool,
}
Copy link
Contributor

Choose a reason for hiding this comment

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

❓ Archive is near future feature that was recently implemented in the CLI, should that be considered here?

bitwarden/clients#16502

Copy link
Author

Choose a reason for hiding this comment

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

I've added an unimplemented archive feature to match Node.js CLI:

  • Add archive command with todo!() placeholder
  • Add --archived flag to list command
  • Update ListOptions struct with archived field

Copy link
Author

Choose a reason for hiding this comment

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

Updated to match searchService.searchCiphersBasic - now searches ID (8+ chars), name, subtitle, and URIs with case-insensitive matching.

Please let me know if tests are needed.

// Search filter (case-insensitive search in name)
if let Some(ref search_term) = options.search {
let search_lower = search_term.to_lowercase();
if !item.name.to_lowercase().contains(&search_lower) {
Copy link
Contributor

Choose a reason for hiding this comment

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

❌ The current implementation of search within the CLI checks the id, name, subtitle and uris. searchService.searchCiphersBasic, I would think we'd want parity to that here.

fer added 2 commits October 17, 2025 19:59
Add unimplemented archive feature to match Node.js CLI:
- Add `archive` command with todo!() placeholder
- Add `--archived` flag to list command
- Update ListOptions struct with archived field

Should align with bitwarden/clients#16502 for future implementation.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants