diff --git a/passkey-client/Cargo.toml b/passkey-client/Cargo.toml index 8b154ef..bd6b818 100644 --- a/passkey-client/Cargo.toml +++ b/passkey-client/Cargo.toml @@ -19,6 +19,7 @@ workspace = true android-asset-validation = ["dep:nom"] testable = ["dep:mockall"] tokio = ["dep:tokio"] +typeshare = ["passkey-types/typeshare", "dep:typeshare"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -36,7 +37,7 @@ reqwest = { version = "0.12", default-features = false, optional = true } serde = { version = "1", features = ["derive"] } serde_json = "1" tokio = { version = "1", features = ["sync"], optional = true } -typeshare = "1" +typeshare = { version = "1", optional = true } url = "2" [dev-dependencies] diff --git a/passkey-client/src/lib.rs b/passkey-client/src/lib.rs index a30f95a..2fd0982 100644 --- a/passkey-client/src/lib.rs +++ b/passkey-client/src/lib.rs @@ -30,6 +30,7 @@ use passkey_types::{ }, }; use serde::Serialize; +#[cfg(feature = "typeshare")] use typeshare::typeshare; use url::Url; @@ -44,7 +45,7 @@ pub use self::rp_id_verifier::android::{UnverifiedAssetLink, ValidationError, va #[cfg(test)] mod tests; -#[typeshare] +#[cfg_attr(feature = "typeshare", typeshare)] #[derive(Debug, serde::Serialize, PartialEq, Eq)] #[serde(tag = "type", content = "content")] /// Errors produced by Webauthn Operations. diff --git a/passkey-types/Cargo.toml b/passkey-types/Cargo.toml index 620ff0c..ef669d2 100644 --- a/passkey-types/Cargo.toml +++ b/passkey-types/Cargo.toml @@ -19,6 +19,7 @@ workspace = true default = [] serialize_bytes_as_base64_string = [] testable = ["dep:p256"] +typeshare = ["dep:typeshare"] [dependencies] bitflags = "2" @@ -31,7 +32,7 @@ serde = { version = "1", features = ["derive"] } serde_json = { version = "1", features = ["preserve_order"] } sha2 = "0.10" strum = { version = "0.27", features = ["derive"] } -typeshare = "1" +typeshare = { version = "1", optional = true } url = { version = "2", features = ["serde"] } zeroize = { version = "1", features = ["zeroize_derive"] } # TODO: investigate rolling our own IANA listings and COSE keys diff --git a/passkey-types/src/utils/bytes.rs b/passkey-types/src/utils/bytes.rs index d32eea5..5c6fd64 100644 --- a/passkey-types/src/utils/bytes.rs +++ b/passkey-types/src/utils/bytes.rs @@ -1,6 +1,7 @@ use std::ops::{Deref, DerefMut}; use serde::{Deserialize, Deserializer, Serialize, de::Visitor}; +#[cfg(feature = "typeshare")] use typeshare::typeshare; use super::encoding; @@ -16,7 +17,7 @@ use super::encoding; /// This will use an array of numbers for JSON, and a byte string in CBOR for example. /// /// It also supports deserializing from `base64` and `base64url` formatted strings. -#[typeshare(transparent)] +#[cfg_attr(feature = "typeshare", typeshare(transparent))] #[derive(Debug, Default, PartialEq, Eq, Clone, Hash)] #[repr(transparent)] pub struct Bytes(Vec); diff --git a/passkey-types/src/webauthn.rs b/passkey-types/src/webauthn.rs index f6277d6..047fba2 100644 --- a/passkey-types/src/webauthn.rs +++ b/passkey-types/src/webauthn.rs @@ -3,6 +3,7 @@ //! [WebAuthn Level 3]: https://w3c.github.io/webauthn use serde::{Deserialize, Serialize}; +#[cfg(feature = "typeshare")] use typeshare::typeshare; use crate::{Bytes, utils::serde::ignore_unknown}; @@ -38,9 +39,12 @@ impl AuthenticatorResponse for AuthenticatorAttestationResponse {} /// #[derive(Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] -#[typeshare( - swift = "Equatable, Hashable", - swiftGenericConstraints = "R: Equatable & Hashable" +#[cfg_attr( + feature = "typeshare", + typeshare( + swift = "Equatable, Hashable", + swiftGenericConstraints = "R: Equatable & Hashable" + ) )] pub struct PublicKeyCredential { /// The id contains the credential ID, chosen by the authenticator. This is usually the base64url diff --git a/passkey-types/src/webauthn/assertion.rs b/passkey-types/src/webauthn/assertion.rs index 7615d77..4c0bd5d 100644 --- a/passkey-types/src/webauthn/assertion.rs +++ b/passkey-types/src/webauthn/assertion.rs @@ -1,6 +1,7 @@ //! Types used for public key authentication use serde::{Deserialize, Serialize}; +#[cfg(feature = "typeshare")] use typeshare::typeshare; use crate::{ @@ -22,7 +23,7 @@ use crate::{ }; /// The response to the successful authentication of a [`PublicKeyCredential`] -#[typeshare(swift = "Equatable, Hashable")] +#[cfg_attr(feature = "typeshare", typeshare(swift = "Equatable, Hashable"))] pub type AuthenticatedPublicKeyCredential = PublicKeyCredential; /// This type supplies `get()` requests with the data it needs to generate an assertion. @@ -31,7 +32,7 @@ pub type AuthenticatedPublicKeyCredential = PublicKeyCredential #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -#[typeshare] +#[cfg_attr(feature = "typeshare", typeshare)] pub struct PublicKeyCredentialRequestOptions { /// This member specifies a challenge that the authenticator signs, along with other data, when /// producing an authentication assertion. See the [Cryptographic Challenges] security consideration. @@ -173,7 +174,7 @@ pub struct PublicKeyCredentialRequestOptions { /// [`navigator.credentials.get`]: https://developer.mozilla.org/en-US/docs/Web/API/CredentialsContainer/get #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -#[typeshare] +#[cfg_attr(feature = "typeshare", typeshare)] pub struct CredentialRequestOptions { /// The key defining that this is a request for a webauthn credential. pub public_key: PublicKeyCredentialRequestOptions, @@ -188,7 +189,7 @@ pub struct CredentialRequestOptions { /// #[derive(Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] -#[typeshare(swift = "Equatable, Hashable")] +#[cfg_attr(feature = "typeshare", typeshare(swift = "Equatable, Hashable"))] pub struct AuthenticatorAssertionResponse { /// This attribute contains the JSON serialization of [`CollectedClientData`] passed to the /// authenticator by the client in order to generate this credential. The exact JSON serialization diff --git a/passkey-types/src/webauthn/attestation.rs b/passkey-types/src/webauthn/attestation.rs index ada31e4..6e1934c 100644 --- a/passkey-types/src/webauthn/attestation.rs +++ b/passkey-types/src/webauthn/attestation.rs @@ -3,6 +3,7 @@ use coset::iana; use indexmap::IndexMap; use serde::{Deserialize, Serialize, Serializer}; use std::fmt; +#[cfg(feature = "typeshare")] use typeshare::typeshare; use crate::{ @@ -25,7 +26,7 @@ use crate::{ }; /// The response to the successful creation of a PublicKeyCredential -#[typeshare(swift = "Equatable, Hashable")] +#[cfg_attr(feature = "typeshare", typeshare(swift = "Equatable, Hashable"))] pub type CreatedPublicKeyCredential = PublicKeyCredential; /// This is the expected input to [`navigator.credentials.create`] when wanting to create a webauthn @@ -36,7 +37,7 @@ pub type CreatedPublicKeyCredential = PublicKeyCredential #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -#[typeshare] +#[cfg_attr(feature = "typeshare", typeshare)] pub struct PublicKeyCredentialCreationOptions { /// This member contains a name and an identifier for the [Relying Party] responsible for the request. /// @@ -170,7 +171,7 @@ pub struct PublicKeyCredentialCreationOptions { /// /// #[derive(Debug, Serialize, Deserialize, Clone)] -#[typeshare] +#[cfg_attr(feature = "typeshare", typeshare)] pub struct PublicKeyCredentialRpEntity { /// A unique identifier for the [Relying Party] entity, which sets the [RP ID]. /// @@ -224,7 +225,7 @@ pub struct PublicKeyCredentialRpEntity { /// [Lang]: https://w3c.github.io/webauthn/#sctn-strings-langdir #[derive(Debug, Serialize, Deserialize, Clone)] #[serde(rename_all = "camelCase")] -#[typeshare] +#[cfg_attr(feature = "typeshare", typeshare)] pub struct PublicKeyCredentialUserEntity { /// The user handle of the user account. A user handle is an opaque byte sequence with a maximum /// size of 64 bytes, and is not meant to be displayed to the user. @@ -275,7 +276,7 @@ pub struct PublicKeyCredentialUserEntity { /// /// #[derive(Debug, Serialize, Deserialize, Clone, Copy)] -#[typeshare] +#[cfg_attr(feature = "typeshare", typeshare)] pub struct PublicKeyCredentialParameters { /// This member specifies the type of credential to be created. The value SHOULD be a member of /// [`PublicKeyCredentialType`] but client platforms MUST ignore unknown values, ignoring any @@ -291,7 +292,8 @@ pub struct PublicKeyCredentialParameters { /// > because it will be serialized into a message to the authenticator, which may be /// > sent over a low-bandwidth link. #[serde(with = "i64_to_iana")] - #[typeshare(serialized_as = "I54")] // because i64 fails for js + #[cfg_attr(feature = "typeshare", typeshare(serialized_as = "I54"))] + // because i64 fails for js pub alg: iana::Algorithm, } @@ -325,7 +327,7 @@ impl PublicKeyCredentialParameters { /// [Relying Parties]: https://w3c.github.io/webauthn/#webauthn-relying-party #[derive(Debug, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -#[typeshare] +#[cfg_attr(feature = "typeshare", typeshare)] pub struct AuthenticatorSelectionCriteria { /// If this member is present, eligible authenticators are filtered to be only those /// authenticators attached with the specified [`AuthenticatorAttachment`] modality. If this @@ -387,7 +389,7 @@ pub struct AuthenticatorSelectionCriteria { /// [discoverable credential]: https://w3c.github.io/webauthn/#client-side-discoverable-credential #[derive(Debug, Deserialize, Serialize, Clone, Copy, PartialEq, Eq)] #[serde(rename_all = "lowercase")] -#[typeshare(serialized_as = "String")] +#[cfg_attr(feature = "typeshare", typeshare(serialized_as = "String"))] pub enum ResidentKeyRequirement { /// The Relying Party prefers creating a [server-side credential], but will accept a client-side /// discoverable credential. The client and authenticator SHOULD create a server-side credential @@ -424,7 +426,7 @@ pub enum ResidentKeyRequirement { /// [attestation conveyance]: https://w3c.github.io/webauthn/#attestation-conveyance #[derive(Debug, Default, Deserialize, Serialize, Clone, Copy, PartialEq, Eq)] #[serde(rename_all = "lowercase")] -#[typeshare(serialized_as = "String")] +#[cfg_attr(feature = "typeshare", typeshare(serialized_as = "String"))] pub enum AttestationConveyancePreference { /// The Relying Party is not interested in authenticator attestation. For example, in order to /// potentially avoid having to obtain user consent to relay identifying information to the @@ -473,7 +475,7 @@ pub enum AttestationConveyancePreference { /// [2]: https://w3c.github.io/webauthn/#sctn-attstn-fmt-ids #[derive(Debug, Default, Deserialize, Serialize, Clone, Copy, PartialEq, Eq)] #[serde(rename_all = "kebab-case")] -#[typeshare] +#[cfg_attr(feature = "typeshare", typeshare)] pub enum AttestationStatementFormatIdentifiers { /// The `packed` attestation statement format is a WebAuthn-optimized format for attestation. /// It uses a very compact but still extensible encoding method. This format is implementable by @@ -515,7 +517,7 @@ pub enum AttestationStatementFormatIdentifiers { /// [Relying Party]: https://w3c.github.io/webauthn/#relying-party #[derive(Debug, Clone, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] -#[typeshare(swift = "Equatable, Hashable")] +#[cfg_attr(feature = "typeshare", typeshare(swift = "Equatable, Hashable"))] pub struct AuthenticatorAttestationResponse { /// This attribute contains the JSON serialization of [`CollectedClientData`] passed to the /// authenticator by the client in order to generate this credential. The exact JSON serialization @@ -535,7 +537,8 @@ pub struct AuthenticatorAttestationResponse { /// This is the [CoseAlgorithmIdentifier] of the new credential /// /// [CoseAlgorithmIdentifier]: https://w3c.github.io/webauthn/#typedefdef-cosealgorithmidentifier - #[typeshare(serialized_as = "I54")] // because i64 fails for js + #[cfg_attr(feature = "typeshare", typeshare(serialized_as = "I54"))] + // ^ because i64 fails for js pub public_key_algorithm: i64, /// This attribute contains an attestation object, which is opaque to, and cryptographically @@ -625,7 +628,7 @@ where /// Used to limit the values of [`CollectedClientData::ty`] and serializes to static strings. #[derive(Debug, Deserialize, Serialize, Clone, Copy, PartialEq, Eq)] -#[typeshare] +#[cfg_attr(feature = "typeshare", typeshare)] pub enum ClientDataType { /// Serializes to the string `"webauthn.create"` #[serde(rename = "webauthn.create")] diff --git a/passkey-types/src/webauthn/common.rs b/passkey-types/src/webauthn/common.rs index 5c1c3ed..a3b5a9c 100644 --- a/passkey-types/src/webauthn/common.rs +++ b/passkey-types/src/webauthn/common.rs @@ -1,6 +1,7 @@ //! Common types used in both Attestation (registration) and Assertion (authentication). //! use serde::{Deserialize, Serialize}; +#[cfg(feature = "typeshare")] use typeshare::typeshare; use crate::{ @@ -22,7 +23,7 @@ use crate::webauthn::{ /// #[derive(Debug, Default, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)] #[serde(rename_all = "kebab-case")] -#[typeshare(serialized_as = "String")] +#[cfg_attr(feature = "typeshare", typeshare(serialized_as = "String"))] pub enum PublicKeyCredentialType { /// Currently the only type defined is a `PublicKey` meaning the public conterpart of an /// asymmetric key pair. @@ -41,7 +42,7 @@ pub enum PublicKeyCredentialType { /// /// #[derive(Debug, Serialize, Deserialize)] -#[typeshare] +#[cfg_attr(feature = "typeshare", typeshare)] pub struct PublicKeyCredentialDescriptor { /// This member contains the type of the public key credential the caller is referring to. The /// value SHOULD be a member of [`PublicKeyCredentialType`] but client platforms MUST ignore any @@ -93,7 +94,7 @@ impl PublicKeyCredentialDescriptor { /// [user verification]: https://w3c.github.io/webauthn/#user-verification #[derive(Debug, Default, Deserialize, Serialize, Clone, Copy, PartialEq, Eq)] #[serde(rename_all = "lowercase")] -#[typeshare(serialized_as = "String")] +#[cfg_attr(feature = "typeshare", typeshare(serialized_as = "String"))] pub enum UserVerificationRequirement { /// The Relying Party requires user verification for the operation and will fail the overall /// ceremony if the response does not have the UV flag set. The client MUST return an error if @@ -119,7 +120,7 @@ pub enum UserVerificationRequirement { /// #[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)] #[serde(rename_all = "lowercase")] -#[typeshare(serialized_as = "String")] +#[cfg_attr(feature = "typeshare", typeshare(serialized_as = "String"))] pub enum AuthenticatorTransport { /// Indicates the respective authenticator can be contacted over removable USB. Usb, @@ -150,7 +151,7 @@ pub enum AuthenticatorTransport { /// #[derive(Debug, Deserialize, Serialize, Clone, Copy, PartialEq, Eq)] #[serde(rename_all = "kebab-case")] -#[typeshare(serialized_as = "String")] +#[cfg_attr(feature = "typeshare", typeshare(serialized_as = "String"))] pub enum AuthenticatorAttachment { /// This value indicates platform attachment which is attached using a client device-specific /// transport, called **platform attachment**, and is usually not removable from the client @@ -182,7 +183,7 @@ pub enum AuthenticatorAttachment { /// #[derive(Debug, Deserialize, Serialize, Clone, Copy, PartialEq, Eq)] #[serde(rename_all = "kebab-case")] -#[typeshare(serialized_as = "String")] +#[cfg_attr(feature = "typeshare", typeshare(serialized_as = "String"))] #[non_exhaustive] pub enum PublicKeyCredentialHints { /// Indicates that the Relying Party believes that users will satisfy this request with a physical diff --git a/passkey-types/src/webauthn/extensions/credential_properties.rs b/passkey-types/src/webauthn/extensions/credential_properties.rs index 2ba3544..60d9ce3 100644 --- a/passkey-types/src/webauthn/extensions/credential_properties.rs +++ b/passkey-types/src/webauthn/extensions/credential_properties.rs @@ -1,4 +1,5 @@ use serde::{Deserialize, Serialize}; +#[cfg(feature = "typeshare")] use typeshare::typeshare; #[cfg(doc)] @@ -13,7 +14,7 @@ use crate::webauthn::PublicKeyCredential; /// [Relying Party]: https://w3c.github.io/webauthn/#relying-party #[derive(Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] -#[typeshare(swift = "Equatable, Hashable")] +#[cfg_attr(feature = "typeshare", typeshare(swift = "Equatable, Hashable"))] pub struct CredentialPropertiesOutput { /// This OPTIONAL property, known abstractly as the resident key credential property /// (i.e., client-side [discoverable credential] property), is a Boolean value indicating whether diff --git a/passkey-types/src/webauthn/extensions/mod.rs b/passkey-types/src/webauthn/extensions/mod.rs index 0dd34bb..18efe30 100644 --- a/passkey-types/src/webauthn/extensions/mod.rs +++ b/passkey-types/src/webauthn/extensions/mod.rs @@ -1,4 +1,5 @@ use serde::{Deserialize, Serialize}; +#[cfg(feature = "typeshare")] use typeshare::typeshare; mod credential_properties; @@ -18,7 +19,7 @@ use crate::webauthn::PublicKeyCredential; /// [WebAuthn Extensions]: https://w3c.github.io/webauthn/#webauthn-extensions #[derive(Debug, Default, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] -#[typeshare] +#[cfg_attr(feature = "typeshare", typeshare)] pub struct AuthenticationExtensionsClientInputs { /// Boolean to indicate that this extension is requested by the relying party. /// @@ -73,7 +74,7 @@ impl AuthenticationExtensionsClientInputs { /// [WebAuthn Extensions]: https://w3c.github.io/webauthn/#webauthn-extensions #[derive(Debug, Default, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] -#[typeshare(swift = "Equatable, Hashable")] +#[cfg_attr(feature = "typeshare", typeshare(swift = "Equatable, Hashable"))] pub struct AuthenticationExtensionsClientOutputs { /// Contains properties of the given [`PublicKeyCredential`] when it is included. /// diff --git a/passkey-types/src/webauthn/extensions/pseudo_random_function.rs b/passkey-types/src/webauthn/extensions/pseudo_random_function.rs index 67dfbc9..cf0b1a1 100644 --- a/passkey-types/src/webauthn/extensions/pseudo_random_function.rs +++ b/passkey-types/src/webauthn/extensions/pseudo_random_function.rs @@ -1,4 +1,5 @@ use serde::{Deserialize, Serialize}; +#[cfg(feature = "typeshare")] use typeshare::typeshare; use std::collections::HashMap; @@ -17,7 +18,7 @@ use crate::Bytes; /// the PRF. #[derive(Debug, Deserialize, Serialize, Clone)] #[serde(rename_all = "camelCase")] -#[typeshare(swift = "Equatable, Hashable")] +#[cfg_attr(feature = "typeshare", typeshare(swift = "Equatable, Hashable"))] pub struct AuthenticationExtensionsPrfValues { /// The first PRF value. pub first: Bytes, @@ -37,7 +38,7 @@ pub struct AuthenticationExtensionsPrfValues { /// #[derive(Debug, Default, Deserialize, Serialize, Clone)] #[serde(rename_all = "camelCase")] -#[typeshare] +#[cfg_attr(feature = "typeshare", typeshare)] pub struct AuthenticationExtensionsPrfInputs { /// One or two inputs on which to evaluate PRF. Not all authenticators /// support evaluating the PRFs during credential creation so outputs may, @@ -61,7 +62,7 @@ pub struct AuthenticationExtensionsPrfInputs { /// See [`AuthenticationExtensionsPrfInputs`] for details. #[derive(Debug, Deserialize, Serialize, Clone)] #[serde(rename_all = "camelCase")] -#[typeshare(swift = "Equatable, Hashable")] +#[cfg_attr(feature = "typeshare", typeshare(swift = "Equatable, Hashable"))] pub struct AuthenticationExtensionsPrfOutputs { /// True if, and only if, the one or two PRFs are available for use with /// the created credential. This is only reported during registration and