diff --git a/proxmox-login/src/tfa.rs b/proxmox-login/src/tfa.rs index afe44d11..ef3e6aa2 100644 --- a/proxmox-login/src/tfa.rs +++ b/proxmox-login/src/tfa.rs @@ -26,6 +26,12 @@ pub struct TfaChallenge { #[serde(skip_serializing_if = "Option::is_none")] pub webauthn: Option, + /// If the user has any webauthn credentials registered, this will contain the corresponding + /// challenge data as a json string. + /// This field is never serialized and is only meant to be informative. + #[serde(default, skip)] + pub webauthn_raw: Option, + /// True if the user has yubico keys configured. #[serde(skip_serializing_if = "bool_is_false", default)] pub yubico: bool, diff --git a/proxmox-login/src/ticket.rs b/proxmox-login/src/ticket.rs index 40decf99..24606da5 100644 --- a/proxmox-login/src/ticket.rs +++ b/proxmox-login/src/ticket.rs @@ -3,6 +3,7 @@ use std::fmt; use serde::{Deserialize, Serialize}; +use serde_json::Value; use crate::error::TicketError; use crate::tfa::TfaChallenge; @@ -24,7 +25,15 @@ impl std::str::FromStr for TicketResponse { Some(pos) => { let challenge: std::borrow::Cow<[u8]> = percent_encoding::percent_decode_str(&challenge[..pos]).into(); - let challenge = serde_json::from_slice(&challenge).map_err(|_| TicketError)?; + let raw_challenge: Value = + serde_json::from_slice(&challenge).map_err(|_| TicketError)?; + let webauthn_raw = raw_challenge["webauthn"].clone(); + let mut challenge: TfaChallenge = + serde_json::from_value(raw_challenge).map_err(|_| TicketError)?; + if !webauthn_raw.is_null() { + challenge.webauthn_raw = + Some(serde_json::to_string(&webauthn_raw).map_err(|_| TicketError)?); + } Ok(TicketResponse::Tfa(ticket.to_string(), challenge)) } None => Err(TicketError),