From 5eb836d6a0d7ff751ec0bace7ff0089c2dc7fc31 Mon Sep 17 00:00:00 2001 From: Andreas Coroiu Date: Thu, 12 Sep 2024 14:24:29 +0200 Subject: [PATCH 1/4] chore: update passkey-rs dep to in-progress PR --- Cargo.lock | 20 +++++++++++--------- crates/bitwarden-fido/Cargo.toml | 5 ++++- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e9c74e8a6..90d39feae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -518,6 +518,7 @@ dependencies = [ "log", "p256", "passkey", + "passkey-client", "reqwest", "schemars", "serde", @@ -2633,8 +2634,8 @@ dependencies = [ [[package]] name = "passkey" -version = "0.3.1" -source = "git+https://github.com/bitwarden/passkey-rs?rev=ae08e2cb7dd3d44d915caed395c0cdc56b50fa27#ae08e2cb7dd3d44d915caed395c0cdc56b50fa27" +version = "0.2.0" +source = "git+https://github.com/bitwarden/passkey-rs?rev=29bb052eb15a42e369728ded3cfb2aa7c91213df#29bb052eb15a42e369728ded3cfb2aa7c91213df" dependencies = [ "passkey-authenticator", "passkey-client", @@ -2644,8 +2645,8 @@ dependencies = [ [[package]] name = "passkey-authenticator" -version = "0.3.0" -source = "git+https://github.com/bitwarden/passkey-rs?rev=ae08e2cb7dd3d44d915caed395c0cdc56b50fa27#ae08e2cb7dd3d44d915caed395c0cdc56b50fa27" +version = "0.2.0" +source = "git+https://github.com/bitwarden/passkey-rs?rev=29bb052eb15a42e369728ded3cfb2aa7c91213df#29bb052eb15a42e369728ded3cfb2aa7c91213df" dependencies = [ "async-trait", "coset", @@ -2657,12 +2658,13 @@ dependencies = [ [[package]] name = "passkey-client" -version = "0.3.1" -source = "git+https://github.com/bitwarden/passkey-rs?rev=ae08e2cb7dd3d44d915caed395c0cdc56b50fa27#ae08e2cb7dd3d44d915caed395c0cdc56b50fa27" +version = "0.2.0" +source = "git+https://github.com/bitwarden/passkey-rs?rev=29bb052eb15a42e369728ded3cfb2aa7c91213df#29bb052eb15a42e369728ded3cfb2aa7c91213df" dependencies = [ "ciborium", "coset", "idna", + "nom", "passkey-authenticator", "passkey-types", "public-suffix", @@ -2674,12 +2676,12 @@ dependencies = [ [[package]] name = "passkey-transports" version = "0.1.0" -source = "git+https://github.com/bitwarden/passkey-rs?rev=ae08e2cb7dd3d44d915caed395c0cdc56b50fa27#ae08e2cb7dd3d44d915caed395c0cdc56b50fa27" +source = "git+https://github.com/bitwarden/passkey-rs?rev=29bb052eb15a42e369728ded3cfb2aa7c91213df#29bb052eb15a42e369728ded3cfb2aa7c91213df" [[package]] name = "passkey-types" version = "0.2.1" -source = "git+https://github.com/bitwarden/passkey-rs?rev=ae08e2cb7dd3d44d915caed395c0cdc56b50fa27#ae08e2cb7dd3d44d915caed395c0cdc56b50fa27" +source = "git+https://github.com/bitwarden/passkey-rs?rev=29bb052eb15a42e369728ded3cfb2aa7c91213df#29bb052eb15a42e369728ded3cfb2aa7c91213df" dependencies = [ "bitflags 2.6.0", "ciborium", @@ -2916,7 +2918,7 @@ dependencies = [ [[package]] name = "public-suffix" version = "0.1.1" -source = "git+https://github.com/bitwarden/passkey-rs?rev=ae08e2cb7dd3d44d915caed395c0cdc56b50fa27#ae08e2cb7dd3d44d915caed395c0cdc56b50fa27" +source = "git+https://github.com/bitwarden/passkey-rs?rev=29bb052eb15a42e369728ded3cfb2aa7c91213df#29bb052eb15a42e369728ded3cfb2aa7c91213df" [[package]] name = "pyo3" diff --git a/crates/bitwarden-fido/Cargo.toml b/crates/bitwarden-fido/Cargo.toml index e85e56a19..f40707999 100644 --- a/crates/bitwarden-fido/Cargo.toml +++ b/crates/bitwarden-fido/Cargo.toml @@ -30,7 +30,10 @@ coset = { version = "0.3.7" } itertools = "0.13.0" log = ">=0.4.18, <0.5" p256 = { version = ">=0.13.2, <0.14" } -passkey = { git = "https://github.com/bitwarden/passkey-rs", rev = "ae08e2cb7dd3d44d915caed395c0cdc56b50fa27" } +passkey = { git = "https://github.com/bitwarden/passkey-rs", rev = "29bb052eb15a42e369728ded3cfb2aa7c91213df" } +passkey-client = { git = "https://github.com/bitwarden/passkey-rs", rev = "29bb052eb15a42e369728ded3cfb2aa7c91213df", features = [ + "android-asset-validation", +] } reqwest = { version = ">=0.12.5, <0.13", default-features = false } schemars = { version = "0.8.21", features = ["uuid1", "chrono"] } serde = { version = ">=1.0, <2.0", features = ["derive"] } From c38bec730aba42b00aa78f30f543f0b5e475cf56 Mon Sep 17 00:00:00 2001 From: Andreas Coroiu Date: Fri, 13 Sep 2024 11:09:59 +0200 Subject: [PATCH 2/4] feat: add support for new Origin type --- crates/bitwarden-fido/src/client.rs | 23 +++---- crates/bitwarden-fido/src/lib.rs | 4 +- crates/bitwarden-fido/src/types.rs | 64 +++++++++++++++++++ crates/bitwarden-uniffi/src/platform/fido2.rs | 6 +- 4 files changed, 78 insertions(+), 19 deletions(-) diff --git a/crates/bitwarden-fido/src/client.rs b/crates/bitwarden-fido/src/client.rs index a72dae6f5..114d14d28 100644 --- a/crates/bitwarden-fido/src/client.rs +++ b/crates/bitwarden-fido/src/client.rs @@ -1,22 +1,19 @@ use passkey::client::WebauthnError; -use reqwest::Url; use thiserror::Error; +use crate::types::InvalidOriginError; + use super::{ authenticator::GetSelectedCredentialError, get_string_name_from_enum, types::{ AuthenticatorAssertionResponse, AuthenticatorAttestationResponse, ClientData, - ClientExtensionResults, CredPropsResult, + ClientExtensionResults, CredPropsResult, Origin, }, Fido2Authenticator, PublicKeyCredentialAuthenticatorAssertionResponse, PublicKeyCredentialAuthenticatorAttestationResponse, }; -#[derive(Debug, Error)] -#[error("Invalid origin: {0}")] -pub struct InvalidOriginError(String); - #[derive(Debug, Error)] pub enum Fido2ClientError { #[error(transparent)] @@ -43,12 +40,11 @@ pub struct Fido2Client<'a> { impl<'a> Fido2Client<'a> { pub async fn register( &mut self, - origin: String, + origin: Origin, request: String, client_data: ClientData, ) -> Result { - let origin = Url::parse(&origin).map_err(|e| InvalidOriginError(format!("{}", e)))?; - + let origin: passkey::client::Origin = origin.try_into()?; let request: passkey::types::webauthn::CredentialCreationOptions = serde_json::from_str(&request)?; @@ -67,7 +63,7 @@ impl<'a> Fido2Client<'a> { let rp_id = request.public_key.rp.id.clone(); let mut client = passkey::client::Client::new(self.authenticator.get_authenticator(true)); - let result = client.register(&origin, request, client_data).await?; + let result = client.register(origin, request, client_data).await?; Ok(PublicKeyCredentialAuthenticatorAttestationResponse { id: result.id, @@ -98,12 +94,11 @@ impl<'a> Fido2Client<'a> { pub async fn authenticate( &mut self, - origin: String, + origin: Origin, request: String, client_data: ClientData, ) -> Result { - let origin = Url::parse(&origin).map_err(|e| InvalidOriginError(format!("{}", e)))?; - + let origin: passkey::client::Origin = origin.try_into()?; let request: passkey::types::webauthn::CredentialRequestOptions = serde_json::from_str(&request)?; @@ -116,7 +111,7 @@ impl<'a> Fido2Client<'a> { .replace(uv); let mut client = passkey::client::Client::new(self.authenticator.get_authenticator(false)); - let result = client.authenticate(&origin, request, client_data).await?; + let result = client.authenticate(origin, request, client_data).await?; Ok(PublicKeyCredentialAuthenticatorAssertionResponse { id: result.id, diff --git a/crates/bitwarden-fido/src/lib.rs b/crates/bitwarden-fido/src/lib.rs index 991828eb3..be1dfdb53 100644 --- a/crates/bitwarden-fido/src/lib.rs +++ b/crates/bitwarden-fido/src/lib.rs @@ -32,10 +32,10 @@ pub use traits::{ pub use types::{ AuthenticatorAssertionResponse, AuthenticatorAttestationResponse, ClientData, Fido2CredentialAutofillView, Fido2CredentialAutofillViewError, GetAssertionRequest, - GetAssertionResult, MakeCredentialRequest, MakeCredentialResult, Options, + GetAssertionResult, MakeCredentialRequest, MakeCredentialResult, Options, Origin, PublicKeyCredentialAuthenticatorAssertionResponse, PublicKeyCredentialAuthenticatorAttestationResponse, PublicKeyCredentialRpEntity, - PublicKeyCredentialUserEntity, + PublicKeyCredentialUserEntity, UnverifiedAssetLink, }; use self::crypto::{cose_key_to_pkcs8, pkcs8_to_cose_key}; diff --git a/crates/bitwarden-fido/src/types.rs b/crates/bitwarden-fido/src/types.rs index 8bc8ae42c..409db7a98 100644 --- a/crates/bitwarden-fido/src/types.rs +++ b/crates/bitwarden-fido/src/types.rs @@ -1,7 +1,10 @@ +use std::borrow::Cow; + use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine}; use bitwarden_crypto::KeyContainer; use bitwarden_vault::{CipherError, CipherView}; use passkey::types::webauthn::UserVerificationRequirement; +use reqwest::Url; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use thiserror::Error; @@ -359,6 +362,67 @@ pub struct AuthenticatorAssertionResponse { pub user_handle: Vec, } +#[derive(Debug, Error)] +#[error("Invalid origin: {0}")] +pub struct InvalidOriginError(String); + +#[cfg_attr(feature = "uniffi", derive(uniffi::Record))] +/// An Unverified asset link. +pub struct UnverifiedAssetLink { + /// Application package name. + package_name: String, + /// Fingerprint to compare. + sha256_cert_fingerprint: String, + /// Host to lookup the well known asset link. + host: String, + /// When sourced from the application statement list or parsed from host for passkeys. + /// Will be generated from `host` if not provided. + asset_link_url: Option, +} + +#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))] +/// The origin of a WebAuthn request. +pub enum Origin { + /// A Url, meant for a request in the web browser. + Web(String), + /// An android digital asset fingerprint. + /// Meant for a request coming from an android application. + Android(UnverifiedAssetLink), +} + +impl<'a> TryFrom for passkey::client::Origin<'a> { + type Error = InvalidOriginError; + + fn try_from(value: Origin) -> Result { + Ok(match value { + Origin::Web(url) => { + let url = Url::parse(&url).map_err(|e| InvalidOriginError(format!("{}", e)))?; + passkey::client::Origin::Web(Cow::Owned(url)) + } + Origin::Android(link) => passkey::client::Origin::Android(link.try_into()?), + }) + } +} + +impl<'a> TryFrom for passkey::client::UnverifiedAssetLink<'a> { + type Error = InvalidOriginError; + + fn try_from(value: UnverifiedAssetLink) -> Result { + let asset_link_url = match value.asset_link_url { + Some(url) => Some(Url::parse(&url).map_err(|e| InvalidOriginError(format!("{}", e)))?), + None => None, + }; + + passkey::client::UnverifiedAssetLink::new( + Cow::from(value.package_name), + value.sha256_cert_fingerprint.as_str(), + Cow::from(value.host), + asset_link_url, + ) + .map_err(|e| InvalidOriginError(format!("{:?}", e))) + } +} + #[cfg(test)] mod tests { use serde::{Deserialize, Serialize}; diff --git a/crates/bitwarden-uniffi/src/platform/fido2.rs b/crates/bitwarden-uniffi/src/platform/fido2.rs index 3018d7beb..f483ff346 100644 --- a/crates/bitwarden-uniffi/src/platform/fido2.rs +++ b/crates/bitwarden-uniffi/src/platform/fido2.rs @@ -11,7 +11,7 @@ use bitwarden::{ }, vault::{Cipher, CipherView, Fido2CredentialNewView}, }; -use bitwarden_fido::Fido2CredentialAutofillView; +use bitwarden_fido::{Fido2CredentialAutofillView, Origin}; use crate::{error::Result, Client}; @@ -135,7 +135,7 @@ pub struct ClientFido2Client(pub(crate) ClientFido2Authenticator); impl ClientFido2Client { pub async fn register( &self, - origin: String, + origin: Origin, request: String, client_data: ClientData, ) -> Result { @@ -153,7 +153,7 @@ impl ClientFido2Client { pub async fn authenticate( &self, - origin: String, + origin: Origin, request: String, client_data: ClientData, ) -> Result { From 41b36f0fa0264183d510cd46b45aaf621e58522a Mon Sep 17 00:00:00 2001 From: Andreas Coroiu Date: Fri, 13 Sep 2024 11:24:19 +0200 Subject: [PATCH 3/4] fix: lint --- crates/bitwarden-fido/src/client.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/bitwarden-fido/src/client.rs b/crates/bitwarden-fido/src/client.rs index 114d14d28..ac4330be7 100644 --- a/crates/bitwarden-fido/src/client.rs +++ b/crates/bitwarden-fido/src/client.rs @@ -1,8 +1,6 @@ use passkey::client::WebauthnError; use thiserror::Error; -use crate::types::InvalidOriginError; - use super::{ authenticator::GetSelectedCredentialError, get_string_name_from_enum, @@ -13,6 +11,7 @@ use super::{ Fido2Authenticator, PublicKeyCredentialAuthenticatorAssertionResponse, PublicKeyCredentialAuthenticatorAttestationResponse, }; +use crate::types::InvalidOriginError; #[derive(Debug, Error)] pub enum Fido2ClientError { From d1394e290ec7b81ecede488491d7a713e6449101 Mon Sep 17 00:00:00 2001 From: Andreas Coroiu Date: Wed, 18 Sep 2024 14:20:40 +0200 Subject: [PATCH 4/4] chore: update passkey-rs to PR-merge-commit --- crates/bitwarden-fido/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bitwarden-fido/Cargo.toml b/crates/bitwarden-fido/Cargo.toml index f40707999..6b04bd796 100644 --- a/crates/bitwarden-fido/Cargo.toml +++ b/crates/bitwarden-fido/Cargo.toml @@ -30,8 +30,8 @@ coset = { version = "0.3.7" } itertools = "0.13.0" log = ">=0.4.18, <0.5" p256 = { version = ">=0.13.2, <0.14" } -passkey = { git = "https://github.com/bitwarden/passkey-rs", rev = "29bb052eb15a42e369728ded3cfb2aa7c91213df" } -passkey-client = { git = "https://github.com/bitwarden/passkey-rs", rev = "29bb052eb15a42e369728ded3cfb2aa7c91213df", features = [ +passkey = { git = "https://github.com/bitwarden/passkey-rs", rev = "ff757604cd7b4e8f321ed1616fef7e40e21ac5df" } +passkey-client = { git = "https://github.com/bitwarden/passkey-rs", rev = "ff757604cd7b4e8f321ed1616fef7e40e21ac5df", features = [ "android-asset-validation", ] } reqwest = { version = ">=0.12.5, <0.13", default-features = false }