Skip to content

[PM-41798] 1Password access module - #1371

Open
detunized wants to merge 21 commits into
bitwarden:mainfrom
detunized:onepassword-access
Open

[PM-41798] 1Password access module#1371
detunized wants to merge 21 commits into
bitwarden:mainfrom
detunized:onepassword-access

Conversation

@detunized

Copy link
Copy Markdown

🎟️ Tracking

N/A

📔 Objective

Adds a direct 1Password client to bitwarden-importers. It logs in with the master password and
Secret Key and downloads every vault the account can open.

It is a Rust port of the 1Password module from the C# password-manager-access library.

What it does:

  • SRP login with the Secret Key, TOTP as the second factor
  • Registers the device when the server asks for it
  • Downloads and decrypts all vaults and items
  • Returns each item as its decrypted overview and details, the way 1Password sends them

Tests cover the crypto with known answer vectors from the C# tests, and the HTTP flows with
wiremock. I also ran it against a real account.

Not included:

  • No SSO, no service accounts
  • TOTP only, no Duo or WebAuthn
  • Nothing in the SDK calls this yet, so the module has #[allow(dead_code, unused_imports)]
    for now

README.md has the remaining notes and open questions.

The next PR will introduce a 1P to BW conversion/importer layer.

Use https://github.com/detunized/onepassword-access-cli to drive this library to test against a live account.

🚨 Breaking Changes

None. Nothing consumes the new module yet.

Logs in with the master password and Secret Key, drives TOTP two-factor,
then downloads and decrypts every accessible vault into a native
1Password model. A Rust port of the OnePassword module in the C#
password-manager-access library.
The client now returns each item as its decrypted overview and details,
which is what 1Password actually sends. Turning that into typed items is
the importer's job, so the parsing and the Item/Field/Otp/SshKey model
move to the conversion layer rather than living behind the download.
@detunized
detunized requested review from a team as code owners August 10, 2026 13:21
@detunized
detunized requested a review from coroiu August 10, 2026 13:21
@CLAassistant

CLAassistant commented Aug 10, 2026

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ detunized
❌ itsadrago
You have signed the CLA already but the status is still pending? Let us recheck it.

@bitwarden-bot

Copy link
Copy Markdown
Collaborator

Thank you for your contribution! We've added this to our internal Community PR board for review.
ID: PM-41798
Link: https://bitwarden.atlassian.net/browse/PM-41798

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

@bitwarden-bot bitwarden-bot changed the title 1Password access module [PM-41798] 1Password access module Aug 10, 2026
Comment thread crates/bitwarden-importers/src/importers/onepassword/access/srp.rs

@harr1424 harr1424 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I saw expect used a handful of times, this in general is discouraged, but overall the error handling appears robust.

Comment thread .github/renovate.json5 Outdated
Comment thread crates/bitwarden-importers/src/importers/onepassword/access/account_key.rs Outdated
Comment thread crates/bitwarden-importers/src/importers/onepassword/access/device.rs Outdated
Comment on lines +21 to +26
- The client fingerprint lives in `identity.rs`: app version, HTTP library and per-platform strings.
Question: do we need per-platform impersonation, or is one fixed identity enough?
- There are many tests converted from the C# repo, they became very noisy in Rust. Do we even need
them? See start_registers_an_unknown_device_then_retries for an example.
- Do we need to import password history?
- Only the credentials and the keys are zeroed. The decrypted vault data is not

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@itsadrago more open questions to review

Comment thread Cargo.toml

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Another reminder to begin a review process for any new dependencies

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Note we have both aes-gcm and pbkdf2 already approved in the clients repo and so I think we'd need approval for...

hkdf (Pure Rust implementation of the HMAC-based Extract-and-Expand Key Derivation Function (HKDF) generic over hash function.)
168 KiB

icu_normalizer (Normalizing text into Unicode Normalization Forms.)
76.3 KiB

num-bigint (Big integer types for Rust, BigInt and BigUint.)
109 KiB

@harr1424 harr1424 added the ai-review Request a Claude code review label Aug 10, 2026
@codecov

codecov Bot commented Aug 11, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 87.92943% with 260 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.32%. Comparing base (99ffb6e) to head (eeeaa17).

Files with missing lines Patch % Lines
...porters/src/importers/onepassword/access/client.rs 57.27% 94 Missing ⚠️
...mporters/src/importers/onepassword/access/model.rs 0.00% 51 Missing ⚠️
...rters/src/importers/onepassword/access/keychain.rs 78.60% 49 Missing ⚠️
...-importers/src/importers/onepassword/access/srp.rs 90.14% 27 Missing ⚠️
...mporters/src/importers/onepassword/access/login.rs 94.33% 14 Missing ⚠️
...porters/src/importers/onepassword/access/region.rs 0.00% 6 Missing ⚠️
...porters/src/importers/onepassword/access/opdata.rs 96.42% 5 Missing ⚠️
...importers/src/importers/onepassword/access/rest.rs 98.36% 5 Missing ⚠️
...rs/src/importers/onepassword/access/account_key.rs 96.19% 4 Missing ⚠️
...-importers/src/importers/onepassword/access/rsa.rs 94.28% 4 Missing ⚠️
... and 1 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1371      +/-   ##
==========================================
+ Coverage   86.28%   86.32%   +0.03%     
==========================================
  Files         500      518      +18     
  Lines       73417    75571    +2154     
==========================================
+ Hits        63349    65234    +1885     
- Misses      10068    10337     +269     

☔ View full report in Codecov by Harness.
📢 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.

Comment thread Cargo.toml Outdated
Comment thread Cargo.toml Outdated
Comment thread Cargo.toml Outdated
Comment thread crates/bitwarden-importers/Cargo.toml
Comment thread crates/bitwarden-importers/src/lib.rs
Comment thread crates/bitwarden-importers/src/importers/onepassword/mod.rs
Comment thread crates/bitwarden-importers/Cargo.toml

@coroiu coroiu left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Let me know when this has been reviewed and approved by tools and I'll give it a look

Comment thread crates/bitwarden-importers/src/importers/onepassword/access/account_key.rs Outdated
Comment thread crates/bitwarden-importers/src/importers/onepassword/access/client.rs Outdated
@detunized

Copy link
Copy Markdown
Author

I saw expect used a handful of times, this in general is discouraged, but overall the error handling appears robust.

@harr1424 I went through the expect calls and improved (I hope) the messages. They should never get triggered, they are only there to make the compiler happy and not to propagate an impossible error. Most of the matches are in tests, which I assume is ok.

Comment thread crates/bitwarden-importers/src/importers/onepassword/access/credentials.rs Outdated
Comment thread crates/bitwarden-importers/src/importers/onepassword/access/credentials.rs Outdated
Comment thread crates/bitwarden-importers/src/importers/onepassword/access/keychain.rs Outdated

@quexten quexten left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Only skimmed this but a few notes:

  • We should use a bigint library appropriate for cryptographic use. I have linked the one maintained by rustcrypto.
  • (optional) It would be nice to have a documentation of how these components interact at a high level. even if it's a link to a spec by 1passsword
  • a lot of dangerous interfaces are publicly exposed here. This is not desireable. Can we please lock them down?

other than that great work!


A Rust port of the OnePassword module in Bitwarden's C# `password-manager-access` library.

The 1P and BW name things differently. 1P has vaults that are independent, could be shared

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@detunized To make this easy to maintain for the tools team, would it be possible to get a higher-level spec for this? Right now it is unclear how the crypto works at a high level, and how it interacts. (cc @harr1424 I know we dm'd about this for the other crates / importers).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hey @quexten ! Yes I spoke about this with @itsadrago and we agreed having a better understanding of the reverse engineering and crypto would go a long ways to improving maintainability.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

@harr1424 @quexten I will write what I can. There's a white paper from 1P with their protocol and vault structure description, but I mainly got that from reversing their minified js code and studying the http logs.

Comment thread crates/bitwarden-importers/src/importers/onepassword/access/rsa.rs Outdated
Comment thread crates/bitwarden-importers/src/importers/onepassword/access/srp.rs Outdated
num-bigint's modpow is not constant time. crypto-bigint raises through
Montgomery form, which is, and it was already in the tree via rsa and
ssh-key so it costs no extra build weight.

Also drops num-bigint from the workspace and removes the crypto-bigint
[patch.crates-io], since 0.7.5 has reached the registry.
Everything the CLI does not name is now pub(super). In wire only the item
DTOs stay public, because model::Item exposes them through its fields; the
auth and session DTOs are internal.

Also drops three imports the blanket allow had been hiding.
@quexten
quexten dismissed their stale review August 15, 2026 05:41

Dismissing change request

@quexten quexten left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks. I don't know the 1Password protocol, but the changes look reasonable. We could probably spend time to refactor it a bit to make it more idiomatic rust in some places, but that's not a requirement from my side at any rate.

Nice work! Love the test vectors and that it's fully in SDK.

@detunized

Copy link
Copy Markdown
Author

@quexten thanks!

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants