webauthn-rs-proto

Patched webauthn-rs-proto (https://crates.io/crates/webauthn-rs-proto) that adds support for Ed25519.
git clone https://git.philomathiclife.com/repos/webauthn-rs-proto
Log | Files | Refs | README | LICENSE

options.rs (11155B)


      1 //! Types that define options as to how an authenticator may interact with
      2 //! with the server.
      3 
      4 use base64urlsafedata::Base64UrlSafeData;
      5 use serde::{Deserialize, Serialize};
      6 use std::{collections::BTreeMap, str::FromStr};
      7 
      8 /// A credential ID type. At the moment this is a vector of bytes, but
      9 /// it could also be a future change for this to be base64 string instead.
     10 ///
     11 /// If changed, this would likely be a major library version change.
     12 pub type CredentialID = Base64UrlSafeData;
     13 
     14 /// Defines the User Authenticator Verification policy. This is documented
     15 /// <https://w3c.github.io/webauthn/#enumdef-userverificationrequirement>, and each
     16 /// variant lists it's effects.
     17 ///
     18 /// To be clear, Verification means that the Authenticator perform extra or supplementary
     19 /// interaction with the user to verify who they are. An example of this is Apple Touch Id
     20 /// required a fingerprint to be verified, or a yubico device requiring a pin in addition to
     21 /// a touch event.
     22 ///
     23 /// An example of a non-verified interaction is a yubico device with no pin where touch is
     24 /// the only interaction - we only verify a user is present, but we don't have extra details
     25 /// to the legitimacy of that user.
     26 ///
     27 /// As UserVerificationPolicy is *only* used in credential registration, this stores the
     28 /// verification state of the credential in the persisted credential. These persisted
     29 /// credentials define which UserVerificationPolicy is issued during authentications.
     30 ///
     31 /// ⚠️  WARNING - discouraged is marked with a warning, as in some cases, some authenticators
     32 /// will FORCE verification during registration but NOT during authentication. This means
     33 /// that is is NOT possible assert verification has been bypassed or not from the server
     34 /// viewpoint, and to the user it may create confusion about when verification is or is
     35 /// not required.
     36 #[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
     37 #[allow(non_camel_case_types)]
     38 #[serde(rename_all = "lowercase")]
     39 pub enum UserVerificationPolicy {
     40     /// Require User Verification bit to be set, and fail the registration or authentication
     41     /// if false. If the authenticator is not able to perform verification, it may not be
     42     /// usable with this policy.
     43     Required,
     44     /// TO FILL IN
     45     #[default]
     46     #[serde(rename = "preferred")]
     47     Preferred,
     48     /// TO FILL IN
     49     #[serde(rename = "discouraged")]
     50     Discouraged_DO_NOT_USE,
     51 }
     52 
     53 /// Relying Party Entity
     54 #[derive(Debug, Serialize, Clone, Deserialize)]
     55 #[serde(rename_all = "camelCase")]
     56 pub struct RelyingParty {
     57     /// The name of the relying party.
     58     pub name: String,
     59     /// The id of the relying party.
     60     pub id: String,
     61     // Note: "icon" is deprecated: https://github.com/w3c/webauthn/pull/1337
     62 }
     63 
     64 /// User Entity
     65 #[derive(Debug, Serialize, Clone, Deserialize)]
     66 #[serde(rename_all = "camelCase")]
     67 pub struct User {
     68     /// The user's id in base64 form. This MUST be a unique id, and
     69     /// must NOT contain personally identifying information, as this value can NEVER
     70     /// be changed. If in doubt, use a UUID.
     71     pub id: Base64UrlSafeData,
     72     /// A detailed name for the account, such as an email address. This value
     73     /// **can** change, so **must not** be used as a primary key.
     74     pub name: String,
     75     /// The user's preferred name for display. This value **can** change, so
     76     /// **must not** be used as a primary key.
     77     pub display_name: String,
     78     // Note: "icon" is deprecated: https://github.com/w3c/webauthn/pull/1337
     79 }
     80 
     81 /// Public key cryptographic parameters
     82 #[derive(Debug, Serialize, Clone, Deserialize)]
     83 pub struct PubKeyCredParams {
     84     /// The type of public-key credential.
     85     #[serde(rename = "type")]
     86     pub type_: String,
     87     /// The algorithm in use defined by COSE.
     88     pub alg: i64,
     89 }
     90 
     91 /// <https://www.w3.org/TR/webauthn/#enumdef-attestationconveyancepreference>
     92 #[derive(Debug, Serialize, Clone, Deserialize)]
     93 #[serde(rename_all = "lowercase")]
     94 pub enum AttestationConveyancePreference {
     95     /// Do not request attestation.
     96     /// <https://www.w3.org/TR/webauthn/#dom-attestationconveyancepreference-none>
     97     None,
     98 
     99     /// Request attestation in a semi-anonymized form.
    100     /// <https://www.w3.org/TR/webauthn/#dom-attestationconveyancepreference-indirect>
    101     Indirect,
    102 
    103     /// Request attestation in a direct form.
    104     /// <https://www.w3.org/TR/webauthn/#dom-attestationconveyancepreference-direct>
    105     Direct,
    106 }
    107 
    108 /// <https://www.w3.org/TR/webauthn/#enumdef-authenticatortransport>
    109 #[derive(Debug, Serialize, Clone, Deserialize, PartialEq, Eq)]
    110 #[serde(rename_all = "lowercase")]
    111 #[allow(unused)]
    112 pub enum AuthenticatorTransport {
    113     /// <https://www.w3.org/TR/webauthn/#dom-authenticatortransport-usb>
    114     Usb,
    115     /// <https://www.w3.org/TR/webauthn/#dom-authenticatortransport-nfc>
    116     Nfc,
    117     /// <https://www.w3.org/TR/webauthn/#dom-authenticatortransport-ble>
    118     Ble,
    119     /// <https://www.w3.org/TR/webauthn/#dom-authenticatortransport-internal>
    120     Internal,
    121     /// Hybrid transport, formerly caBLE. Part of the level 3 draft specification.
    122     /// <https://w3c.github.io/webauthn/#dom-authenticatortransport-hybrid>
    123     Hybrid,
    124     /// Test transport; used for Windows 10.
    125     Test,
    126 }
    127 
    128 impl FromStr for AuthenticatorTransport {
    129     type Err = ();
    130     fn from_str(s: &str) -> Result<Self, Self::Err> {
    131         use AuthenticatorTransport::*;
    132 
    133         // "internal" is longest (8 chars)
    134         if s.len() > 8 {
    135             return Err(());
    136         }
    137 
    138         Ok(match s.to_ascii_lowercase().as_str() {
    139             "usb" => Usb,
    140             "nfc" => Nfc,
    141             "ble" => Ble,
    142             "internal" => Internal,
    143             "test" => Test,
    144             "hybrid" => Hybrid,
    145             &_ => return Err(()),
    146         })
    147     }
    148 }
    149 
    150 impl ToString for AuthenticatorTransport {
    151     fn to_string(&self) -> String {
    152         use AuthenticatorTransport::*;
    153         match self {
    154             Usb => "usb",
    155             Nfc => "nfc",
    156             Ble => "ble",
    157             Internal => "internal",
    158             Test => "test",
    159             Hybrid => "hybrid",
    160         }
    161         .to_string()
    162     }
    163 }
    164 
    165 /// <https://www.w3.org/TR/webauthn/#dictdef-publickeycredentialdescriptor>
    166 #[derive(Debug, Serialize, Clone, Deserialize)]
    167 pub struct PublicKeyCredentialDescriptor {
    168     /// The type of credential
    169     #[serde(rename = "type")]
    170     pub type_: String,
    171     /// The credential id.
    172     pub id: Base64UrlSafeData,
    173     /// The allowed transports for this credential. Note this is a hint, and is NOT
    174     /// enforced.
    175     #[serde(skip_serializing_if = "Option::is_none")]
    176     pub transports: Option<Vec<AuthenticatorTransport>>,
    177 }
    178 
    179 /// The authenticator attachment hint. This is NOT enforced, and is only used
    180 /// to help a user select a relevant authenticator type.
    181 ///
    182 /// <https://www.w3.org/TR/webauthn/#attachment>
    183 #[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)]
    184 pub enum AuthenticatorAttachment {
    185     /// Request a device that is part of the machine aka inseperable.
    186     /// <https://www.w3.org/TR/webauthn/#attachment>
    187     #[serde(rename = "platform")]
    188     Platform,
    189     /// Request a device that can be seperated from the machine aka an external token.
    190     /// <https://www.w3.org/TR/webauthn/#attachment>
    191     #[serde(rename = "cross-platform")]
    192     CrossPlatform,
    193 }
    194 
    195 /// <https://www.w3.org/TR/webauthn/#dictdef-authenticatorselectioncriteria>
    196 #[derive(Debug, Serialize, Clone, Deserialize)]
    197 #[serde(rename_all = "camelCase")]
    198 pub struct AuthenticatorSelectionCriteria {
    199     /// How the authenticator should be attached to the client machine.
    200     /// Note this is only a hint. It is not enforced in anyway shape or form.
    201     /// <https://www.w3.org/TR/webauthn/#attachment>
    202     #[serde(skip_serializing_if = "Option::is_none")]
    203     pub authenticator_attachment: Option<AuthenticatorAttachment>,
    204 
    205     /// Hint to the credential to create a resident key. Note this can not be enforced
    206     /// or validated, so the authenticator may choose to ignore this parameter.
    207     /// <https://www.w3.org/TR/webauthn/#resident-credential>
    208     pub require_resident_key: bool,
    209 
    210     /// The user verification level to request during registration. Depending on if this
    211     /// authenticator provides verification may affect future interactions as this is
    212     /// associated to the credential during registration.
    213     pub user_verification: UserVerificationPolicy,
    214 }
    215 
    216 /// A descriptor of a credential that can be used.
    217 #[derive(Debug, Serialize, Clone, Deserialize)]
    218 pub struct AllowCredentials {
    219     #[serde(rename = "type")]
    220     /// The type of credential.
    221     pub type_: String,
    222     /// The id of the credential.
    223     pub id: Base64UrlSafeData,
    224     /// <https://www.w3.org/TR/webauthn/#transport>
    225     /// may be usb, nfc, ble, internal
    226     #[serde(skip_serializing_if = "Option::is_none")]
    227     pub transports: Option<Vec<AuthenticatorTransport>>,
    228 }
    229 
    230 /// The data collected and hashed in the operation.
    231 /// <https://www.w3.org/TR/webauthn-2/#dictdef-collectedclientdata>
    232 #[derive(Debug, Serialize, Clone, Deserialize)]
    233 pub struct CollectedClientData {
    234     /// The credential type
    235     #[serde(rename = "type")]
    236     pub type_: String,
    237     /// The challenge.
    238     pub challenge: Base64UrlSafeData,
    239     /// The rp origin as the browser understood it.
    240     pub origin: url::Url,
    241     /// The inverse of the sameOriginWithAncestors argument value that was
    242     /// passed into the internal method.
    243     #[serde(rename = "crossOrigin", skip_serializing_if = "Option::is_none")]
    244     pub cross_origin: Option<bool>,
    245     /// tokenBinding.
    246     #[serde(rename = "tokenBinding")]
    247     pub token_binding: Option<TokenBinding>,
    248     /// This struct be extended, so it's important to be tolerant of unknown
    249     /// keys.
    250     #[serde(flatten)]
    251     pub unknown_keys: BTreeMap<String, serde_json::value::Value>,
    252 }
    253 
    254 /*
    255 impl TryFrom<&[u8]> for CollectedClientData {
    256     type Error = WebauthnError;
    257     fn try_from(data: &[u8]) -> Result<CollectedClientData, WebauthnError> {
    258         let ccd: CollectedClientData =
    259             serde_json::from_slice(data).map_err(WebauthnError::ParseJSONFailure)?;
    260         Ok(ccd)
    261     }
    262 }
    263 */
    264 
    265 /// Token binding
    266 #[derive(Debug, Clone, Deserialize, Serialize)]
    267 pub struct TokenBinding {
    268     /// status
    269     pub status: String,
    270     /// id
    271     pub id: Option<String>,
    272 }
    273 
    274 #[cfg(test)]
    275 mod test {
    276     use std::str::FromStr;
    277 
    278     use crate::AuthenticatorTransport;
    279 
    280     #[test]
    281     fn test_authenticator_transports() {
    282         let cases: [(&str, AuthenticatorTransport); 6] = [
    283             ("ble", AuthenticatorTransport::Ble),
    284             ("internal", AuthenticatorTransport::Internal),
    285             ("nfc", AuthenticatorTransport::Nfc),
    286             ("usb", AuthenticatorTransport::Usb),
    287             ("test", AuthenticatorTransport::Test),
    288             ("hybrid", AuthenticatorTransport::Hybrid),
    289         ];
    290 
    291         for (s, t) in cases {
    292             assert_eq!(
    293                 t,
    294                 AuthenticatorTransport::from_str(s).expect("unknown authenticatorTransport")
    295             );
    296             assert_eq!(s, AuthenticatorTransport::to_string(&t));
    297         }
    298 
    299         assert!(AuthenticatorTransport::from_str("fake fake").is_err());
    300     }
    301 }