alibi_plugins/passkey/
options.rs1use alibi_core::{AuthConfig, AuthRequest, AuthResult, ContextExtensions, wire::UserView};
3use async_trait::async_trait;
4use serde_json::Value;
5use std::sync::Arc;
6
7pub struct PasskeyOptionsContext<'a> {
8 pub request: &'a AuthRequest,
9 pub auth_config: &'a AuthConfig,
10 pub extensions: &'a ContextExtensions,
11 pub user: Option<&'a UserView>,
12}
13
14#[async_trait]
15pub trait PasskeyExtensionsResolver: Send + Sync {
16 async fn resolve(&self, context: &PasskeyOptionsContext<'_>) -> AuthResult<Value>;
17}
18
19#[derive(Clone)]
20pub enum PasskeyExtensions {
21 Static(Value),
22 Resolver(Arc<dyn PasskeyExtensionsResolver>),
23}
24impl std::fmt::Debug for PasskeyExtensions {
25 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26 match self {
27 Self::Static(value) => f.debug_tuple("Static").field(value).finish(),
28 Self::Resolver(_) => f.write_str("Resolver(..)"),
29 }
30 }
31}
32impl PasskeyExtensions {
33 pub(super) async fn resolve(&self, context: &PasskeyOptionsContext<'_>) -> AuthResult<Value> {
34 let value = match self {
35 Self::Static(value) => Ok(value.clone()),
36 Self::Resolver(resolver) => resolver.resolve(context).await.map_err(|error| {
37 if alibi_core::endpoint::is_endpoint_api_error(&error) {
38 error
39 } else {
40 alibi_core::AuthError::CallbackFailure(Box::new(error))
41 }
42 }),
43 }?;
44 if !value.is_object() {
45 return Err(alibi_core::AuthError::config(
46 "Passkey extensions must be an object",
47 ));
48 }
49 Ok(value)
50 }
51}
52
53#[derive(Debug, Clone, Default)]
54pub struct PasskeyAuthenticatorSelection {
55 pub resident_key: Option<String>,
56 pub user_verification: Option<String>,
57 pub authenticator_attachment: Option<String>,
58}