passkey-client 0.4.0

Webauthn client in Rust.
Documentation
//! The goal of this module is to address quirks with RP's different implementations.
//! We don't want to limit this library's functionality for all RPs because of only
//! a few RPs misbehave.

use passkey_types::webauthn::CreatedPublicKeyCredential;

/// List of quirky RPs, the default is [`Self::NotQuirky`] which maps to being a no-op
#[derive(Default)]
pub(crate) enum QuirkyRp {
    /// The RP is not known to be quirky, thus the mapping methods will be no-ops.
    #[default]
    NotQuirky,

    /// Adobe crashes on their server when they encounter the key
    /// [credProps.authenticatorDisplayName][adn] during key creation.
    ///
    /// RP_IDs:
    /// * `adobe.com`
    ///
    /// [adn]: https://w3c.github.io/webauthn/#dom-credentialpropertiesoutput-authenticatordisplayname
    Adobe,

    /// Hyatt returns an "invalid request" error when they encounter the key
    /// [credProps.authenticatorDisplayName][adn] during key creation.
    ///
    /// RP_IDs:
    /// * `hyatt.com`
    ///
    /// [adn]: https://w3c.github.io/webauthn/#dom-credentialpropertiesoutput-authenticatordisplayname
    Hyatt,
}

impl QuirkyRp {
    pub fn from_rp_id(rp_id: &str) -> Self {
        match rp_id {
            "adobe.com" => QuirkyRp::Adobe,
            "hyatt.com" => QuirkyRp::Hyatt,
            _ => QuirkyRp::NotQuirky,
        }
    }

    /// Use this after creating the response but before returning it to the function caller
    #[inline]
    pub fn map_create_credential(
        &self,
        response: CreatedPublicKeyCredential,
    ) -> CreatedPublicKeyCredential {
        match self {
            // no-op
            Self::NotQuirky => response,
            Self::Adobe | Self::Hyatt => remove_authenticator_display_name(response),
        }
    }
}

#[inline]
fn remove_authenticator_display_name(
    mut response: CreatedPublicKeyCredential,
) -> CreatedPublicKeyCredential {
    if let Some(cp) = response.client_extension_results.cred_props.as_mut() {
        cp.authenticator_display_name = None;
    }
    response
}