diff --git a/crates/tranquil-pds/src/auth/webauthn.rs b/crates/tranquil-pds/src/auth/webauthn.rs index 88d3b5c..3788804 100644 --- a/crates/tranquil-pds/src/auth/webauthn.rs +++ b/crates/tranquil-pds/src/auth/webauthn.rs @@ -20,6 +20,10 @@ pub struct WebAuthnConfig { webauthn: Webauthn, } +fn clear_authentication_hints(response: &mut RequestChallengeResponse) { + response.public_key.hints = None; +} + impl WebAuthnConfig { pub fn new(hostname: &str) -> Result { let rp_id = hostname.split(':').next().unwrap_or(hostname).to_string(); @@ -89,6 +93,10 @@ impl WebAuthnConfig { ) -> Result<(RequestChallengeResponse, SecurityKeyAuthentication), WebauthnError> { self.webauthn .start_securitykey_authentication(&credentials) + .map(|(mut rcr, state)| { + clear_authentication_hints(&mut rcr); + (rcr, state) + }) .map_err(|e| WebauthnError::AuthenticationFailed(e.to_string())) } @@ -150,7 +158,8 @@ impl WebAuthnConfig { #[cfg(test)] mod tests { - use super::WebAuthnConfig; + use super::{WebAuthnConfig, clear_authentication_hints}; + use webauthn_rs::prelude::RequestChallengeResponse; #[test] fn registration_does_not_prefer_security_key_ui() { @@ -162,4 +171,18 @@ mod tests { assert!(challenge.pointer("/publicKey/hints").is_none()); } + + #[test] + fn authentication_does_not_prefer_security_key_ui() { + let config = WebAuthnConfig::new("pds.example.com").unwrap(); + let (challenge, _) = config.start_discoverable_authentication().unwrap(); + let mut challenge = serde_json::to_value(challenge).unwrap(); + challenge["publicKey"]["hints"] = serde_json::json!(["security-key"]); + let mut challenge: RequestChallengeResponse = serde_json::from_value(challenge).unwrap(); + + clear_authentication_hints(&mut challenge); + + let challenge = serde_json::to_value(challenge).unwrap(); + assert!(challenge.pointer("/publicKey/hints").is_none()); + } }