better_auth_api/plugins/passkey/
options.rs1use super::callbacks::{
4 PasskeyAuthenticationHook, PasskeyExtensionsResolver, PasskeyRegistrationHook,
5 PasskeyUserResolver,
6};
7use serde::{Deserialize, Serialize};
8use serde_json::{Map, Value};
9use std::sync::Arc;
10
11#[derive(Debug, Clone, Default)]
13pub enum PasskeyOrigins {
14 #[default]
15 Request,
16 Explicit(Vec<String>),
17}
18impl From<String> for PasskeyOrigins {
19 fn from(value: String) -> Self {
20 if value.is_empty() {
21 Self::Request
22 } else {
23 Self::Explicit(vec![value])
24 }
25 }
26}
27impl From<&str> for PasskeyOrigins {
28 fn from(value: &str) -> Self {
29 value.to_owned().into()
30 }
31}
32impl From<Vec<String>> for PasskeyOrigins {
33 fn from(value: Vec<String>) -> Self {
34 Self::Explicit(value)
35 }
36}
37
38#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
40#[serde(rename_all = "kebab-case")]
41pub enum AuthenticatorAttachment {
42 Platform,
43 CrossPlatform,
44}
45#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
47#[serde(rename_all = "lowercase")]
48pub enum PasskeyRequirement {
49 Required,
50 Preferred,
51 Discouraged,
52}
53#[derive(Debug, Clone, Default, Serialize, Deserialize)]
55#[serde(rename_all = "camelCase")]
56pub struct AuthenticatorSelection {
57 #[serde(skip_serializing_if = "Option::is_none")]
58 pub authenticator_attachment: Option<AuthenticatorAttachment>,
59 #[serde(skip_serializing_if = "Option::is_none")]
60 pub resident_key: Option<PasskeyRequirement>,
61 #[serde(skip_serializing_if = "Option::is_none")]
62 pub require_resident_key: Option<bool>,
63 #[serde(skip_serializing_if = "Option::is_none")]
64 pub user_verification: Option<PasskeyRequirement>,
65}
66
67#[derive(Clone, Default)]
69pub enum PasskeyExtensions {
70 #[default]
71 None,
72 Static(Map<String, Value>),
73 Dynamic(Arc<dyn PasskeyExtensionsResolver>),
74}
75impl std::fmt::Debug for PasskeyExtensions {
76 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
77 match self {
78 Self::None => f.write_str("None"),
79 Self::Static(value) => f.debug_tuple("Static").field(value).finish(),
80 Self::Dynamic(_) => f.write_str("Dynamic(..)"),
81 }
82 }
83}
84#[derive(Clone)]
86pub struct PasskeyRegistrationOptions {
87 pub require_session: bool,
88 pub resolve_user: Option<Arc<dyn PasskeyUserResolver>>,
89 pub after_verification: Option<Arc<dyn PasskeyRegistrationHook>>,
90 pub extensions: PasskeyExtensions,
91}
92impl Default for PasskeyRegistrationOptions {
93 fn default() -> Self {
94 Self {
95 require_session: true,
96 resolve_user: None,
97 after_verification: None,
98 extensions: PasskeyExtensions::None,
99 }
100 }
101}
102impl std::fmt::Debug for PasskeyRegistrationOptions {
103 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104 f.debug_struct("PasskeyRegistrationOptions")
105 .field("require_session", &self.require_session)
106 .field("resolve_user", &self.resolve_user.is_some())
107 .field("after_verification", &self.after_verification.is_some())
108 .field("extensions", &self.extensions)
109 .finish()
110 }
111}
112#[derive(Clone, Default)]
114pub struct PasskeyAuthenticationOptions {
115 pub after_verification: Option<Arc<dyn PasskeyAuthenticationHook>>,
116 pub extensions: PasskeyExtensions,
117}
118impl std::fmt::Debug for PasskeyAuthenticationOptions {
119 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
120 f.debug_struct("PasskeyAuthenticationOptions")
121 .field("after_verification", &self.after_verification.is_some())
122 .field("extensions", &self.extensions)
123 .finish()
124 }
125}