use base64urlsafedata::Base64UrlSafeData;
use serde::{Deserialize, Serialize};
use crate::extensions::{RegistrationExtensionsClientOutputs, RequestRegistrationExtensions};
use crate::options::*;
#[derive(Debug, Serialize, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PublicKeyCredentialCreationOptions {
pub rp: RelyingParty,
pub user: User,
pub challenge: Base64UrlSafeData,
pub pub_key_cred_params: Vec<PubKeyCredParams>,
#[serde(skip_serializing_if = "Option::is_none")]
pub timeout: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub attestation: Option<AttestationConveyancePreference>,
#[serde(skip_serializing_if = "Option::is_none")]
pub exclude_credentials: Option<Vec<PublicKeyCredentialDescriptor>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub authenticator_selection: Option<AuthenticatorSelectionCriteria>,
#[serde(skip_serializing_if = "Option::is_none")]
pub extensions: Option<RequestRegistrationExtensions>,
}
#[derive(Debug, Serialize, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CreationChallengeResponse {
pub public_key: PublicKeyCredentialCreationOptions,
}
#[cfg(feature = "wasm")]
impl From<CreationChallengeResponse> for web_sys::CredentialCreationOptions {
fn from(ccr: CreationChallengeResponse) -> Self {
use js_sys::{Array, Object, Uint8Array};
use wasm_bindgen::JsValue;
let chal = Uint8Array::from(ccr.public_key.challenge.0.as_slice());
let userid = Uint8Array::from(ccr.public_key.user.id.0.as_slice());
let jsv = serde_wasm_bindgen::to_value(&ccr).unwrap();
let pkcco = js_sys::Reflect::get(&jsv, &"publicKey".into()).unwrap();
js_sys::Reflect::set(&pkcco, &"challenge".into(), &chal).unwrap();
let user = js_sys::Reflect::get(&pkcco, &"user".into()).unwrap();
js_sys::Reflect::set(&user, &"id".into(), &userid).unwrap();
if let Some(extensions) = ccr.public_key.extensions {
let obj: Object = (&extensions).into();
js_sys::Reflect::set(&pkcco, &"extensions".into(), &obj).unwrap();
}
if let Some(exclude_credentials) = ccr.public_key.exclude_credentials {
let exclude_creds: Array = exclude_credentials
.iter()
.map(|ac| {
let obj = Object::new();
js_sys::Reflect::set(
&obj,
&"type".into(),
&JsValue::from_str(ac.type_.as_str()),
)
.unwrap();
js_sys::Reflect::set(&obj, &"id".into(), &Uint8Array::from(ac.id.0.as_slice()))
.unwrap();
if let Some(transports) = &ac.transports {
let tarray: Array = transports
.iter()
.map(|trs| serde_wasm_bindgen::to_value(trs).unwrap())
.collect();
js_sys::Reflect::set(&obj, &"transports".into(), &tarray).unwrap();
}
obj
})
.collect();
js_sys::Reflect::set(&pkcco, &"excludeCredentials".into(), &exclude_creds).unwrap();
}
web_sys::CredentialCreationOptions::from(jsv)
}
}
#[derive(Debug, Serialize, Clone, Deserialize)]
pub struct AuthenticatorAttestationResponseRaw {
#[serde(rename = "attestationObject")]
pub attestation_object: Base64UrlSafeData,
#[serde(rename = "clientDataJSON")]
pub client_data_json: Base64UrlSafeData,
#[serde(default)]
pub transports: Option<Vec<AuthenticatorTransport>>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct RegisterPublicKeyCredential {
pub id: String,
#[serde(rename = "rawId")]
pub raw_id: Base64UrlSafeData,
pub response: AuthenticatorAttestationResponseRaw,
#[serde(rename = "type")]
pub type_: String,
#[serde(default)]
pub extensions: RegistrationExtensionsClientOutputs,
}
#[cfg(feature = "wasm")]
impl From<web_sys::PublicKeyCredential> for RegisterPublicKeyCredential {
fn from(data: web_sys::PublicKeyCredential) -> RegisterPublicKeyCredential {
use js_sys::Uint8Array;
let transports = None;
let data_raw_id =
Uint8Array::new(&js_sys::Reflect::get(&data, &"rawId".into()).unwrap()).to_vec();
let data_response = js_sys::Reflect::get(&data, &"response".into()).unwrap();
let data_response_attestation_object = Uint8Array::new(
&js_sys::Reflect::get(&data_response, &"attestationObject".into()).unwrap(),
)
.to_vec();
let data_response_client_data_json = Uint8Array::new(
&js_sys::Reflect::get(&data_response, &"clientDataJSON".into()).unwrap(),
)
.to_vec();
let data_extensions = data.get_client_extension_results();
let data_raw_id_b64 = Base64UrlSafeData(data_raw_id);
let data_response_attestation_object_b64 =
Base64UrlSafeData(data_response_attestation_object);
let data_response_client_data_json_b64 = Base64UrlSafeData(data_response_client_data_json);
RegisterPublicKeyCredential {
id: format!("{}", data_raw_id_b64),
raw_id: data_raw_id_b64,
response: AuthenticatorAttestationResponseRaw {
attestation_object: data_response_attestation_object_b64,
client_data_json: data_response_client_data_json_b64,
transports,
},
type_: "public-key".to_string(),
extensions: data_extensions.into(),
}
}
}