use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
pub struct PasskeyLoginStartRequest {
#[serde(rename = "subject", alias = "did")]
pub did: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
pub struct PasskeyLoginStartResponse {
pub session_id: String,
pub challenge: String,
#[serde(default)]
pub allow_credentials: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
pub struct PasskeyLoginFinishRequest {
pub session_id: String,
pub credential_id: String,
pub authenticator_data: String,
#[serde(rename = "clientDataJSON")]
pub client_data_json: String,
pub signature: String,
pub verification_method: String,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn start_response_camel_case() {
let json = r#"{
"sessionId": "sess-1",
"challenge": "deadbeef",
"allowCredentials": ["abc","def"]
}"#;
let parsed: PasskeyLoginStartResponse = serde_json::from_str(json).unwrap();
assert_eq!(parsed.session_id, "sess-1");
assert_eq!(parsed.challenge, "deadbeef");
assert_eq!(parsed.allow_credentials, vec!["abc", "def"]);
}
#[test]
fn finish_request_camel_case() {
let json = r#"{
"sessionId": "sess-1",
"credentialId": "cred-id-b64",
"authenticatorData": "ad-b64",
"clientDataJSON": "cd-b64",
"signature": "sig-b64",
"verificationMethod": "did:webvh:example.com:alice#passkey-abc"
}"#;
let parsed: PasskeyLoginFinishRequest = serde_json::from_str(json).unwrap();
assert_eq!(parsed.session_id, "sess-1");
assert_eq!(parsed.credential_id, "cred-id-b64");
assert_eq!(
parsed.verification_method,
"did:webvh:example.com:alice#passkey-abc"
);
}
}