diff --git a/cmd/passless/src/authenticator.rs b/cmd/passless/src/authenticator.rs index ff110ed..55b31d4 100644 --- a/cmd/passless/src/authenticator.rs +++ b/cmd/passless/src/authenticator.rs @@ -81,7 +81,12 @@ impl AuthenticatorCallbacks for PasslessCallbacks { return Ok(UpResult::Accepted); } - match show_verification_notification(info, Some(rp), user) { + match show_verification_notification( + info, + Some(rp), + user, + self.security_config.notification_timeout, + ) { Ok(crate::notification::NotificationResult::Accepted) => Ok(UpResult::Accepted), Ok(crate::notification::NotificationResult::Denied) => Ok(UpResult::Denied), Err(e) => { @@ -343,6 +348,7 @@ mod tests { constant_signature_counter: false, user_verification_registration: true, user_verification_authentication: true, + notification_timeout: 30, }; let service = AuthenticatorService::new(storage, security_config); diff --git a/cmd/passless/src/notification.rs b/cmd/passless/src/notification.rs index 9a3587c..ce1cb80 100644 --- a/cmd/passless/src/notification.rs +++ b/cmd/passless/src/notification.rs @@ -48,21 +48,11 @@ fn requires_default_action() -> bool { } /// Show a user verification notification and wait for response -/// -/// # Arguments -/// -/// * `operation` - Description of the operation (e.g., "Registration", "Authentication") -/// * `relying_party` - Optional relying party identifier -/// * `user` - Optional user identifier -/// -/// # Returns -/// -/// Result indicating whether the user accepted or denied the operation, -/// or an error if the notification failed to show. pub fn show_verification_notification( operation: &str, relying_party: Option<&str>, user: Option<&str>, + timeout_seconds: u32, ) -> Result { // Build notification message let mut message = format!("Operation: {}", operation); @@ -88,7 +78,7 @@ pub fn show_verification_notification( .summary("🔒 User Verification Required") .body(&message) .icon("security-high") - .timeout(Timeout::Never); // Wait for user action + .timeout(Timeout::Milliseconds(timeout_seconds * 1000)); if default_means_user_present { // For servers that don't support action buttons properly, diff --git a/passless-core/src/config.rs b/passless-core/src/config.rs index 1dd2857..3e8c9e2 100644 --- a/passless-core/src/config.rs +++ b/passless-core/src/config.rs @@ -165,6 +165,16 @@ pub struct SecurityConfig { #[serde(default)] #[default(true)] pub user_verification_authentication: bool, + + /// Notification timeout in seconds (0 = no timeout) + #[arg( + long = "notification-timeout", + env = "PASSLESS_NOTIFICATION_TIMEOUT", + value_name = "SECONDS" + )] + #[serde(default)] + #[default(30)] + pub notification_timeout: u32, } impl SecurityConfig {