[PR #7370] Add passwordless webauthn login #37070

Open
opened 2026-07-13 21:34:45 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/dani-garcia/vaultwarden/pull/7370
Author: @RaphaelRoumezin
Created: 6/23/2026
Status: 🔄 Open

Base: mainHead: feat/webauthn_login


📝 Commits (9)

📊 Changes

22 files changed (+811 additions, -57 deletions)

View changed files

📝 .env.template (+3 -0)
migrations/mysql/2026-06-23-120000_add_webauthn/down.sql (+1 -0)
migrations/mysql/2026-06-23-120000_add_webauthn/up.sql (+10 -0)
migrations/postgresql/2026-06-23-120000_add_webauthn/down.sql (+1 -0)
migrations/postgresql/2026-06-23-120000_add_webauthn/up.sql (+10 -0)
migrations/sqlite/2026-06-23-120000_add_webauthn/down.sql (+1 -0)
migrations/sqlite/2026-06-23-120000_add_webauthn/up.sql (+10 -0)
📝 src/api/core/ciphers.rs (+23 -7)
📝 src/api/core/mod.rs (+9 -13)
📝 src/api/core/two_factor/mod.rs (+2 -1)
📝 src/api/core/two_factor/webauthn.rs (+22 -25)
src/api/core/webauthn.rs (+286 -0)
📝 src/api/identity.rs (+221 -8)
📝 src/api/web.rs (+1 -0)
📝 src/auth.rs (+32 -2)
📝 src/config.rs (+4 -0)
📝 src/db/models/mod.rs (+2 -0)
📝 src/db/models/two_factor.rs (+1 -0)
📝 src/db/models/user.rs (+2 -1)
src/db/models/webauthn_credential.rs (+153 -0)

...and 2 more files

📄 Description

This PR is my attempt at providing passwordless login, taking heavy inspiration from the work of @samos667 (#6820), who I believe has its work inspired from @zUnixorn (#5929).

I'm looking forward to your feedback on this work !

Working features

(same as #5929 and #6820)

  • Login with passkey without using it for encryption
  • Login with passkey while using it for encryption
  • Adding a new passkey
  • Listing all registered passkeys
  • Deleting a passkey

New

  • The passkey_login_allowed backend option was added, which can disable passkey-related endpoints and remove passkey-related settings and passkey login button from the web vault
  • The vault can be unlocked with all the encryption passkeys of the account, and not only the one used for logging in

Main differences from #6820

  • Refactored web_authn to webauthn, and WebAuthn to Webauthn for all related symbols
  • Switched to a stateless architecture for auth flow. The authentication state is sent to the client through JWT, despite the warning given by webauthn_rs. This is because the state does not hold more information than what is already given to the client, and i don't think the replay attack weakness is a problem in the bitwarden context, as this allows to bypass authentication but keeps vault content encrypted (and it isn't more replayable than the password auth flow). As for the passkey registration flow, the state is stored in the TwoFactor table (with type TwoFactorType::WebauthnPasskeyRegisterChallenge), as a replay could allow a deleted passkey to be recreated.
  • The webauthn authentication flow does not check for a verified email like the password flow, as creating a passkey already requires the user to be able to use the web vault, and thus having a verified email in the related contexts.
  • Relocated webauthn-related endpoints from src/api/core/mod.rs to src/api/core/webauthn.rs
  • The get_prf_status() function was added, following the C# bitwarden implementation.

Open questions

  • The authentication state is stored in JWT, and the registration state is stored in the table TwoFactor. The safest would be to store everything in the DB, but I think stateless auth would be preferrable if its secure. Using a dedicated table for webauthn_rs states is an option too.

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/dani-garcia/vaultwarden/pull/7370 **Author:** [@RaphaelRoumezin](https://github.com/RaphaelRoumezin) **Created:** 6/23/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `feat/webauthn_login` --- ### 📝 Commits (9) - [`7711b02`](https://github.com/dani-garcia/vaultwarden/commit/7711b02153d01386a9543b19d5141e2f8e99b04a) feat: passwordless login - [`007ac4f`](https://github.com/dani-garcia/vaultwarden/commit/007ac4f99234d11609e7027daf3181e447e88bb3) fix: Correct attestation options - [`8cba57a`](https://github.com/dani-garcia/vaultwarden/commit/8cba57a1afb82e0652c0dfe8835ce2b609470bab) feat(config): Add passkey_login_allowed config option - [`224ad8a`](https://github.com/dani-garcia/vaultwarden/commit/224ad8a4065d62abba69a33da2056d540db96385) fix: typos - [`05c9af4`](https://github.com/dani-garcia/vaultwarden/commit/05c9af4d1e931b6d8cf3ed42a75998edb8b83c51) fix: Allowed Chromium extensions as origins for passwordless login - [`3b66926`](https://github.com/dani-garcia/vaultwarden/commit/3b669264bb247351129916bcbbf2bf125b6c939d) fix(clippy): few refactors - [`9e4aa5e`](https://github.com/dani-garcia/vaultwarden/commit/9e4aa5efe76f78d349492bc36731f2117b488a7b) feat: Added support for passkey vault unlock feature - [`89a25c4`](https://github.com/dani-garcia/vaultwarden/commit/89a25c4e123deb792fd40d145011ed202ec5ff34) Merge branch 'main' of https://github.com/dani-garcia/vaultwarden into feat/webauthn_login - [`89bcfe6`](https://github.com/dani-garcia/vaultwarden/commit/89bcfe67f899efb594ce625824c6deac2f6b1d9d) Merge branch 'main' of https://github.com/dani-garcia/vaultwarden into feat/webauthn_login ### 📊 Changes **22 files changed** (+811 additions, -57 deletions) <details> <summary>View changed files</summary> 📝 `.env.template` (+3 -0) ➕ `migrations/mysql/2026-06-23-120000_add_webauthn/down.sql` (+1 -0) ➕ `migrations/mysql/2026-06-23-120000_add_webauthn/up.sql` (+10 -0) ➕ `migrations/postgresql/2026-06-23-120000_add_webauthn/down.sql` (+1 -0) ➕ `migrations/postgresql/2026-06-23-120000_add_webauthn/up.sql` (+10 -0) ➕ `migrations/sqlite/2026-06-23-120000_add_webauthn/down.sql` (+1 -0) ➕ `migrations/sqlite/2026-06-23-120000_add_webauthn/up.sql` (+10 -0) 📝 `src/api/core/ciphers.rs` (+23 -7) 📝 `src/api/core/mod.rs` (+9 -13) 📝 `src/api/core/two_factor/mod.rs` (+2 -1) 📝 `src/api/core/two_factor/webauthn.rs` (+22 -25) ➕ `src/api/core/webauthn.rs` (+286 -0) 📝 `src/api/identity.rs` (+221 -8) 📝 `src/api/web.rs` (+1 -0) 📝 `src/auth.rs` (+32 -2) 📝 `src/config.rs` (+4 -0) 📝 `src/db/models/mod.rs` (+2 -0) 📝 `src/db/models/two_factor.rs` (+1 -0) 📝 `src/db/models/user.rs` (+2 -1) ➕ `src/db/models/webauthn_credential.rs` (+153 -0) _...and 2 more files_ </details> ### 📄 Description This PR is my attempt at providing passwordless login, taking heavy inspiration from the work of @samos667 (#6820), who I believe has its work inspired from @zUnixorn (#5929). I'm looking forward to your feedback on this work ! ## Working features *(same as #5929 and #6820)* - Login with passkey without using it for encryption - Login with passkey while using it for encryption - Adding a new passkey - Listing all registered passkeys - Deleting a passkey *New* - The `passkey_login_allowed` backend option was added, which can disable passkey-related endpoints and remove passkey-related settings and passkey login button from the web vault - The vault can be unlocked with all the encryption passkeys of the account, and not only the one used for logging in ## Main differences from #6820 - Refactored `web_authn` to `webauthn`, and `WebAuthn` to `Webauthn` for all related symbols - Switched to a stateless architecture for auth flow. The authentication state is sent to the client through JWT, despite the warning given by webauthn_rs. This is because the state does not hold more information than what is already given to the client, and i don't think the replay attack weakness is a problem in the bitwarden context, as this allows to bypass authentication but keeps vault content encrypted (and it isn't more replayable than the password auth flow). As for the passkey registration flow, the state is stored in the `TwoFactor` table (with type `TwoFactorType::WebauthnPasskeyRegisterChallenge`), as a replay could allow a deleted passkey to be recreated. - The webauthn authentication flow does not check for a verified email like the password flow, as creating a passkey already requires the user to be able to use the web vault, and thus having a verified email in the related contexts. - Relocated webauthn-related endpoints from `src/api/core/mod.rs` to `src/api/core/webauthn.rs` - The `get_prf_status()` function was added, following the C# bitwarden implementation. ## Open questions - The authentication state is stored in JWT, and the registration state is stored in the table `TwoFactor`. The safest would be to store everything in the DB, but I think stateless auth would be preferrable if its secure. Using a dedicated table for webauthn_rs states is an option too. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-07-13 21:34:45 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/vaultwarden#37070