use super::helpers::{create_test_attestation_object, create_test_client_data_json};
use crate::*;
#[test]
fn test_cred_props_in_challenge_when_requested() {
let passki = Passki::new("localhost", "http://localhost:3000", "Test");
let (challenge, _) = passki
.start_passkey_registration(
b"user123_16bytes_",
"alice",
"Alice",
60000,
AttestationConveyancePreference::None,
ResidentKeyRequirement::Preferred,
UserVerificationRequirement::Preferred,
None,
Some(RegistrationExtensions {
cred_props: Some(true),
..Default::default()
}),
)
.unwrap();
let json = serde_json::to_value(&challenge).unwrap();
assert_eq!(json["extensions"]["credProps"], true);
}
#[test]
fn test_cred_props_absent_from_challenge_when_not_requested() {
let passki = Passki::new("localhost", "http://localhost:3000", "Test");
let (challenge, _) = passki
.start_passkey_registration(
b"user123_16bytes_",
"alice",
"Alice",
60000,
AttestationConveyancePreference::None,
ResidentKeyRequirement::Preferred,
UserVerificationRequirement::Preferred,
None,
None,
)
.unwrap();
let json = serde_json::to_value(&challenge).unwrap();
assert!(json.get("extensions").is_none());
}
#[test]
fn test_cred_props_and_prf_can_be_requested_together() {
let passki = Passki::new("localhost", "http://localhost:3000", "Test");
let (challenge, _) = passki
.start_passkey_registration(
b"user123_16bytes_",
"alice",
"Alice",
60000,
AttestationConveyancePreference::None,
ResidentKeyRequirement::Preferred,
UserVerificationRequirement::Preferred,
None,
Some(RegistrationExtensions {
cred_props: Some(true),
prf: Some(PrfInput { eval: None }),
}),
)
.unwrap();
let json = serde_json::to_value(&challenge).unwrap();
assert_eq!(json["extensions"]["credProps"], true);
assert!(json["extensions"]["prf"].is_object());
}
fn make_credential(
state: &RegistrationState,
cred_props: Option<CredPropsResult>,
) -> RegistrationCredential {
let attestation_obj = create_test_attestation_object(-7, 0x45);
let client_data_json = create_test_client_data_json(&state.challenge, "http://localhost:3000");
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: Some(ClientExtensionResults {
cred_props,
prf: None,
}),
}
}
#[test]
fn test_cred_props_rk_true_surfaced_in_result() {
let passki = Passki::new("localhost", "http://localhost:3000", "Test App");
let (_, state) = passki
.start_passkey_registration(
b"user123_16bytes_",
"testuser",
"Test User",
60000,
AttestationConveyancePreference::None,
ResidentKeyRequirement::Preferred,
UserVerificationRequirement::Preferred,
None,
Some(RegistrationExtensions {
cred_props: Some(true),
..Default::default()
}),
)
.unwrap();
let credential = make_credential(&state, Some(CredPropsResult { rk: Some(true) }));
let result = passki
.finish_passkey_registration(&credential, &state)
.unwrap();
assert_eq!(result.rk, Some(true));
}
#[test]
fn test_cred_props_rk_false_surfaced_in_result() {
let passki = Passki::new("localhost", "http://localhost:3000", "Test App");
let (_, state) = passki
.start_passkey_registration(
b"user123_16bytes_",
"testuser",
"Test User",
60000,
AttestationConveyancePreference::None,
ResidentKeyRequirement::Preferred,
UserVerificationRequirement::Preferred,
None,
Some(RegistrationExtensions {
cred_props: Some(true),
..Default::default()
}),
)
.unwrap();
let credential = make_credential(&state, Some(CredPropsResult { rk: Some(false) }));
let result = passki
.finish_passkey_registration(&credential, &state)
.unwrap();
assert_eq!(result.rk, Some(false));
}
#[test]
fn test_cred_props_rk_none_when_no_extension_results() {
let passki = Passki::new("localhost", "http://localhost:3000", "Test App");
let (_, state) = passki
.start_passkey_registration(
b"user123_16bytes_",
"testuser",
"Test User",
60000,
AttestationConveyancePreference::None,
ResidentKeyRequirement::Preferred,
UserVerificationRequirement::Preferred,
None,
None,
)
.unwrap();
let attestation_obj = create_test_attestation_object(-7, 0x45);
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,
};
let result = passki
.finish_passkey_registration(&credential, &state)
.unwrap();
assert_eq!(result.rk, None);
}
#[test]
fn test_cred_props_rk_none_when_rk_not_reported() {
let passki = Passki::new("localhost", "http://localhost:3000", "Test App");
let (_, state) = passki
.start_passkey_registration(
b"user123_16bytes_",
"testuser",
"Test User",
60000,
AttestationConveyancePreference::None,
ResidentKeyRequirement::Preferred,
UserVerificationRequirement::Preferred,
None,
Some(RegistrationExtensions {
cred_props: Some(true),
..Default::default()
}),
)
.unwrap();
let credential = make_credential(&state, Some(CredPropsResult { rk: None }));
let result = passki
.finish_passkey_registration(&credential, &state)
.unwrap();
assert_eq!(result.rk, None);
}
#[test]
fn test_cred_props_result_deserializes_rk_true() {
let json = r#"{"rk": true}"#;
let result: CredPropsResult = serde_json::from_str(json).unwrap();
assert_eq!(result.rk, Some(true));
}
#[test]
fn test_cred_props_result_deserializes_rk_false() {
let json = r#"{"rk": false}"#;
let result: CredPropsResult = serde_json::from_str(json).unwrap();
assert_eq!(result.rk, Some(false));
}
#[test]
fn test_cred_props_result_deserializes_missing_rk_as_none() {
let json = r#"{}"#;
let result: CredPropsResult = serde_json::from_str(json).unwrap();
assert_eq!(result.rk, None);
}
#[test]
fn test_client_extension_results_deserializes_cred_props() {
let json = r#"{"credProps": {"rk": true}}"#;
let result: ClientExtensionResults = serde_json::from_str(json).unwrap();
assert_eq!(result.cred_props.unwrap().rk, Some(true));
assert!(result.prf.is_none());
}