passkey_types/webauthn/attestation.rs
1//! Types specific to public key credential creation
2use coset::iana;
3use indexmap::IndexMap;
4use serde::{Deserialize, Serialize, Serializer};
5use std::fmt;
6#[cfg(feature = "typeshare")]
7use typeshare::typeshare;
8
9use crate::{
10 Bytes,
11 utils::serde::{
12 i64_to_iana, ignore_unknown, ignore_unknown_opt_vec, ignore_unknown_vec,
13 maybe_stringified_bool, maybe_stringified_num,
14 },
15 webauthn::{
16 AuthenticationExtensionsClientInputs, AuthenticatorAttachment, AuthenticatorTransport,
17 PublicKeyCredential, PublicKeyCredentialDescriptor, PublicKeyCredentialHints,
18 PublicKeyCredentialType, UserVerificationRequirement,
19 },
20};
21
22#[cfg(doc)]
23use crate::{
24 ctap2::{Aaguid, AttestedCredentialData, AuthenticatorData},
25 webauthn::AuthenticatorAssertionResponse,
26};
27
28/// The response to the successful creation of a PublicKeyCredential
29#[cfg_attr(feature = "typeshare", typeshare(swift = "Equatable, Hashable"))]
30pub type CreatedPublicKeyCredential = PublicKeyCredential<AuthenticatorAttestationResponse>;
31
32/// This is the expected input to [`navigator.credentials.create`] when wanting to create a webauthn
33/// credential.
34///
35/// <https://w3c.github.io/webauthn/#sctn-credentialcreationoptions-extension>
36///
37/// [`navigator.credentials.create`]: https://developer.mozilla.org/en-US/docs/Web/API/CredentialsContainer/create
38#[derive(Debug, Serialize, Deserialize)]
39#[serde(rename_all = "camelCase")]
40#[cfg_attr(feature = "typeshare", typeshare)]
41pub struct CredentialCreationOptions {
42 /// The key defining that this is a request for a webauthn credential.
43 pub public_key: PublicKeyCredentialCreationOptions,
44}
45
46/// This defines the request for creating a [`PublicKeyCredential`].
47///
48/// <https://w3c.github.io/webauthn/#dictdef-publickeycredentialcreationoptions>
49#[derive(Debug, Serialize, Deserialize)]
50#[serde(rename_all = "camelCase")]
51#[cfg_attr(feature = "typeshare", typeshare)]
52pub struct PublicKeyCredentialCreationOptions {
53 /// This member contains a name and an identifier for the [Relying Party] responsible for the request.
54 ///
55 /// [Relying Party]: https://w3c.github.io/webauthn/#relying-party
56 pub rp: PublicKeyCredentialRpEntity,
57
58 /// This member contains names and an identifier for the user account performing the registration.
59 ///
60 /// The value's [`PublicKeyCredentialUserEntity::id`] can be returned as the [`AuthenticatorAssertionResponse::user_handle`]
61 /// in some future authentication ceremonies. It is also used to overwrite existing [discoverable credentials]
62 /// that have the same [`PublicKeyCredentialRpEntity::id`] and [`PublicKeyCredentialUserEntity::id`]
63 /// on the same authenticator.
64 ///
65 /// [discoverable credentials]: https://w3c.github.io/webauthn/#discoverable-credential
66 pub user: PublicKeyCredentialUserEntity,
67
68 /// This member specifies a challenge that the authenticator signs, along with other data,
69 /// when producing an [`AttestedCredentialData`] for the newly created credential.
70 ///
71 /// See the [Cryptographic Challenges] security consideration.
72 ///
73 /// [Cryptographic Challenges]: https://w3c.github.io/webauthn/#sctn-cryptographic-challenges
74 pub challenge: Bytes,
75
76 /// This member lists the key types and signature algorithms the [Relying Party] supports, ordered
77 /// from most preferred to least preferred. The client and authenticator make a best-effort to
78 /// create a credential of the most preferred type possible. If none of the listed types can be
79 /// created, the `create()` operation MUST fail.
80 ///
81 /// Relying Parties that wish to support a wide range of authenticators SHOULD include at least
82 /// the following [COSEAlgorithmIdentifier] values:
83 ///
84 /// * [Ed25519][-8]
85 /// * [ES256][-7]
86 /// * [RS256][-257]
87 ///
88 /// Additional signature algorithms can be included as needed.
89 ///
90 /// [Relying Party]: https://w3c.github.io/webauthn/#relying-party
91 /// [COSEAlgorithmIdentifier]: https://w3c.github.io/webauthn/#typedefdef-cosealgorithmidentifier
92 /// [-8]: coset::iana::Algorithm::EdDSA
93 /// [-7]: coset::iana::Algorithm::ES256
94 /// [-257]: coset::iana::Algorithm::RS256
95 #[serde(deserialize_with = "ignore_unknown_vec")]
96 pub pub_key_cred_params: Vec<PublicKeyCredentialParameters>,
97
98 /// This OPTIONAL member specifies a time, in milliseconds, that the Relying Party is willing to
99 /// wait for the call to complete. This is treated as a hint, and MAY be overridden by the client.
100 #[serde(
101 default,
102 skip_serializing_if = "Option::is_none",
103 deserialize_with = "maybe_stringified_num"
104 )]
105 pub timeout: Option<u32>,
106
107 /// The Relying Party SHOULD use this OPTIONAL member to list any existing credentials mapped to
108 /// this user account (as identified by [`PublicKeyCredentialUserEntity::id`]). This ensures that
109 /// the new credential is not created on an authenticator that already contains a credential
110 /// mapped to this user account. If it would be, the client is requested to instead guide the
111 /// user to use a different authenticator, or return an error if that fails.
112 #[serde(
113 default,
114 skip_serializing_if = "Option::is_none",
115 deserialize_with = "ignore_unknown_opt_vec"
116 )]
117 pub exclude_credentials: Option<Vec<PublicKeyCredentialDescriptor>>,
118
119 /// The Relying Party MAY use this OPTIONAL member to specify capabilities and settings that the
120 /// authenticator MUST or SHOULD satisfy to participate in the `create()` operation.
121 ///
122 /// For more information see [`AuthenticatorSelectionCriteria`].
123 #[serde(default, skip_serializing_if = "Option::is_none")]
124 pub authenticator_selection: Option<AuthenticatorSelectionCriteria>,
125
126 /// This OPTIONAL member contains zero or more elements from [`PublicKeyCredentialHints`]` to
127 /// guide the user agent in interacting with the user.
128 ///
129 /// This field ignores unknown hint values at deserialization.
130 #[serde(
131 default,
132 skip_serializing_if = "Option::is_none",
133 deserialize_with = "ignore_unknown_opt_vec"
134 )]
135 pub hints: Option<Vec<PublicKeyCredentialHints>>,
136
137 /// The Relying Party MAY use this OPTIONAL member to specify a preference regarding attestation
138 /// conveyance. Its value SHOULD be a member of [`AttestationConveyancePreference`]. Client platforms
139 /// MUST ignore unknown values, treating an unknown value as if the member does not exist,
140 /// therefore acting as the default value.
141 ///
142 /// The default value is [`AttestationConveyancePreference::None`]
143 #[serde(default, deserialize_with = "ignore_unknown")]
144 pub attestation: AttestationConveyancePreference,
145
146 /// The Relying Party MAY use this OPTIONAL member to specify a preference regarding the attestation
147 /// statement format used by the authenticator. Values SHOULD be taken from the IANA "WebAuthn
148 /// Attestation Statement Format Identifiers" registry [IANA-WebAuthn-Registries] established by
149 /// [RFC8809]. Values are ordered from most preferable to least preferable. This parameter is
150 /// advisory and the authenticator MAY use an attestation statement not enumerated in this parameter.
151 ///
152 /// The default value is the empty list, which indicates no preference.
153 ///
154 /// [IANA-WebAuthn-Registries]: https://www.iana.org/assignments/webauthn/webauthn.xhtml#webauthn-attestation-statement-format-ids
155 /// [RFC8809]: https://www.rfc-editor.org/rfc/rfc8809
156 #[serde(
157 default,
158 skip_serializing_if = "Option::is_none",
159 deserialize_with = "ignore_unknown_opt_vec"
160 )]
161 pub attestation_formats: Option<Vec<AttestationStatementFormatIdentifiers>>,
162
163 /// The Relying Party MAY use this OPTIONAL member to provide client extension inputs requesting
164 /// additional processing by the client and authenticator. For example, the Relying Party may
165 /// request that the client returns additional information about the credential that was created.
166 #[serde(default, skip_serializing_if = "Option::is_none")]
167 pub extensions: Option<AuthenticationExtensionsClientInputs>,
168}
169
170/// This type is used to supply additional Relying Party attributes when creating a new credential.
171///
172/// <https://w3c.github.io/webauthn/#dictdef-publickeycredentialrpentity>
173#[derive(Debug, Serialize, Deserialize, Clone)]
174#[cfg_attr(feature = "typeshare", typeshare)]
175pub struct PublicKeyCredentialRpEntity {
176 /// A unique identifier for the [Relying Party] entity, which sets the [RP ID].
177 ///
178 /// If omitted, its value will be the requesting origin's [effective domain]
179 ///
180 /// [Relying Party]: https://w3c.github.io/webauthn/#relying-party
181 /// [RP ID]: https://w3c.github.io/webauthn/#rp-id
182 /// [effective domain]: https://html.spec.whatwg.org/multipage/browsers.html#concept-origin-effective-domain
183 #[serde(default, skip_serializing_if = "Option::is_none")]
184 pub id: Option<String>,
185
186 /// A human palatable identifier for the Relying Party, intended only for display. It should
187 /// follow the following guidelines.
188 ///
189 /// * Relying Parties SHOULD perform enforcement, as prescribed in Section 2.3 of [RFC8266] for
190 /// the Nickname Profile of the PRECIS FreeformClass [RFC8264], when setting name's value, or
191 /// displaying the value to the user.
192 /// * This string MAY contain language and direction metadata. Relying Parties SHOULD consider
193 /// providing this information. See [Language and Direction Encoding][Lang] about how this
194 /// metadata is encoded.
195 /// * Clients SHOULD perform enforcement, as prescribed in Section 2.3 of [RFC8266] for the
196 /// Nickname Profile of the PRECIS FreeformClass [RFC8264], on name's value prior to
197 /// displaying the value to the user or including the value as a parameter of the
198 /// authenticatorMakeCredential operation.
199 ///
200 /// [RFC8266]: https://www.rfc-editor.org/rfc/rfc8266
201 /// [RFC8264]: https://www.rfc-editor.org/rfc/rfc8264
202 /// [Lang]: https://w3c.github.io/webauthn/#sctn-strings-langdir
203 pub name: String,
204}
205
206/// This type is used to supply additional user account attributes when creating a new credential.
207///
208/// The `name` and `display_name` members should follow the following guidelines:
209///
210/// * Relying Parties SHOULD perform enforcement, as prescribed in Section 2.3 of [RFC8266] for
211/// the Nickname Profile of the PRECIS FreeformClass [RFC8264], when setting name's value, or
212/// displaying the value to the user.
213/// * This string MAY contain language and direction metadata. Relying Parties SHOULD consider
214/// providing this information. See [Language and Direction Encoding][Lang] about how this
215/// metadata is encoded.
216/// * Clients SHOULD perform enforcement, as prescribed in Section 2.3 of [RFC8266] for the
217/// Nickname Profile of the PRECIS FreeformClass [RFC8264], on name's value prior to
218/// displaying the value to the user or including the value as a parameter of the
219/// authenticatorMakeCredential operation.
220///
221/// <https://w3c.github.io/webauthn/#dictdef-publickeycredentialuserentity>
222///
223/// [RFC8266]: https://www.rfc-editor.org/rfc/rfc8266
224/// [RFC8264]: https://www.rfc-editor.org/rfc/rfc8264
225/// [Lang]: https://w3c.github.io/webauthn/#sctn-strings-langdir
226#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
227#[serde(rename_all = "camelCase")]
228#[cfg_attr(feature = "typeshare", typeshare)]
229pub struct PublicKeyCredentialUserEntity {
230 /// The user handle of the user account. A user handle is an opaque byte sequence with a maximum
231 /// size of 64 bytes, and is not meant to be displayed to the user.
232 ///
233 /// To ensure secure operation, authentication and authorization decisions MUST be made on the
234 /// basis of this id member, not the [`Self::display_name`] nor [`Self::name`] members.
235 ///
236 /// The user handle MUST NOT contain personally identifying information about the user, such as
237 /// a username or e-mail address; see [User Handle Contents] for details.
238 /// The user handle MUST NOT be empty.
239 ///
240 /// [User Handle Contents]: https://w3c.github.io/webauthn/#sctn-user-handle-privacy
241 pub id: Bytes,
242
243 /// A human-palatable name for the user account, intended only for display.
244 /// For example:
245 ///
246 /// * "Alex Müller" or
247 /// * "田中倫".
248 ///
249 /// The Relying Party SHOULD let the user choose this, and SHOULD NOT restrict the choice more
250 /// than necessary.
251 ///
252 /// Authenticators MUST accept and store a 64-byte minimum length for a `display_name` member’s
253 /// value. Authenticators MAY truncate a displayName member’s value so that it fits within 64 bytes.
254 /// See [String Truncation] about truncation and other considerations.
255 ///
256 /// [String Truncation]: https://w3c.github.io/webauthn/#sctn-strings-truncation
257 pub display_name: String,
258
259 /// A human-palatable identifier for a user account. It is intended only for display,
260 /// i.e., aiding the user in determining the difference between user accounts with similar
261 /// [`Self::display_name`]s. For example:
262 ///
263 /// * "alexm",
264 /// * "alex.mueller@example.com" or
265 /// * "+14255551234"
266 ///
267 /// Authenticators MUST accept and store a 64-byte minimum length for a `display_name` member’s
268 /// value. Authenticators MAY truncate a displayName member’s value so that it fits within 64 bytes.
269 /// See [String Truncation] about truncation and other considerations.
270 ///
271 /// [String Truncation]: https://w3c.github.io/webauthn/#sctn-strings-truncation
272 pub name: String,
273}
274
275/// This type is used to supply additional parameters when creating a new credential.
276///
277/// <https://w3c.github.io/webauthn/#dictdef-publickeycredentialparameters>
278#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
279#[cfg_attr(feature = "typeshare", typeshare)]
280pub struct PublicKeyCredentialParameters {
281 /// This member specifies the type of credential to be created. The value SHOULD be a member of
282 /// [`PublicKeyCredentialType`] but client platforms MUST ignore unknown values, ignoring any
283 /// [`PublicKeyCredentialParameters`] with an [`PublicKeyCredentialType::Unknown`] type.
284 #[serde(rename = "type", deserialize_with = "ignore_unknown")]
285 pub ty: PublicKeyCredentialType,
286
287 /// This member specifies the cryptographic signature algorithm with which the newly generated
288 /// credential will be used, and thus also the type of asymmetric key pair to be generated,
289 /// e.g., RSA or Elliptic Curve.
290 ///
291 /// > Note: we use `alg` as the latter member name, rather than spelling-out `algorithm`,
292 /// > because it will be serialized into a message to the authenticator, which may be
293 /// > sent over a low-bandwidth link.
294 #[serde(with = "i64_to_iana")]
295 #[cfg_attr(feature = "typeshare", typeshare(serialized_as = "I54"))]
296 // because i64 fails for js
297 pub alg: iana::Algorithm,
298}
299
300impl PublicKeyCredentialParameters {
301 /// Create an array with the default algorithms in case
302 /// [`PublicKeyCredentialCreationOptions::pub_key_cred_params`] comes in empty.
303 ///
304 /// This array contains:
305 /// * [`iana::Algorithm::ES256`]
306 /// * [`iana::Algorithm::RS256`]
307 ///
308 /// <https://w3c.github.io/webauthn/#ref-for-list-size>
309 pub fn default_algorithms() -> Vec<Self> {
310 vec![
311 Self {
312 ty: PublicKeyCredentialType::PublicKey,
313 alg: iana::Algorithm::ES256,
314 },
315 Self {
316 ty: PublicKeyCredentialType::PublicKey,
317 alg: iana::Algorithm::RS256,
318 },
319 ]
320 }
321}
322
323impl From<iana::Algorithm> for PublicKeyCredentialParameters {
324 fn from(value: iana::Algorithm) -> Self {
325 Self {
326 ty: PublicKeyCredentialType::PublicKey,
327 alg: value,
328 }
329 }
330}
331
332/// [Relying Parties] may use this type to specify their requirements regarding authenticator attributes.
333///
334/// <https://w3c.github.io/webauthn/#dictdef-authenticatorselectioncriteria>
335///
336/// [Relying Parties]: https://w3c.github.io/webauthn/#webauthn-relying-party
337#[derive(Debug, Default, Serialize, Deserialize)]
338#[serde(rename_all = "camelCase")]
339#[cfg_attr(feature = "typeshare", typeshare)]
340pub struct AuthenticatorSelectionCriteria {
341 /// If this member is present, eligible authenticators are filtered to be only those
342 /// authenticators attached with the specified [`AuthenticatorAttachment`] modality. If this
343 /// member is absent, then any attachment modality is acceptable. The value SHOULD be a member
344 /// of [`AuthenticatorAttachment`] but client platforms MUST ignore unknown values, treating an
345 /// unknown value (`None`) as if the member does not exist.
346 ///
347 /// See also the [`PublicKeyCredential::authenticator_attachment`] member, which can tell what
348 /// authenticator attachment modality was used in a successful `create()` or `get()` operation.
349 #[serde(
350 skip_serializing_if = "Option::is_none",
351 deserialize_with = "ignore_unknown",
352 default
353 )]
354 pub authenticator_attachment: Option<AuthenticatorAttachment>,
355
356 /// Specifies the extent to which the Relying Party desires to create a client-side [discoverable credential].
357 /// For historical reasons the naming retains the deprecated “resident” terminology.
358 /// The value SHOULD be a member of [`ResidentKeyRequirement`] but client platforms MUST ignore
359 /// unknown values, treating an unknown value (`None`) as if the member does not exist. If no
360 /// value is given then the effective value is required if [`Self::require_resident_key`] is `true`
361 /// or discouraged if it is `false` or absent.
362 ///
363 /// See [`ResidentKeyRequirement`] for the description of `resident_key`'s values and semantics.
364 ///
365 /// [discoverable credential]: https://w3c.github.io/webauthn/#client-side-discoverable-credential
366 #[serde(
367 skip_serializing_if = "Option::is_none",
368 deserialize_with = "ignore_unknown",
369 default
370 )]
371 pub resident_key: Option<ResidentKeyRequirement>,
372
373 /// This member is retained for backwards compatibility with WebAuthn Level 1 and, for historical
374 /// reasons, its naming retains the deprecated “resident” terminology for [discoverable credentials].
375 /// Relying Parties SHOULD set it to `true` if, and only if, [`Self::resident_key`] is set to required.
376 ///
377 /// [discoverable credential]: https://w3c.github.io/webauthn/#client-side-discoverable-credential
378 #[serde(default, deserialize_with = "maybe_stringified_bool")]
379 pub require_resident_key: bool,
380
381 /// This member specifies the Relying Party's requirements regarding [user verification] for the
382 /// `create()` operation. The value SHOULD be a member of [`UserVerificationRequirement`] but
383 /// client platforms MUST ignore unknown values, treating an unknown value as if the member does
384 /// not exist.
385 ///
386 /// See [`UserVerificationRequirement`] for the description of user verification's values and semantics.
387 ///
388 /// [user verification]: https://w3c.github.io/webauthn/#user-verification
389 #[serde(default, deserialize_with = "ignore_unknown")]
390 pub user_verification: UserVerificationRequirement,
391}
392
393/// This enumeration’s values describe the Relying Party's requirements for client-side
394/// [discoverable credentials] (formerly known as resident credentials or resident keys).
395///
396/// <https://w3c.github.io/webauthn/#enumdef-residentkeyrequirement>
397///
398/// [discoverable credential]: https://w3c.github.io/webauthn/#client-side-discoverable-credential
399#[derive(Debug, Deserialize, Serialize, Clone, Copy, PartialEq, Eq)]
400#[serde(rename_all = "lowercase")]
401#[cfg_attr(feature = "typeshare", typeshare(serialized_as = "String"))]
402pub enum ResidentKeyRequirement {
403 /// The Relying Party prefers creating a [server-side credential], but will accept a client-side
404 /// discoverable credential. The client and authenticator SHOULD create a server-side credential
405 /// if possible.
406 ///
407 /// > Note: A Relying Party cannot require that a created credential is a server-side credential
408 /// > and the Credential Properties Extension may not return a value for the rk property.
409 /// > Because of this, it may be the case that it does not know if a credential is a
410 /// > server-side credential or not and thus does not know whether creating a second
411 /// > credential with the same user handle will evict the first.
412 ///
413 /// [server-side credential]: https://w3c.github.io/webauthn/#server-side-credential
414 Discouraged,
415
416 /// The Relying Party strongly prefers creating a client-side discoverable credential, but will
417 /// accept a server-side credential. The client and authenticator SHOULD create a discoverable
418 /// credential if possible. For example, the client SHOULD guide the user through setting up
419 /// [user verification] if needed to create a discoverable credential. This takes precedence
420 /// over the setting of [`AuthenticatorSelectionCriteria::user_verification`]
421 ///
422 /// [user verification]: https://w3c.github.io/webauthn/#user-verification
423 Preferred,
424
425 /// The Relying Party requires a client-side discoverable credential. The client MUST return an
426 /// error if a client-side discoverable credential cannot be created.
427 Required,
428}
429
430/// Relying Parties may use this enumeration to specify their preference regarding
431/// [attestation conveyance] during credential generation.
432///
433/// <https://w3c.github.io/webauthn/#enumdef-attestationconveyancepreference>
434///
435/// [attestation conveyance]: https://w3c.github.io/webauthn/#attestation-conveyance
436#[derive(Debug, Default, Deserialize, Serialize, Clone, Copy, PartialEq, Eq)]
437#[serde(rename_all = "lowercase")]
438#[cfg_attr(feature = "typeshare", typeshare(serialized_as = "String"))]
439pub enum AttestationConveyancePreference {
440 /// The Relying Party is not interested in authenticator attestation. For example, in order to
441 /// potentially avoid having to obtain user consent to relay identifying information to the
442 /// Relying Party, or to save a roundtrip to an Attestation CA or Anonymization CA. If the
443 /// authenticator generates an attestation statement that is not a self attestation, the client
444 /// will replace it with a None attestation statement.
445 ///
446 /// This is the default, and unknown values fall back to the behavior of this value.
447 #[default]
448 None,
449
450 /// The Relying Party wants to receive a verifiable attestation statement, but allows the client
451 /// to decide how to obtain such an attestation statement. The client MAY replace an
452 /// authenticator-generated attestation statement with one generated by an Anonymization CA, in
453 /// order to protect the user’s privacy, or to assist Relying Parties with attestation
454 /// verification in a heterogeneous ecosystem.
455 ///
456 /// > Note: There is no guarantee that the Relying Party will obtain a verifiable attestation
457 /// > statement in this case. For example, in the case that the authenticator employs
458 /// > [self attestation] and the client passes the attestation statement through unmodified.
459 ///
460 /// [self attestation]: https://w3c.github.io/webauthn/#self-attestation
461 Indirect,
462
463 /// The Relying Party wants to receive the attestation statement as generated by the authenticator.
464 Direct,
465
466 /// The Relying Party wants to receive an attestation statement that may include uniquely
467 /// identifying information. This is intended for controlled deployments within an enterprise
468 /// where the organization wishes to tie registrations to specific authenticators. User agents
469 /// MUST NOT provide such an attestation unless the user agent or authenticator configuration
470 /// permits it for the requested RP ID.
471 ///
472 /// If permitted, the user agent SHOULD signal to the authenticator (at invocation time) that
473 /// enterprise attestation is requested, and convey the resulting AAGUID and attestation
474 /// statement, unaltered, to the Relying Party.
475 Enterprise,
476}
477
478/// Attestation statement formats are identified by a string, called an attestation statement format
479/// identifier, chosen by the author of the attestation statement format. The values defined below
480/// are registed in the [IANA WebAuthn regirsty][1]. See [Attestation Statement Identifiers][2] in
481/// the WebAuthn spec for more information.
482///
483/// [1]: https://www.iana.org/assignments/webauthn/webauthn.xhtml#webauthn-attestation-statement-format-ids
484/// [2]: https://w3c.github.io/webauthn/#sctn-attstn-fmt-ids
485#[derive(Debug, Default, Deserialize, Serialize, Clone, Copy, PartialEq, Eq)]
486#[serde(rename_all = "kebab-case")]
487#[cfg_attr(feature = "typeshare", typeshare)]
488pub enum AttestationStatementFormatIdentifiers {
489 /// The `packed` attestation statement format is a WebAuthn-optimized format for attestation.
490 /// It uses a very compact but still extensible encoding method. This format is implementable by
491 /// authenticators with limited resources (e.g., secure elements).
492 Packed,
493
494 /// The TPM attestation statement format returns an attestation statement in the same format as
495 /// the packed attestation statement format, although the `rawData` and `signature` fields are
496 /// computed differently.
497 Tpm,
498
499 /// Platform authenticators on versions "N", and later, may provide this proprietary
500 /// `hardware attestation` statement.
501 AndroidKey,
502
503 /// Android-based platform authenticators MAY produce an attestation statement based on the
504 /// [Android SafetyNet API](https://developer.android.com/training/safetynet/).
505 AndroidSafetynet,
506
507 /// Used with FIDO U2F authenticators.
508 FidoU2f,
509
510 /// Used with Apple devices' platform authenticators.
511 Apple,
512
513 /// Used to replace any authenticator-provided attestation statement when a WebAuthn Relying
514 /// Party indicates it does not wish to receive attestation information.
515 #[default]
516 None,
517}
518
519/// The type represents the authenticator's response to a client’s request for the creation of a new
520/// [`PublicKeyCredential`]. It contains information about the new credential that can be used to
521/// identify it for later use, and metadata that can be used by the [Relying Party] to assess the
522/// characteristics of the credential during registration.
523///
524/// <https://w3c.github.io/webauthn/#iface-authenticatorattestationresponse>
525///
526/// [Relying Party]: https://w3c.github.io/webauthn/#relying-party
527#[derive(Debug, Clone, Deserialize, Serialize)]
528#[serde(rename_all = "camelCase")]
529#[cfg_attr(feature = "typeshare", typeshare(swift = "Equatable, Hashable"))]
530pub struct AuthenticatorAttestationResponse {
531 /// This attribute contains the JSON serialization of [`CollectedClientData`] passed to the
532 /// authenticator by the client in order to generate this credential. The exact JSON serialization
533 /// MUST be preserved, as the hash of the serialized client data has been computed over it.
534 #[serde(rename = "clientDataJSON")]
535 pub client_data_json: Bytes,
536
537 /// This is the authenticator Data that is contained within Attestation Object.
538 pub authenticator_data: Bytes,
539
540 /// This is the DER [SubjectPublicKeyInfo] of the new credential. Or None if it is not available.
541 ///
542 /// [SubjectPublicKeyInfo]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.7
543 #[serde(skip_serializing_if = "Option::is_none")]
544 pub public_key: Option<Bytes>,
545
546 /// This is the [CoseAlgorithmIdentifier] of the new credential
547 ///
548 /// [CoseAlgorithmIdentifier]: https://w3c.github.io/webauthn/#typedefdef-cosealgorithmidentifier
549 #[cfg_attr(feature = "typeshare", typeshare(serialized_as = "I54"))]
550 // ^ because i64 fails for js
551 pub public_key_algorithm: i64,
552
553 /// This attribute contains an attestation object, which is opaque to, and cryptographically
554 /// protected against tampering by, the client. The attestation object contains both
555 /// [`AuthenticatorData`] and an attestation statement. The former contains the [`Aaguid`], a unique
556 /// credential ID, and the [`AttestedCredentialData`] of the credential's public key. The contents
557 /// of the attestation statement are determined by the attestation statement format used by the
558 /// authenticator. It also contains any additional information that the Relying Party's server
559 /// requires to validate the attestation statement, as well as to decode and validate the
560 /// [`AuthenticatorData`] along with the JSON-compatible serialization of client data.
561 pub attestation_object: Bytes,
562
563 /// This field contains a sequence of zero or more unique [`AuthenticatorTransport`] values in
564 /// lexicographical order. These values are the transports that the authenticator is believed to
565 /// support, or an empty sequence if the information is unavailable. The values SHOULD be
566 /// members of [`AuthenticatorTransport`] but Relying Parties SHOULD accept and store unknown values.
567 #[serde(default, skip_serializing_if = "Option::is_none")]
568 pub transports: Option<Vec<AuthenticatorTransport>>,
569}
570
571/// The client data represents the contextual bindings of both the Relying Party and the client.
572/// It is a key-value mapping whose keys are strings. Values can be any type that has a valid
573/// encoding in JSON.
574///
575/// > Note: The [`CollectedClientData`] may be extended in the future. Therefore it’s critical when
576/// > parsing to be tolerant of unknown keys and of any reordering of the keys
577///
578/// This struct conforms to the JSON byte serialization format expected of `CollectedClientData`,
579/// detailed in section [5.8.1.1 Serialization] of the WebAuthn spec. Namely the following
580/// requirements:
581///
582/// * `type`, `challenge`, `origin`, `crossOrigin` must always be present in the serialized format
583/// _in that order_.
584/// * Any extra parameters must keep the order in which they were used in the signature, hence the
585/// use of [`IndexMap`].
586///
587/// <https://w3c.github.io/webauthn/#dictionary-client-data>
588///
589/// [5.8.1.1 Serialization]: https://w3c.github.io/webauthn/#clientdatajson-serialization
590#[derive(Debug, Clone, Serialize, Deserialize)]
591#[serde(rename_all = "camelCase")]
592pub struct CollectedClientData<E = ()>
593where
594 E: Clone + Serialize,
595{
596 /// This member contains the value [`ClientDataType::Create`] when creating new credentials, and
597 /// [`ClientDataType::Get`] when getting an assertion from an existing credential. The purpose
598 /// of this member is to prevent certain types of signature confusion attacks (where an attacker
599 /// substitutes one legitimate signature for another).
600 #[serde(rename = "type")]
601 pub ty: ClientDataType,
602
603 /// This member contains the base64url encoding of the challenge provided by the Relying Party.
604 /// See the [Cryptographic Challenges] security consideration.
605 ///
606 /// [Cryptographic Challenges]: https://w3c.github.io/webauthn/#sctn-cryptographic-challenges
607 pub challenge: String,
608
609 /// This member contains the fully qualified origin of the requester, as provided to the
610 /// authenticator by the client, in the syntax defined by [RFC6454].
611 ///
612 /// [RFC6454]: https://www.rfc-editor.org/rfc/rfc6454
613 pub origin: String,
614
615 /// This OPTIONAL member contains the inverse of the sameOriginWithAncestors argument value that
616 /// was passed into the internal method
617 #[serde(default, serialize_with = "truthiness")]
618 pub cross_origin: Option<bool>,
619
620 /// CollectedClientData can be extended by the user of this library, this accounts for
621 /// keys that are unknown to the library, but may be known to the user.
622 #[serde(flatten)]
623 pub extra_data: E,
624
625 /// CollectedClientData can be extended in the future, this accounts for unknown keys
626 /// Uses an IndexMap to preserve order of keys for JSON byte serialization
627 #[serde(flatten)]
628 pub unknown_keys: IndexMap<String, serde_json::value::Value>,
629}
630
631fn truthiness<S>(cross_origin: &Option<bool>, ser: S) -> Result<S::Ok, S::Error>
632where
633 S: Serializer,
634{
635 ser.serialize_bool(cross_origin.filter(|b| *b).is_some())
636}
637
638/// Used to limit the values of [`CollectedClientData::ty`] and serializes to static strings.
639#[derive(Debug, Deserialize, Serialize, Clone, Copy, PartialEq, Eq)]
640#[cfg_attr(feature = "typeshare", typeshare)]
641pub enum ClientDataType {
642 /// Serializes to the string `"webauthn.create"`
643 #[serde(rename = "webauthn.create")]
644 Create,
645
646 /// Serializes to the string `"webauthn.get"`
647 #[serde(rename = "webauthn.get")]
648 Get,
649
650 /// Serializes to the string `"payment.get"`
651 /// This variant is part of the Secure Payment Confirmation specification
652 ///
653 /// See <https://www.w3.org/TR/secure-payment-confirmation/#client-extension-processing-authentication>
654 #[serde(rename = "payment.get")]
655 PaymentGet,
656}
657
658impl fmt::Display for ClientDataType {
659 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
660 let renamed = serde_json::to_string(self).unwrap();
661 write!(f, "{}", renamed.trim_matches('"'))
662 }
663}
664
665#[cfg(test)]
666mod tests;