#[cfg(not(any(target_os = "macos", target_os = "ios")))]
fn main() {
eprintln!("native_passkey example requires macOS or iOS");
std::process::exit(1);
}
#[cfg(any(target_os = "macos", target_os = "ios"))]
fn main() {
use cheers::native::apple::passkey::{
native_registration_to_credential, perform_registration, RegistrationRequest,
};
use cheers::passkey::{PasskeyRelyingParty, Url, Uuid};
const RP_ID: &str = "example.com";
const ORIGIN: &str = "https://example.com";
let rp = PasskeyRelyingParty::new(RP_ID, Url::parse(ORIGIN).unwrap())
.expect("valid RP configuration");
let user_uuid = Uuid::new_v4();
let user_name = "alice@example.com";
let (ccr, reg_state) = rp
.start_registration(user_uuid, user_name, "Alice Example", &[])
.expect("start_registration");
let req = RegistrationRequest::from_challenge(
&ccr,
user_uuid.as_bytes().to_vec(),
user_name,
"Alice Example",
)
.expect("build RegistrationRequest");
let (tx, rx) = std::sync::mpsc::sync_channel(1);
unsafe {
perform_registration(req, move |result| {
let _ = tx.send(result);
})
.expect("perform_registration launched");
}
loop {
match rx.try_recv() {
Ok(result) => {
let native_reg = result.expect("registration succeeded");
let credential = native_registration_to_credential(&native_reg)
.expect("build RegisterPublicKeyCredential");
let passkey = rp
.finish_registration(&credential, ®_state)
.expect("finish_registration");
println!("Registered passkey: {:?}", passkey.cred_id());
return;
}
Err(std::sync::mpsc::TryRecvError::Empty) => {
unsafe {
use objc2::runtime::AnyObject;
let rl: *const AnyObject =
objc2::msg_send![objc2::runtime::AnyClass::get("NSRunLoop").unwrap(), currentRunLoop];
let mode: *const AnyObject =
objc2::msg_send![objc2::runtime::AnyClass::get("NSString").unwrap(),
stringWithUTF8String: c"kCFRunLoopDefaultMode".as_ptr()];
let date: *const AnyObject =
objc2::msg_send![objc2::runtime::AnyClass::get("NSDate").unwrap(),
dateWithTimeIntervalSinceNow: 0.1f64];
let _: bool = objc2::msg_send![rl, runMode: mode beforeDate: date];
}
}
Err(std::sync::mpsc::TryRecvError::Disconnected) => {
eprintln!("ceremony cancelled");
return;
}
}
}
}