1use bitwarden_vault::{CipherListView, CipherView, EncryptionContext, Fido2CredentialNewView};
2use passkey::authenticator::UIHint;
3use thiserror::Error;
4
5#[derive(Debug, Error)]
6pub enum Fido2CallbackError {
7 #[error("The operation requires user interaction")]
8 UserInterfaceRequired,
9
10 #[error("The operation was cancelled by the user")]
11 OperationCancelled,
12
13 #[error("Unknown error: {0}")]
14 Unknown(String),
15}
16
17#[async_trait::async_trait]
18pub trait Fido2UserInterface: Send + Sync {
19 async fn check_user<'a>(
20 &self,
21 options: CheckUserOptions,
22 hint: UIHint<'a, CipherView>,
23 ) -> Result<CheckUserResult, Fido2CallbackError>;
24 async fn pick_credential_for_authentication(
25 &self,
26 available_credentials: Vec<CipherView>,
27 ) -> Result<CipherView, Fido2CallbackError>;
28 async fn check_user_and_pick_credential_for_creation(
29 &self,
30 options: CheckUserOptions,
31 new_credential: Fido2CredentialNewView,
32 ) -> Result<(CipherView, CheckUserResult), Fido2CallbackError>;
33 async fn is_verification_enabled(&self) -> bool;
34}
35
36#[async_trait::async_trait]
37pub trait Fido2CredentialStore: Send + Sync {
38 async fn find_credentials(
39 &self,
40 ids: Option<Vec<Vec<u8>>>,
41 rip_id: String,
42 ) -> Result<Vec<CipherView>, Fido2CallbackError>;
43
44 async fn all_credentials(&self) -> Result<Vec<CipherListView>, Fido2CallbackError>;
45
46 async fn save_credential(&self, cred: EncryptionContext) -> Result<(), Fido2CallbackError>;
47}
48
49#[derive(Clone)]
50#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
51pub struct CheckUserOptions {
52 pub require_presence: bool,
53 pub require_verification: Verification,
54}
55
56#[derive(Clone)]
57#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
58pub enum Verification {
59 Discouraged,
60 Preferred,
61 Required,
62}
63
64pub struct CheckUserResult {
65 pub user_present: bool,
66 pub user_verified: bool,
67}