Skip to main content

alibi_plugins/passkey/
options.rs

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