Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion passkey-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,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

Expand All @@ -35,7 +36,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]
Expand Down
3 changes: 2 additions & 1 deletion passkey-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use passkey_types::{
},
};
use serde::Serialize;
#[cfg(feature = "typeshare")]
use typeshare::typeshare;
use url::Url;

Expand All @@ -45,7 +46,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.
Expand Down
3 changes: 2 additions & 1 deletion passkey-types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ workspace = true
default = []
serialize_bytes_as_base64_string = []
testable = ["dep:p256"]
typeshare = ["dep:typeshare"]

[dependencies]
bitflags = "2"
Expand All @@ -30,7 +31,7 @@ serde = { version = "1", features = ["derive"] }
serde_json = { version = "1", features = ["preserve_order"] }
sha2 = "0.10"
strum = { version = "0.25", 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
Expand Down
3 changes: 2 additions & 1 deletion passkey-types/src/utils/bytes.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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<u8>);
Expand Down
12 changes: 8 additions & 4 deletions passkey-types/src/webauthn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -38,9 +39,12 @@ impl AuthenticatorResponse for AuthenticatorAttestationResponse {}
/// <https://w3c.github.io/webauthn/#iface-pkcredential>
#[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<R: AuthenticatorResponse> {
/// The id contains the credential ID, chosen by the authenticator. This is usually the base64url
Expand All @@ -51,7 +55,7 @@ pub struct PublicKeyCredential<R: AuthenticatorResponse> {
/// authenticators.
///
/// > NOTE: This API does not constrain the format or length of this identifier, except that it
/// MUST be sufficient for the authenticator to uniquely select a key.
/// > MUST be sufficient for the authenticator to uniquely select a key.
pub id: String,

/// The raw byte containing the credential ID, see [Self::id] for more information.
Expand Down
9 changes: 5 additions & 4 deletions passkey-types/src/webauthn/assertion.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Types used for public key authentication

use serde::{Deserialize, Serialize};
#[cfg(feature = "typeshare")]
use typeshare::typeshare;

use crate::{
Expand All @@ -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<AuthenticatorAssertionResponse>;

/// This type supplies `get()` requests with the data it needs to generate an assertion.
Expand All @@ -31,7 +32,7 @@ pub type AuthenticatedPublicKeyCredential = PublicKeyCredential<AuthenticatorAss
/// <https://w3c.github.io/webauthn/#dictdef-publickeycredentialrequestoptions>
#[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.
Expand Down Expand Up @@ -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,
Expand All @@ -188,7 +189,7 @@ pub struct CredentialRequestOptions {
/// <https://w3c.github.io/webauthn/#iface-authenticatorassertionresponse>
#[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
Expand Down
44 changes: 32 additions & 12 deletions passkey-types/src/webauthn/attestation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand All @@ -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<AuthenticatorAttestationResponse>;

/// This is the expected input to [`navigator.credentials.create`] when wanting to create a webauthn
Expand All @@ -36,7 +37,7 @@ pub type CreatedPublicKeyCredential = PublicKeyCredential<AuthenticatorAttestati
/// [`navigator.credentials.create`]: https://developer.mozilla.org/en-US/docs/Web/API/CredentialsContainer/create
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[typeshare]
#[cfg_attr(feature = "typeshare", typeshare)]
pub struct CredentialCreationOptions {
/// The key defining that this is a request for a webauthn credential.
pub public_key: PublicKeyCredentialCreationOptions,
Expand All @@ -47,7 +48,7 @@ pub struct CredentialCreationOptions {
/// <https://w3c.github.io/webauthn/#dictdef-publickeycredentialcreationoptions>
#[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.
///
Expand Down Expand Up @@ -170,7 +171,7 @@ pub struct PublicKeyCredentialCreationOptions {
///
/// <https://w3c.github.io/webauthn/#dictdef-publickeycredentialrpentity>
#[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].
///
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -275,14 +276,15 @@ pub struct PublicKeyCredentialUserEntity {
///
/// <https://w3c.github.io/webauthn/#dictdef-publickeycredentialparameters>
#[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
/// [`PublicKeyCredentialParameters`] with an [`PublicKeyCredentialType::Unknown`] type.
#[serde(rename = "type", deserialize_with = "ignore_unknown")]
pub ty: PublicKeyCredentialType,

#[cfg(feature = "typeshare")]
/// This member specifies the cryptographic signature algorithm with which the newly generated
/// credential will be used, and thus also the type of asymmetric key pair to be generated,
/// e.g., RSA or Elliptic Curve.
Expand All @@ -293,6 +295,17 @@ pub struct PublicKeyCredentialParameters {
#[serde(with = "i64_to_iana")]
#[typeshare(serialized_as = "I54")] // because i64 fails for js
pub alg: iana::Algorithm,

#[cfg(not(feature = "typeshare"))]
/// This member specifies the cryptographic signature algorithm with which the newly generated
/// credential will be used, and thus also the type of asymmetric key pair to be generated,
/// e.g., RSA or Elliptic Curve.
///
/// > Note: we use `alg` as the latter member name, rather than spelling-out `algorithm`,
/// > 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")]
pub alg: iana::Algorithm,
}

impl PublicKeyCredentialParameters {
Expand Down Expand Up @@ -325,7 +338,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
Expand Down Expand Up @@ -387,7 +400,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
Expand Down Expand Up @@ -424,7 +437,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
Expand Down Expand Up @@ -473,7 +486,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
Expand Down Expand Up @@ -515,7 +528,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
Expand All @@ -532,12 +545,19 @@ pub struct AuthenticatorAttestationResponse {
#[serde(skip_serializing_if = "Option::is_none")]
pub public_key: Option<Bytes>,

#[cfg(feature = "typeshare")]
/// 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
pub public_key_algorithm: i64,

#[cfg(not(feature = "typeshare"))]
/// This is the [CoseAlgorithmIdentifier] of the new credential
///
/// [CoseAlgorithmIdentifier]: https://w3c.github.io/webauthn/#typedefdef-cosealgorithmidentifier
pub public_key_algorithm: i64,

/// This attribute contains an attestation object, which is opaque to, and cryptographically
/// protected against tampering by, the client. The attestation object contains both
/// [`AuthenticatorData`] and an attestation statement. The former contains the [`Aaguid`], a unique
Expand Down Expand Up @@ -625,7 +645,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")]
Expand Down
13 changes: 7 additions & 6 deletions passkey-types/src/webauthn/common.rs
Original file line number Diff line number Diff line change
@@ -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::{
Expand All @@ -22,7 +23,7 @@ use crate::webauthn::{
/// <https://w3c.github.io/webauthn/#enumdef-publickeycredentialtype>
#[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.
Expand All @@ -41,7 +42,7 @@ pub enum PublicKeyCredentialType {
///
/// <https://w3c.github.io/webauthn/#dictdef-publickeycredentialdescriptor>
#[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
Expand Down Expand Up @@ -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
Expand All @@ -119,7 +120,7 @@ pub enum UserVerificationRequirement {
/// <https://w3c.github.io/webauthn/#enum-transport>
#[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,
Expand Down Expand Up @@ -150,7 +151,7 @@ pub enum AuthenticatorTransport {
/// <https://w3c.github.io/webauthn/#enumdef-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"))]
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
Expand Down Expand Up @@ -182,7 +183,7 @@ pub enum AuthenticatorAttachment {
/// <https://w3c.github.io/webauthn/#enum-hints>
#[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
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use serde::{Deserialize, Serialize};
#[cfg(feature = "typeshare")]
use typeshare::typeshare;

#[cfg(doc)]
Expand All @@ -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
Expand Down
Loading
Loading