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;