Skip to content

Commit

Permalink
Add credprops extension support
Browse files Browse the repository at this point in the history
this includes the new authenticator display name addition to the extension introduced in w3c/webauthn#1880
  • Loading branch information
Progdrasil committed Nov 16, 2023
1 parent 03c0186 commit d12be97
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 27 deletions.
14 changes: 14 additions & 0 deletions passkey-authenticator/src/authenticator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ pub struct Authenticator<S, U> {
transports: Vec<webauthn::AuthenticatorTransport>,
/// Provider of user verification factor.
user_validation: U,

/// The display name given when a [`webauthn::CredentialPropertiesOutput`] is requested
display_name: Option<String>,
}

impl<S, U> Authenticator<S, U>
Expand All @@ -43,9 +46,20 @@ where
webauthn::AuthenticatorTransport::Hybrid,
],
user_validation: user,
display_name: None,
}
}

/// Set the authenticator's display name which will be returned if [`webauthn::CredentialPropertiesOutput`] is requested.
pub fn set_display_name(&mut self, name: String) {
self.display_name = Some(name);
}

/// Get a reference to the authenticators display name to return in [`webauthn::CredentialPropertiesOutput`].
pub fn display_name(&self) -> Option<&String> {
self.display_name.as_ref()
}

/// Access the [`CredentialStore`] to look into what is stored.
pub fn store(&self) -> &S {
&self.store
Expand Down
18 changes: 15 additions & 3 deletions passkey-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ use ciborium::{cbor, value::Value};
use coset::{iana::EnumI64, Algorithm};
use passkey_authenticator::{Authenticator, CredentialStore, UserValidationMethod};
use passkey_types::{
crypto::sha256, ctap2, encoding, webauthn, webauthn::AuthenticationExtensionsClientOutputs,
crypto::sha256,
ctap2, encoding, webauthn,
webauthn::{AuthenticatorExtensionsClientOutputs, CredentialPropertiesOutput},
Passkey,
};
use typeshare::typeshare;
Expand Down Expand Up @@ -186,6 +188,16 @@ where
let client_data_json_hash =
client_data_hash.unwrap_or_else(|| sha256(client_data_json.as_bytes()).to_vec());

let cred_props =
if let Some(true) = request.extensions.as_ref().and_then(|ext| ext.cred_props) {
Some(CredentialPropertiesOutput {
discoverable: Some(true), // Set to true because it is set in the Options of make_credential.
authenticator_display_name: self.authenticator.display_name().cloned(),
})
} else {
None
};

let ctap2_response = self
.authenticator
.make_credential(ctap2::make_credential::Request {
Expand Down Expand Up @@ -257,8 +269,8 @@ where
attestation_object: attestation_object.into(),
transports: auth_info.transports,
},
client_extension_results: AuthenticationExtensionsClientOutputs {},
authenticator_attachment: Some(self.authenticator().attachment_type()),
client_extension_results: AuthenticatorExtensionsClientOutputs { cred_props },
};

Ok(response)
Expand Down Expand Up @@ -334,7 +346,7 @@ where
attestation_object: None,
},
authenticator_attachment: Some(self.authenticator().attachment_type()),
client_extension_results: AuthenticationExtensionsClientOutputs {},
client_extension_results: AuthenticatorExtensionsClientOutputs::default(),
})
}
}
Expand Down
17 changes: 4 additions & 13 deletions passkey-types/src/webauthn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ use crate::{utils::serde::ignore_unknown, Bytes};
mod assertion;
mod attestation;
mod common;
mod extensions;

// re-export types
pub use self::{assertion::*, attestation::*, common::*};
pub use self::{assertion::*, attestation::*, common::*, extensions::*};

mod sealed {
pub trait Sealed {}
Expand Down Expand Up @@ -71,16 +72,6 @@ pub struct PublicKeyCredential<R: AuthenticatorResponse> {

/// This object is a map containing extension identifier → client extension output entries
/// produced by the extension’s client extension processing.
pub client_extension_results: AuthenticationExtensionsClientOutputs,
#[serde(default)]
pub client_extension_results: AuthenticatorExtensionsClientOutputs,
}

/// This is a dictionary containing the client extension output values for zero or more
/// [WebAuthn Extensions]. There are currently none supported.
///
/// <https://w3c.github.io/webauthn/#dictdef-authenticationextensionsclientoutputs>
///
/// [WebAuthn Extensions]: https://w3c.github.io/webauthn/#webauthn-extensions
#[derive(Debug, Deserialize, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
#[typeshare]
pub struct AuthenticationExtensionsClientOutputs {}
11 changes: 0 additions & 11 deletions passkey-types/src/webauthn/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,6 @@ use crate::webauthn::{
PublicKeyCredentialRequestOptions,
};

/// This is a dictionary containing the client extension input values for zero or more
/// [WebAuthn Extensions]. There are currently none supported.
///
/// <https://w3c.github.io/webauthn/#dictdef-authenticationextensionsclientinputs>
///
/// [WebAuthn Extensions]: https://w3c.github.io/webauthn/#webauthn-extensions
#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
#[typeshare]
pub struct AuthenticationExtensionsClientInputs {}

/// This enumeration defines the valid credential types. It is an extension point; values can be
/// added to it in the future, as more credential types are defined. The values of this enumeration
/// are used for versioning the Authentication Assertion and attestation structures according to the
Expand Down
87 changes: 87 additions & 0 deletions passkey-types/src/webauthn/extensions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
use serde::{Deserialize, Serialize};
use typeshare::typeshare;

#[cfg(doc)]
use crate::webauthn::PublicKeyCredential;

/// This is a dictionary containing the client extension input values for zero or more
/// [WebAuthn Extensions]. There are currently none supported.
///
/// <https://w3c.github.io/webauthn/#dictdef-authenticationextensionsclientinputs>
///
/// [WebAuthn Extensions]: https://w3c.github.io/webauthn/#webauthn-extensions
#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
#[typeshare]
pub struct AuthenticationExtensionsClientInputs {
/// Boolean to indicate that this extension is requested by the relying party.
///
/// See [`CredentialPropertiesOutput`] for more information.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cred_props: Option<bool>,
}

/// This is a dictionary containing the client extension output values for zero or more
/// [WebAuthn Extensions].
///
/// <https://w3c.github.io/webauthn/#dictdef-authenticationextensionsclientoutputs>
///
/// [WebAuthn Extensions]: https://w3c.github.io/webauthn/#webauthn-extensions
#[derive(Debug, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
#[typeshare]
pub struct AuthenticatorExtensionsClientOutputs {
/// Contains properties of the given [`PublicKeyCredential`] when it is included.
///
/// See [`CredentialPropertiesOutput`] for more information
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cred_props: Option<CredentialPropertiesOutput>,
}

/// This client registration extension facilitates reporting certain credential properties known by
/// the client to the requesting WebAuthn [Relying Party] upon creation of a [`PublicKeyCredential`]
/// source as a result of a registration ceremony.
///
/// <https://w3c.github.io/webauthn/#sctn-authenticator-credential-properties-extension>
///
/// [Relying Party]: https://w3c.github.io/webauthn/#relying-party
#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
#[typeshare]
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
/// the [`PublicKeyCredential`] returned as a result of a registration ceremony is a client-side
/// [discoverable credential].
/// * If `rk` is true, the credential is a [discoverable credential].
/// * If `rk` is false, the credential is a [server-side credential].
/// * If `rk` is not present, it is not known whether the credential is a [discoverable credential]
/// or a [server-side credential].
///
/// [discoverable credential]: https://w3c.github.io/webauthn/#discoverable-credential
/// [server-side credential]: https://w3c.github.io/webauthn/#server-side-public-key-credential-source
#[serde(rename = "rk", default, skip_serializing_if = "Option::is_none")]
pub discoverable: Option<bool>,

/// This OPTIONAL property is a human-palatable description of the credential’s managing
/// authenticator, chosen by the user.
///
/// The client MUST allow the user to choose this value, MAY or MAY not present that choice
/// during registration ceremonies, and MAY reuse the same value for multiple credentials with
/// the same managing authenticator across multiple Relying Parties.
///
/// The client MAY query the authenticator, by some unspecified mechanism, for this value.
/// The authenticator MAY allow the user to configure the response to such a query.
/// The authenticator vendor MAY provide a default response to such a query. The client MAY
/// consider a user-configured response chosen by the user, and SHOULD allow the user to
/// modify a vendor-provided default response.
///
/// If the Relying Party includes an `authenticatorDisplayName` item in credential records, the
/// Relying Party MAY offer this value, if present, as a default value for the
/// `authenticatorDisplayName` of the new credential record.
///
/// NOTE: This is still [in proposal](https://github.com/w3c/webauthn/pull/1880), we are
/// implementing it here to show our backing to this feature
#[serde(default, skip_serializing_if = "Option::is_none")]
pub authenticator_display_name: Option<String>,
}

0 comments on commit d12be97

Please sign in to comment.