use super::helpers::{
create_test_attestation_object, create_test_auth_client_data_json,
create_test_authenticator_data, create_test_client_data_json,
};
use crate::*;
fn registration_state(passki: &Passki) -> RegistrationState {
passki
.start_passkey_registration(
b"user123_16bytes_",
"testuser",
"Test User",
RegistrationOptions::default(),
)
.unwrap()
.1
}
#[test]
fn test_finish_passkey_registration_populates_be_and_bs() {
let passki = Passki::new("localhost", &["http://localhost:3000"], "Test App");
let state = registration_state(&passki);
let attestation_obj = create_test_attestation_object(-7, 0x40 | 0x01 | 0x08 | 0x10);
let client_data_json = create_test_client_data_json(&state.challenge, "http://localhost:3000");
let credential = RegistrationCredential {
credential_id: Passki::base64_encode(&[1u8; 16]),
public_key: Passki::base64_encode(&attestation_obj),
client_data_json: Passki::base64_encode(&client_data_json),
client_extension_results: None,
authenticator_attachment: None,
transports: Vec::new(),
};
let passkey = passki
.finish_passkey_registration(&credential, &state)
.unwrap();
assert!(passkey.be);
assert!(passkey.bs);
}
#[test]
fn test_finish_passkey_registration_be_without_bs() {
let passki = Passki::new("localhost", &["http://localhost:3000"], "Test App");
let state = registration_state(&passki);
let attestation_obj = create_test_attestation_object(-7, 0x40 | 0x01 | 0x08);
let client_data_json = create_test_client_data_json(&state.challenge, "http://localhost:3000");
let credential = RegistrationCredential {
credential_id: Passki::base64_encode(&[1u8; 16]),
public_key: Passki::base64_encode(&attestation_obj),
client_data_json: Passki::base64_encode(&client_data_json),
client_extension_results: None,
authenticator_attachment: None,
transports: Vec::new(),
};
let passkey = passki
.finish_passkey_registration(&credential, &state)
.unwrap();
assert!(passkey.be);
assert!(!passkey.bs);
}
#[test]
fn test_finish_passkey_registration_no_backup_flags() {
let passki = Passki::new("localhost", &["http://localhost:3000"], "Test App");
let state = registration_state(&passki);
let attestation_obj = create_test_attestation_object(-7, 0x40 | 0x01);
let client_data_json = create_test_client_data_json(&state.challenge, "http://localhost:3000");
let credential = RegistrationCredential {
credential_id: Passki::base64_encode(&[1u8; 16]),
public_key: Passki::base64_encode(&attestation_obj),
client_data_json: Passki::base64_encode(&client_data_json),
client_extension_results: None,
authenticator_attachment: None,
transports: Vec::new(),
};
let passkey = passki
.finish_passkey_registration(&credential, &state)
.unwrap();
assert!(!passkey.be);
assert!(!passkey.bs);
}
#[test]
fn test_finish_passkey_registration_bs_without_be_rejected() {
let passki = Passki::new("localhost", &["http://localhost:3000"], "Test App");
let state = registration_state(&passki);
let attestation_obj = create_test_attestation_object(-7, 0x40 | 0x01 | 0x10);
let client_data_json = create_test_client_data_json(&state.challenge, "http://localhost:3000");
let credential = RegistrationCredential {
credential_id: Passki::base64_encode(&[1u8; 16]),
public_key: Passki::base64_encode(&attestation_obj),
client_data_json: Passki::base64_encode(&client_data_json),
client_extension_results: None,
authenticator_attachment: None,
transports: Vec::new(),
};
let result = passki.finish_passkey_registration(&credential, &state);
assert!(matches!(
result.unwrap_err(),
PasskiError::InvalidBackupFlags
));
}
#[test]
fn test_finish_passkey_authentication_bs_without_be_rejected() {
let passki = Passki::new("localhost", &["http://localhost:3000"], "Test App");
let stored_passkey = StoredPasskey {
credential_id: vec![1u8; 16],
public_key: vec![2u8; 64],
counter: 5,
algorithm: -7,
aaguid: [0u8; 16],
attestation_type: AttestationType::None,
transports: Vec::new(),
rk: None,
large_blob_supported: None,
be: false,
bs: false,
};
let passkeys = vec![stored_passkey.clone()];
let (_challenge, state) =
passki.start_passkey_authentication(&passkeys, AuthenticationOptions::default());
let authenticator_data = create_test_authenticator_data(6, 0x01 | 0x10);
let client_data_json =
create_test_auth_client_data_json(&state.challenge, "http://localhost:3000");
let credential = AuthenticationCredential {
credential_id: Passki::base64_encode(&[1u8; 16]),
authenticator_data: Passki::base64_encode(&authenticator_data),
client_data_json: Passki::base64_encode(&client_data_json),
signature: Passki::base64_encode(&[9u8; 64]),
user_handle: None,
client_extension_results: None,
authenticator_attachment: None,
};
let result = passki.finish_passkey_authentication(&credential, &state, &stored_passkey);
assert!(matches!(
result.unwrap_err(),
PasskiError::InvalidBackupFlags
));
}
#[test]
fn test_stored_passkey_deserializes_without_be_bs_fields() {
let json = serde_json::json!({
"credential_id": [1, 2, 3],
"public_key": [4, 5, 6],
"counter": 0,
"algorithm": -7
});
let passkey: StoredPasskey = serde_json::from_value(json).unwrap();
assert!(!passkey.be);
assert!(!passkey.bs);
}
#[test]
fn test_stored_passkey_be_bs_roundtrip() {
let passkey = StoredPasskey {
credential_id: vec![1u8; 16],
public_key: vec![2u8; 32],
counter: 0,
algorithm: -7,
aaguid: [0u8; 16],
attestation_type: AttestationType::None,
transports: Vec::new(),
rk: None,
large_blob_supported: None,
be: true,
bs: true,
};
let json = serde_json::to_string(&passkey).unwrap();
let restored: StoredPasskey = serde_json::from_str(&json).unwrap();
assert!(restored.be);
assert!(restored.bs);
}