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

attest.rs (8379B)


      1 //! Types related to attestation (Registration)
      2 
      3 use base64urlsafedata::Base64UrlSafeData;
      4 use serde::{Deserialize, Serialize};
      5 
      6 use crate::extensions::{RegistrationExtensionsClientOutputs, RequestRegistrationExtensions};
      7 use crate::options::*;
      8 
      9 /// <https://w3c.github.io/webauthn/#dictionary-makecredentialoptions>
     10 #[derive(Debug, Serialize, Clone, Deserialize)]
     11 #[serde(rename_all = "camelCase")]
     12 pub struct PublicKeyCredentialCreationOptions {
     13     /// The relying party
     14     pub rp: RelyingParty,
     15     /// The user.
     16     pub user: User,
     17     /// The one-time challenge for the credential to sign.
     18     pub challenge: Base64UrlSafeData,
     19     /// The set of cryptographic types allowed by this server.
     20     pub pub_key_cred_params: Vec<PubKeyCredParams>,
     21 
     22     /// The timeout for the authenticator to stop accepting the operation
     23     #[serde(skip_serializing_if = "Option::is_none")]
     24     pub timeout: Option<u32>,
     25 
     26     /// The requested attestation level from the device.
     27     #[serde(skip_serializing_if = "Option::is_none")]
     28     pub attestation: Option<AttestationConveyancePreference>,
     29 
     30     /// Credential ID's that are excluded from being able to be registered.
     31     #[serde(skip_serializing_if = "Option::is_none")]
     32     pub exclude_credentials: Option<Vec<PublicKeyCredentialDescriptor>>,
     33 
     34     /// Criteria defining which authenticators may be used in this operation.
     35     #[serde(skip_serializing_if = "Option::is_none")]
     36     pub authenticator_selection: Option<AuthenticatorSelectionCriteria>,
     37 
     38     /// Non-standard extensions that may be used by the browser/authenticator.
     39     #[serde(skip_serializing_if = "Option::is_none")]
     40     pub extensions: Option<RequestRegistrationExtensions>,
     41 }
     42 
     43 /// A JSON serializable challenge which is issued to the user's webbrowser
     44 /// for handling. This is meant to be opaque, that is, you should not need
     45 /// to inspect or alter the content of the struct - you should serialise it
     46 /// and transmit it to the client only.
     47 #[derive(Debug, Serialize, Clone, Deserialize)]
     48 #[serde(rename_all = "camelCase")]
     49 pub struct CreationChallengeResponse {
     50     /// The options.
     51     pub public_key: PublicKeyCredentialCreationOptions,
     52 }
     53 
     54 #[cfg(feature = "wasm")]
     55 impl From<CreationChallengeResponse> for web_sys::CredentialCreationOptions {
     56     fn from(ccr: CreationChallengeResponse) -> Self {
     57         use js_sys::{Array, Object, Uint8Array};
     58         use wasm_bindgen::JsValue;
     59 
     60         let chal = Uint8Array::from(ccr.public_key.challenge.0.as_slice());
     61         let userid = Uint8Array::from(ccr.public_key.user.id.0.as_slice());
     62 
     63         let jsv = serde_wasm_bindgen::to_value(&ccr).unwrap();
     64 
     65         let pkcco = js_sys::Reflect::get(&jsv, &"publicKey".into()).unwrap();
     66         js_sys::Reflect::set(&pkcco, &"challenge".into(), &chal).unwrap();
     67 
     68         let user = js_sys::Reflect::get(&pkcco, &"user".into()).unwrap();
     69         js_sys::Reflect::set(&user, &"id".into(), &userid).unwrap();
     70 
     71         if let Some(extensions) = ccr.public_key.extensions {
     72             let obj: Object = (&extensions).into();
     73             js_sys::Reflect::set(&pkcco, &"extensions".into(), &obj).unwrap();
     74         }
     75 
     76         if let Some(exclude_credentials) = ccr.public_key.exclude_credentials {
     77             // There must be an array of these in the jsv ...
     78             let exclude_creds: Array = exclude_credentials
     79                 .iter()
     80                 .map(|ac| {
     81                     let obj = Object::new();
     82                     js_sys::Reflect::set(
     83                         &obj,
     84                         &"type".into(),
     85                         &JsValue::from_str(ac.type_.as_str()),
     86                     )
     87                     .unwrap();
     88 
     89                     js_sys::Reflect::set(&obj, &"id".into(), &Uint8Array::from(ac.id.0.as_slice()))
     90                         .unwrap();
     91 
     92                     if let Some(transports) = &ac.transports {
     93                         let tarray: Array = transports
     94                             .iter()
     95                             .map(|trs| serde_wasm_bindgen::to_value(trs).unwrap())
     96                             .collect();
     97 
     98                         js_sys::Reflect::set(&obj, &"transports".into(), &tarray).unwrap();
     99                     }
    100 
    101                     obj
    102                 })
    103                 .collect();
    104 
    105             js_sys::Reflect::set(&pkcco, &"excludeCredentials".into(), &exclude_creds).unwrap();
    106         }
    107 
    108         web_sys::CredentialCreationOptions::from(jsv)
    109     }
    110 }
    111 
    112 /// <https://w3c.github.io/webauthn/#authenticatorattestationresponse>
    113 #[derive(Debug, Serialize, Clone, Deserialize)]
    114 pub struct AuthenticatorAttestationResponseRaw {
    115     /// <https://w3c.github.io/webauthn/#dom-authenticatorattestationresponse-attestationobject>
    116     #[serde(rename = "attestationObject")]
    117     pub attestation_object: Base64UrlSafeData,
    118 
    119     /// <https://w3c.github.io/webauthn/#dom-authenticatorresponse-clientdatajson>
    120     #[serde(rename = "clientDataJSON")]
    121     pub client_data_json: Base64UrlSafeData,
    122 
    123     /// <https://w3c.github.io/webauthn/#dom-authenticatorattestationresponse-gettransports>
    124     #[serde(default)]
    125     pub transports: Option<Vec<AuthenticatorTransport>>,
    126 }
    127 
    128 /// A client response to a registration challenge. This contains all required
    129 /// information to asses and assert trust in a credentials legitimacy, followed
    130 /// by registration to a user.
    131 ///
    132 /// You should not need to handle the inner content of this structure - you should
    133 /// provide this to the correctly handling function of Webauthn only.
    134 /// <https://w3c.github.io/webauthn/#iface-pkcredential>
    135 #[derive(Debug, Clone, Deserialize, Serialize)]
    136 pub struct RegisterPublicKeyCredential {
    137     /// The id of the PublicKey credential, likely in base64.
    138     ///
    139     /// This is NEVER actually
    140     /// used in a real registration, because the true credential ID is taken from the
    141     /// attestation data.
    142     pub id: String,
    143     /// The id of the credential, as binary.
    144     ///
    145     /// This is NEVER actually
    146     /// used in a real registration, because the true credential ID is taken from the
    147     /// attestation data.
    148     #[serde(rename = "rawId")]
    149     pub raw_id: Base64UrlSafeData,
    150     /// <https://w3c.github.io/webauthn/#dom-publickeycredential-response>
    151     pub response: AuthenticatorAttestationResponseRaw,
    152     /// The type of credential.
    153     #[serde(rename = "type")]
    154     pub type_: String,
    155     /// Unsigned Client processed extensions.
    156     #[serde(default)]
    157     pub extensions: RegistrationExtensionsClientOutputs,
    158 }
    159 
    160 #[cfg(feature = "wasm")]
    161 impl From<web_sys::PublicKeyCredential> for RegisterPublicKeyCredential {
    162     fn from(data: web_sys::PublicKeyCredential) -> RegisterPublicKeyCredential {
    163         use js_sys::Uint8Array;
    164 
    165         // is_user_verifying_platform_authenticator_available
    166 
    167         // AuthenticatorAttestationResponse has getTransports but web_sys isn't exposing it?
    168         let transports = None;
    169 
    170         // First, we have to b64 some data here.
    171         // data.raw_id
    172         let data_raw_id =
    173             Uint8Array::new(&js_sys::Reflect::get(&data, &"rawId".into()).unwrap()).to_vec();
    174 
    175         let data_response = js_sys::Reflect::get(&data, &"response".into()).unwrap();
    176         let data_response_attestation_object = Uint8Array::new(
    177             &js_sys::Reflect::get(&data_response, &"attestationObject".into()).unwrap(),
    178         )
    179         .to_vec();
    180 
    181         let data_response_client_data_json = Uint8Array::new(
    182             &js_sys::Reflect::get(&data_response, &"clientDataJSON".into()).unwrap(),
    183         )
    184         .to_vec();
    185 
    186         let data_extensions = data.get_client_extension_results();
    187 
    188         // Now we can convert to the base64 values for json.
    189         let data_raw_id_b64 = Base64UrlSafeData(data_raw_id);
    190 
    191         let data_response_attestation_object_b64 =
    192             Base64UrlSafeData(data_response_attestation_object);
    193 
    194         let data_response_client_data_json_b64 = Base64UrlSafeData(data_response_client_data_json);
    195 
    196         RegisterPublicKeyCredential {
    197             id: format!("{}", data_raw_id_b64),
    198             raw_id: data_raw_id_b64,
    199             response: AuthenticatorAttestationResponseRaw {
    200                 attestation_object: data_response_attestation_object_b64,
    201                 client_data_json: data_response_client_data_json_b64,
    202                 transports,
    203             },
    204             type_: "public-key".to_string(),
    205             extensions: data_extensions.into(),
    206         }
    207     }
    208 }