webauthn_rs_proto/
attest.rs1#[cfg(feature = "wasm")]
4use base64::Engine;
5use base64urlsafedata::Base64UrlSafeData;
6use serde::{Deserialize, Serialize};
7
8use crate::extensions::{RegistrationExtensionsClientOutputs, RequestRegistrationExtensions};
9use crate::options::*;
10#[cfg(feature = "wasm")]
11use crate::BASE64_ENGINE;
12
13#[derive(Debug, Serialize, Clone, Deserialize)]
15#[serde(rename_all = "camelCase")]
16pub struct PublicKeyCredentialCreationOptions {
17 pub rp: RelyingParty,
19 pub user: User,
21 pub challenge: Base64UrlSafeData,
23 pub pub_key_cred_params: Vec<PubKeyCredParams>,
25
26 #[serde(skip_serializing_if = "Option::is_none")]
28 pub timeout: Option<u32>,
29
30 #[serde(skip_serializing_if = "Option::is_none")]
32 pub exclude_credentials: Option<Vec<PublicKeyCredentialDescriptor>>,
33
34 #[serde(skip_serializing_if = "Option::is_none")]
36 pub authenticator_selection: Option<AuthenticatorSelectionCriteria>,
37
38 #[serde(skip_serializing_if = "Option::is_none")]
40 pub hints: Option<Vec<PublicKeyCredentialHints>>,
41
42 #[serde(skip_serializing_if = "Option::is_none")]
44 pub attestation: Option<AttestationConveyancePreference>,
45
46 #[serde(skip_serializing_if = "Option::is_none")]
48 pub attestation_formats: Option<Vec<AttestationFormat>>,
49
50 #[serde(skip_serializing_if = "Option::is_none")]
52 pub extensions: Option<RequestRegistrationExtensions>,
53}
54
55#[derive(Debug, Serialize, Clone, Deserialize)]
60#[serde(rename_all = "camelCase")]
61pub struct CreationChallengeResponse {
62 pub public_key: PublicKeyCredentialCreationOptions,
64}
65
66#[cfg(feature = "wasm")]
67impl From<CreationChallengeResponse> for web_sys::CredentialCreationOptions {
68 fn from(ccr: CreationChallengeResponse) -> Self {
69 use js_sys::{Array, Object, Uint8Array};
70 use wasm_bindgen::JsValue;
71
72 let chal = Uint8Array::from(ccr.public_key.challenge.as_slice());
73 let userid = Uint8Array::from(ccr.public_key.user.id.as_slice());
74
75 let jsv = serde_wasm_bindgen::to_value(&ccr).unwrap();
76
77 let pkcco = js_sys::Reflect::get(&jsv, &"publicKey".into()).unwrap();
78 js_sys::Reflect::set(&pkcco, &"challenge".into(), &chal).unwrap();
79
80 let user = js_sys::Reflect::get(&pkcco, &"user".into()).unwrap();
81 js_sys::Reflect::set(&user, &"id".into(), &userid).unwrap();
82
83 if let Some(extensions) = ccr.public_key.extensions {
84 let obj: Object = (&extensions).into();
85 js_sys::Reflect::set(&pkcco, &"extensions".into(), &obj).unwrap();
86 }
87
88 if let Some(exclude_credentials) = ccr.public_key.exclude_credentials {
89 let exclude_creds: Array = exclude_credentials
91 .iter()
92 .map(|ac| {
93 let obj = Object::new();
94 js_sys::Reflect::set(
95 &obj,
96 &"type".into(),
97 &JsValue::from_str(ac.type_.as_str()),
98 )
99 .unwrap();
100
101 js_sys::Reflect::set(&obj, &"id".into(), &Uint8Array::from(ac.id.as_slice()))
102 .unwrap();
103
104 if let Some(transports) = &ac.transports {
105 let tarray: Array = transports
106 .iter()
107 .map(|trs| serde_wasm_bindgen::to_value(trs).unwrap())
108 .collect();
109
110 js_sys::Reflect::set(&obj, &"transports".into(), &tarray).unwrap();
111 }
112
113 obj
114 })
115 .collect();
116
117 js_sys::Reflect::set(&pkcco, &"excludeCredentials".into(), &exclude_creds).unwrap();
118 }
119
120 web_sys::CredentialCreationOptions::from(jsv)
121 }
122}
123
124#[derive(Debug, Serialize, Clone, Deserialize)]
126pub struct AuthenticatorAttestationResponseRaw {
127 #[serde(rename = "attestationObject")]
129 pub attestation_object: Base64UrlSafeData,
130
131 #[serde(rename = "clientDataJSON")]
133 pub client_data_json: Base64UrlSafeData,
134
135 #[serde(default)]
137 pub transports: Option<Vec<AuthenticatorTransport>>,
138}
139
140#[derive(Debug, Clone, Deserialize, Serialize)]
148pub struct RegisterPublicKeyCredential {
149 pub id: String,
155 #[serde(rename = "rawId")]
161 pub raw_id: Base64UrlSafeData,
162 pub response: AuthenticatorAttestationResponseRaw,
164 #[serde(rename = "type")]
166 pub type_: String,
167 #[serde(default, alias = "clientExtensionResults", alias = "extensions")]
169 pub extensions: RegistrationExtensionsClientOutputs,
170}
171
172#[cfg(feature = "wasm")]
173impl From<web_sys::PublicKeyCredential> for RegisterPublicKeyCredential {
174 fn from(data: web_sys::PublicKeyCredential) -> RegisterPublicKeyCredential {
175 use js_sys::Uint8Array;
176
177 let transports = None;
179
180 let data_raw_id =
183 Uint8Array::new(&js_sys::Reflect::get(&data, &"rawId".into()).unwrap()).to_vec();
184
185 let data_response = js_sys::Reflect::get(&data, &"response".into()).unwrap();
186 let data_response_attestation_object = Uint8Array::new(
187 &js_sys::Reflect::get(&data_response, &"attestationObject".into()).unwrap(),
188 )
189 .to_vec();
190
191 let data_response_client_data_json = Uint8Array::new(
192 &js_sys::Reflect::get(&data_response, &"clientDataJSON".into()).unwrap(),
193 )
194 .to_vec();
195
196 let data_extensions = data.get_client_extension_results();
197
198 RegisterPublicKeyCredential {
199 id: BASE64_ENGINE.encode(&data_raw_id),
200 raw_id: data_raw_id.into(),
201 response: AuthenticatorAttestationResponseRaw {
202 attestation_object: data_response_attestation_object.into(),
203 client_data_json: data_response_client_data_json.into(),
204 transports,
205 },
206 type_: "public-key".to_string(),
207 extensions: data_extensions.into(),
208 }
209 }
210}