Add webauthn3-proto crate

The webauthn3-proto crate provides a FIDO WebAuthn3 API definition that
implements the w3c CredentialManagement API defined in the
credential-management-proto crate.
dev
Nick Zana 1 year ago
parent 89cf54df04
commit 0186b2ee40
No known key found for this signature in database
GPG Key ID: 936524EE913D6538

@ -0,0 +1,2 @@
/target
/Cargo.lock

@ -0,0 +1,15 @@
[package]
name = "webauthn3-proto"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
base64 = "0.21.0"
credential-management-proto = { path = "../credential-management-proto" }
fido-common = { path = "../fido-common" }
serde = { version = "1.0", features = ["derive"], optional = true }
[features]
serde = ["dep:serde"]

@ -0,0 +1,28 @@
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Copy, Debug)]
/// > WebAuthn Relying Parties may use AttestationConveyancePreference to
/// > specify their preference regarding attestation conveyance during
/// > credential generation.
/// >
/// > <https://w3c.github.io/webauthn/#enum-attestation-convey/>
pub enum ConveyancePreference {
/// > The Relying Party is not interested in authenticator attestation.
#[cfg_attr(feature = "serde", serde(rename = "none"))]
None,
/// > The Relying Party wants to receive a verifiable attestation statement,
/// > but allows the client to decide how to obtain such an attestation
/// > statement.
#[cfg_attr(feature = "serde", serde(rename = "indirect"))]
Indirect,
/// > The Relying Party wants to receive the attestation statement as
/// > generated by the authenticator.
#[cfg_attr(feature = "serde", serde(rename = "direct"))]
Direct,
/// > The Relying Party wants to receive an attestation statement that may
/// > include uniquely identifying information.
#[cfg_attr(feature = "serde", serde(rename = "enterprise"))]
Enterprise,
}

@ -0,0 +1,35 @@
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy)]
/// > This enumerations values describe authenticators' attachment modalities.
/// > Relying Parties use this to express a preferred authenticator attachment
/// > modality when calling `navigator.credentials.create()` to create a
/// > credential, and clients use this to report the authenticator attachment
/// > modality used to complete a registration or authentication ceremony.
/// >
/// > <https://w3c.github.io/webauthn/#enumdef-authenticatorattachment/>
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Attachment {
#[cfg_attr(feature = "serde", serde(rename = "platform"))]
Platform,
#[cfg_attr(feature = "serde", serde(rename = "cross-platform"))]
CrossPlatform,
}
#[derive(Debug)]
/// Contains the contents of an authenticator's response to a Relying Party's
/// request.
///
/// > <https://www.w3.org/TR/webauthn-3/#authenticatorresponse/>
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Response {
// TODO: Fill out response???
// Attestation {
// client_data: client::Data<{ client::DataType::Create }>,
// attestation_object: Vec<u8>,
// },
// Assertion {
// client_data: client::Data<{ client::DataType::Get }>,
// },
}

@ -0,0 +1,49 @@
use crate::token;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(PartialEq, Eq, Clone, Copy)]
pub enum DataType {
#[cfg_attr(feature = "serde", serde(rename = "webauthn.create"))]
Create,
#[cfg_attr(feature = "serde", serde(rename = "webauthn.get"))]
Get,
}
/// > The client data represents the contextual bindings of both the
/// > `WebAuthn` Relying Party and the client.
/// >
/// > <https://www.w3.org/TR/webauthn-3/#client-data/>
pub struct Data<const TYPE: DataType> {
/// > This member contains the base64url encoding of the challenge
/// > provided by the Relying Party.
pub challenge: String,
/// > This member contains the fully qualified origin of the requester,
/// > as provided to the authenticator by the client, in the syntax
/// > defined by
/// > [RFC6454](https://www.w3.org/TR/webauthn-3/#biblio-rfc6454).
pub origin: String,
// TODO: Description
pub cross_origin: Option<bool>,
/// > ...contains information about the state of the Token Binding
/// > protocol... used when communicating with the Relying Party. Its
/// > absence indicates that the client doesnt support token binding.
pub token_binding: Option<token::Binding>,
}
#[cfg(feature = "serde")]
impl<const TYPE: DataType> Serialize for Data<TYPE> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
// Keys are: "type", "challenge", "origin", "topOrigin", "crossOrigin"
const LEN: usize = 5;
let mut map = serializer.serialize_map(Some(LEN))?;
// map.serialize_entry("type", value)
todo!()
}
}

@ -0,0 +1,34 @@
#![feature(async_fn_in_trait, adt_const_params, associated_const_equality)]
#![allow(incomplete_features, clippy::unused_async, clippy::doc_markdown)]
pub mod attestation;
pub mod authenticator;
pub mod client;
pub mod public_key;
pub mod token;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Copy)]
/// > A WebAuthn Relying Party may require user verification for some of its
/// > operations but not for others, and may use this type to express its needs.
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 user verification cannot
/// > be performed.
#[cfg_attr(feature = "serde", serde(rename = "required"))]
Required,
/// > The Relying Party prefers user verification for the operation if
/// > possible, but will not fail the operation if the response does not
/// > have the UV flag set.
#[cfg_attr(feature = "serde", serde(rename = "preferred"))]
Preferred,
/// > The Relying Party does not want user verification employed during the
/// > operation (e.g., in the interest of minimizing disruption to the user
/// > interaction flow).
#[cfg_attr(feature = "serde", serde(rename = "discouraged"))]
Discouraged,
}

@ -0,0 +1,51 @@
use crate::authenticator;
use credential_management_proto::{credential, discovery};
pub mod create;
pub mod request;
/// > The [`public_key::Credential`] interface inherits from
/// > [`credential::Credential`], and contains the attributes that are returned
/// > to the caller when a new credential is created, or a new assertion is
/// > requested.
/// >
/// > <https://w3c.github.io/webauthn/#iface-pkcredential/>
pub trait Credential: credential::Credential {
/// Returns the raw byte array of the credential's `id`.
fn raw_id(&self) -> &[u8];
/// > This attribute contains the authenticator's response to the clients
/// > request to either create a public key credential, or generate an
/// > authentication assertion. If the [`public_key::Credential`] is created
/// > in response to `create()`, this attributes value will be an
/// > [`authenticator::Response::Attestation`], otherwise, the
/// > [`public_key::Credential`] was created in response to `get()`, and
/// > this attributes value will be an
/// > [`authenticator::Response::Assertion`].
fn response(&self) -> &authenticator::Response;
/// > This attribute reports the authenticator attachment modality in effect
/// > at the time the `navigator.credentials.create()` or
/// > `navigator.credentials.get()` methods successfully complete.
///
/// If the attachment method is unknown, this function returns `None`.
fn authenticator_attachment(&self) -> Option<authenticator::Attachment>;
}
pub trait Container:
for<'a> credential::Container<
Credential = Self::PublicKeyCredential,
RequestOptions = Self::PublicKeyRequestOptions,
CreateOptions = Self::PublicKeyCreateOptions,
DISCOVERY_MODE = { discovery::Mode::Remote },
>
{
type PublicKeyCredential: Credential;
type PublicKeyRequestOptions: request::Options;
type PublicKeyCreateOptions: create::Options;
/// > ...indicate[s] availability for conditional mediation.
/// >
/// > <https://w3c.github.io/webauthn/#dom-publickeycredential-isconditionalmediationavailable/>
async fn is_conditional_mediation_available() -> bool;
}

@ -0,0 +1,106 @@
use fido_common::{attestation::FormatIdentifier, credential::public_key};
use crate::{attestation, authenticator, UserVerificationRequirement};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
/// > <https://w3c.github.io/webauthn/#dictionary-makecredentialoptions/>
pub trait Options {
/// > This member contains a name and an identifier for the Relying Party
/// > responsible for the request.
fn public_key_credential_relying_party_entity(&self) -> &public_key::RelyingPartyEntity;
/// > This member contains names and an identifier for the user account
/// > performing the registration.
fn public_key_credential_user_entity(&self) -> &public_key::UserEntity;
/// > This member specifies a challenge that the authenticator signs, along
/// > with other data, when producing an attestation object for the newly
/// > created credential.
fn challenge(&self) -> &[u8];
/// > This member lists the key types and signature algorithms the Relying
/// > Party supports, ordered from most preferred to least preferred.
fn public_key_credential_parameters(&self) -> &[public_key::Parameters];
/// > This OPTIONAL member specifies a time, in milliseconds, that the
/// > Relying Party is willing to wait for the call to complete. This is
/// > treated as a hint, and MAY be overridden by the client.
fn timeout(&self) -> Option<u64>;
/// > The Relying Party SHOULD use this OPTIONAL member to list any existing
/// > credentials mapped to this user account (as identified by `user.id`).
/// > This ensures that the new credential is not created on an
/// > authenticator that already contains a credential mapped to this user
/// > account. If it would be, the client is requested to instead guide the
/// > user to use a different authenticator, or return an error if that
/// > fails.
fn exclude_credentials(&self) -> Option<&[public_key::Descriptor]>;
/// > The Relying Party MAY use this OPTIONAL member to specify capabilities
/// > and settings that the authenticator MUST or SHOULD satisfy to
/// > participate in the `create()` operation.
fn authenticator_selection(&self) -> Option<AuthenticatorSelectionCriteria>;
/// > The Relying Party MAY use this OPTIONAL member to specify a preference
/// > regarding attestation conveyance.
fn attestation(&self) -> Option<attestation::ConveyancePreference>;
/// > The Relying Party MAY use this OPTIONAL member to specify a preference
/// > regarding the attestation statement format used by the authenticator.
fn attestation_formats(&self) -> &[FormatIdentifier];
}
/// > WebAuthn Relying Parties may use the [`AuthenticatorSelectionCriteria`]
/// > dictionary to specify their requirements regarding authenticator
/// > attributes.
/// >
/// > <https://w3c.github.io/webauthn/#dictionary-authenticatorSelection/>
#[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct AuthenticatorSelectionCriteria {
/// > If this member is present, eligible authenticators are filtered to be
/// > only those authenticators attached with the specified authenticator
/// > attachment modality... If this member is absent, then any attachment
/// > modality is acceptable.
#[cfg_attr(feature = "serde", serde(rename = "authenticatorAttachment"))]
pub attachment: Option<authenticator::Attachment>,
/// > Specifies the extent to which the Relying Party desires to create a
/// > client-side discoverable credential.
#[cfg_attr(feature = "serde", serde(rename = "residentKey"))]
pub resident_key_requirement: ResidentKeyRequirement,
/// > This member specifies the Relying Party's requirements regarding user
/// > verification for the `create()` operation.
pub user_verification_requirement: UserVerificationRequirement,
}
/// > This enumerations values describe the Relying Party's requirements for
/// > client-side discoverable credentials (formerly known as resident
/// > credentials or resident keys):
/// >
/// > <https://w3c.github.io/webauthn/#enumdef-residentkeyrequirement/>
#[derive(Debug, Clone, Copy)]
#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize),
serde(rename_all = "camelCase")
)]
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 if possible.
Discouraged,
/// > The Relying Party strongly prefers creating a client-side discoverable
/// > credential, but will accept a server-side credential. The client and
/// > authenticator SHOULD create a discoverable credential if possible. For
/// > example, the client SHOULD guide the user through setting up user
/// > verification if needed to create a discoverable credential. This takes
/// > precedence over the setting of
/// > [`AuthenticatorSelectionCriteria::user_verification`].
Preferred,
/// > The Relying Party requires a client-side discoverable credential. The
/// > client MUST return an error if a client-side discoverable credential
/// > cannot be created.
Required,
}

@ -0,0 +1,46 @@
use fido_common::{attestation::FormatIdentifier, credential::public_key};
use crate::{attestation, UserVerificationRequirement};
/// > [This struct] supplies `get()` with the data it needs to generate an
/// > assertion.
pub trait Options {
/// > This member specifies a challenge that the authenticator signs, along
/// > with other data, when producing an authentication assertion.
fn challenge(&self) -> &[u8];
/// > This OPTIONAL member specifies a time, in milliseconds, that the
/// > Relying Party is willing to wait for the call to complete. The value
/// > is treated as a hint, and MAY be overridden by the client.
fn timeout(&self) -> Option<u64>;
/// > This OPTIONAL member specifies the RP ID claimed by the Relying Party.
/// > The client MUST verify that the Relying Party's origin matches the
/// > scope of this RP ID. The authenticator MUST verify that this RP ID
/// > exactly equals the rpId of the credential to be used for the
/// > authentication ceremony.
/// >
/// > If not specified, its value will be the [`CredentialsContainer`]
/// > objects relevant settings object's origin's effective domain.
fn relying_party_id(&self) -> Option<&str>;
/// > This OPTIONAL member is used by the client to find authenticators
/// > eligible for this authentication ceremony.
/// > ...
/// > If not empty, the client MUST return an error if none of the listed
/// > credentials can be used.
/// >
/// > The list is ordered in descending order of preference: the first item
/// > in the list is the most preferred credential, and the last is the
/// > least preferred.
fn allow_credentials(&self) -> Option<&[public_key::Descriptor]>;
/// > ... specifies the Relying Party's requirements regarding user
/// > verification for the get() operation... Eligible authenticators are
/// > filtered to only those capable of satisfying this requirement.
fn user_verification(&self) -> Option<UserVerificationRequirement>;
/// > The Relying Party MAY use this OPTIONAL member to specify a preference
/// > regarding attestation conveyance.
fn attestation(&self) -> Option<attestation::ConveyancePreference>;
/// > The Relying Party MAY use this OPTIONAL member to specify a preference
/// > regarding the attestation statement format used by the
/// > authenticator... Values are ordered from most preferable to least
/// > preferable.
fn attestation_formats(&self) -> Option<&[FormatIdentifier]>;
}

@ -0,0 +1,20 @@
pub enum BindingStatus {
/// > Indicates token binding was used when communicating with the
/// > Relying
/// > Party. In this case, the `TokenBinding::id` member MUST be
/// > present.
Present,
/// > Indicates the client supports token binding, but it was not
/// > negotiated
/// > when communicating with the Relying Party.
Supported,
}
pub struct Binding {
/// > ...a base64url encoding of the Token Binding ID that was used when
/// > communicating with the Relying Party.
pub id: String,
/// Indicates the usage and support status of token binding by the
/// client.
pub status: BindingStatus,
}
Loading…
Cancel
Save