Skip to main content

simple_authentication/
simple_authentication.rs

1//! # Recommended usage
2//!
3//! `Context::authenticate()` is asynchronous: it returns immediately after *starting*
4//! authentication and delivers the final result via the callback.
5//!
6//! **In GUI applications**, you typically do not need any additional synchronization.
7//! The application's event loop keeps the process alive while the user interacts with
8//! the authentication prompt.
9//!
10//! ```no_run
11//! let context = Context::new(());
12//! context.authenticate(TEXT, &POLICY, |result| {
13//!     match result {
14//!         Ok(()) => println!("Authentication successful"),
15//!         Err(e) => eprintln!("Authentication failed: {:?}", e),
16//!     }
17//! });
18//! ```
19//!
20//! # Why this example uses `mpsc::channel()`
21//!
22//! This file is a CLI-style demo. Without an event loop, `main()` would exit before the
23//! authentication completes (especially on Linux where the polkit check runs in the
24//! background). We therefore use an `mpsc::channel()` to wait for the callback.
25//!
26//! # Linux notes
27//!
28//! - Ensure the polkit policy file is installed for the chosen `action_id`
29//!   (see README: "Usage on Linux").
30//! - Ensure a polkit authentication agent is running in the current desktop session,
31//!   otherwise no prompt will appear and the request will fail with `NoAgent`/`Unavailable`.
32
33use std::sync::mpsc;
34
35use robius_authentication::{
36    AndroidText, BiometricStrength, Context, PolicyBuilder, Text, WindowsText,
37};
38
39const TEXT: Text = Text {
40    android: AndroidText {
41        title: "Title",
42        subtitle: None,
43        description: None,
44    },
45    apple: "authenticate",
46    windows: match WindowsText::new("Title", "Description") {
47        Some(text) => text,
48        None => panic!("Windows text too long"),
49    },
50};
51
52fn main() {
53    let context = Context::new(());
54    let mut policy = PolicyBuilder::new()
55        // On Linux You need to set action_ids.
56        // See: ./org.robius.authentication.policy file settings and (README: "Usage on Linux").
57        .action_ids([
58            "org.robius.authentication",
59            "org.robius.authentication.settings",
60        ])
61        .biometrics(Some(BiometricStrength::Strong))
62        .password(true)
63        .companion(true)
64        .build()
65        .unwrap();
66
67    if let Err(e) = policy.set_action_id("org.robius.authentication.settings") {
68        eprintln!("Invalid action_id: {:?}", e);
69        return;
70    }
71
72    let (tx, rx) = mpsc::channel();
73
74    // Start authentication. `res` only indicates whether the request was successfully
75    // initiated; the final result is delivered via the callback.
76    let res = context.authenticate(TEXT, &policy, move |result| {
77        let _ = tx.send(result);
78    });
79
80    if let Err(e) = res {
81        eprintln!("Failed to start authentication: {:?}", e);
82        return;
83    }
84
85    // Block until the callback produces a result.
86    match rx.recv() {
87        Ok(Ok(_)) => println!("Authentication successful"),
88        Ok(Err(e)) => println!("Authentication failed: {:?}", e),
89        Err(e) => eprintln!("Failed to receive auth result: {:?}", e),
90    }
91}