tmuntaner_webauthn/
lib.rs1mod utils;
8
9pub trait WebauthnNotifier {
10 fn notify_start(&self) -> Result<()>;
11 fn notify_end(&self) -> Result<()>;
12}
13
14#[cfg(feature = "progress_bar")]
15mod progress_bar;
16
17#[cfg(feature = "progress_bar")]
18use crate::progress_bar::ProgressBarFallbackNotifier;
19
20#[cfg(feature = "notifications")]
21mod desktop_notifications;
22
23#[cfg(feature = "notifications")]
24use crate::desktop_notifications::DesktopNotificationsFallbackNotifier;
25
26#[cfg(target_os = "windows")]
27mod windows;
28
29#[cfg(any(target_os = "linux", target_os = "macos"))]
30mod mozilla;
31
32use anyhow::Result;
33use serde::{Deserialize, Serialize};
34
35#[derive(Debug, Serialize, Clone, Deserialize)]
37#[serde(rename_all = "camelCase")]
38struct CollectedClientData {
39 #[serde(rename = "type")]
40 sign_type: String,
41 challenge: String,
42 origin: String,
43 #[serde(skip_serializing_if = "Option::is_none")]
44 cross_origin: Option<bool>,
45 token_binding: Option<TokenBinding>,
46}
47
48#[derive(Debug, Clone, Deserialize, Serialize)]
50struct TokenBinding {
51 status: String,
52 id: Option<String>,
53}
54
55pub struct SignatureResponse {
56 pub client_data: String,
57 pub signature_data: String,
58 pub authenticator_data: String,
59}
60
61#[derive(Default)]
62pub struct WebauthnClient {
63 notifiers: Vec<Box<dyn WebauthnNotifier>>,
64}
65
66impl WebauthnClient {
67 pub fn new() -> Self {
68 Self::default()
69 }
70
71 pub fn add_notifier(&mut self, notifier: Box<dyn WebauthnNotifier>) -> &mut WebauthnClient {
72 self.notifiers.push(notifier);
73
74 self
75 }
76
77 #[cfg(feature = "progress_bar")]
78 pub fn add_progress_bar_notifier(&mut self) -> &mut WebauthnClient {
79 let notifier = Box::new(ProgressBarFallbackNotifier::new());
80
81 self.add_notifier(notifier)
82 }
83
84 #[cfg(feature = "notifications")]
85 pub fn add_desktop_notification_notifier(&mut self) -> &mut WebauthnClient {
86 let notifier = Box::new(DesktopNotificationsFallbackNotifier::new());
87
88 self.add_notifier(notifier)
89 }
90
91 #[cfg(target_os = "windows")]
92 pub fn sign(
93 self,
94 challenge_str: String,
95 host: String,
96 credential_ids: Vec<String>,
97 ) -> Result<SignatureResponse> {
98 windows::sign(challenge_str, host, credential_ids)
99 }
100
101 #[cfg(any(target_os = "linux", target_os = "macos"))]
102 pub fn sign(
103 self,
104 challenge_str: String,
105 host: String,
106 credential_ids: Vec<String>,
107 ) -> Result<SignatureResponse> {
108 mozilla::sign(challenge_str, host, credential_ids, self.notifiers)
109 }
110}