Skip to main content

passkey_server/
types.rs

1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone)]
4pub struct PasskeyConfig {
5    pub rp_id: String,
6    pub rp_name: String,
7    pub origin: String,
8    pub state_ttl: i64,
9}
10
11#[derive(Debug, Serialize, Deserialize, Clone)]
12pub struct StoredPasskey {
13    pub user_id: String,
14    pub cred_id: String,
15    pub public_key: String, // Base64url-encoded COSE key
16    pub name: String,
17    pub created_at: i64,
18    pub last_used_at: i64,
19    pub counter: i64,
20}
21
22#[derive(Debug, Serialize, Deserialize, Clone)]
23pub struct PasskeyState {
24    pub id: String,
25    pub state_json: String,
26    pub expires_at: i64,
27}
28
29// WebAuthn Protocol Types
30
31#[derive(Serialize, Deserialize, Debug, Clone)]
32#[serde(rename_all = "camelCase")]
33pub struct PublicKeyCredentialCreationOptions {
34    pub rp: RpEntity,
35    pub user: UserEntity,
36    pub challenge: String,
37    pub pub_key_cred_params: Vec<PubKeyCredParam>,
38    #[serde(skip_serializing_if = "Option::is_none")]
39    pub timeout: Option<u64>,
40    #[serde(skip_serializing_if = "Option::is_none")]
41    pub exclude_credentials: Option<Vec<CredentialDescriptor>>,
42    #[serde(skip_serializing_if = "Option::is_none")]
43    pub authenticator_selection: Option<AuthenticatorSelection>,
44    #[serde(skip_serializing_if = "Option::is_none")]
45    pub attestation: Option<String>,
46}
47
48#[derive(Serialize, Deserialize, Debug, Clone)]
49#[serde(rename_all = "camelCase")]
50pub struct PublicKeyCredentialRequestOptions {
51    pub challenge: String,
52    #[serde(skip_serializing_if = "Option::is_none")]
53    pub timeout: Option<u64>,
54    pub rp_id: String,
55    #[serde(skip_serializing_if = "Option::is_none")]
56    pub allow_credentials: Option<Vec<CredentialDescriptor>>,
57    #[serde(skip_serializing_if = "Option::is_none")]
58    pub user_verification: Option<String>,
59}
60
61#[derive(Serialize, Deserialize, Debug, Clone)]
62#[serde(rename_all = "camelCase")]
63pub struct RpEntity {
64    pub name: String,
65    pub id: String,
66}
67
68#[derive(Serialize, Deserialize, Debug, Clone)]
69#[serde(rename_all = "camelCase")]
70pub struct UserEntity {
71    pub id: String,
72    pub name: String,
73    pub display_name: String,
74}
75
76#[derive(Serialize, Deserialize, Debug, Clone)]
77#[serde(rename_all = "camelCase")]
78pub struct PubKeyCredParam {
79    #[serde(rename = "type")]
80    pub type_: String,
81    pub alg: i32,
82}
83
84#[derive(Serialize, Deserialize, Debug, Clone)]
85#[serde(rename_all = "camelCase")]
86pub struct CredentialDescriptor {
87    #[serde(rename = "type")]
88    pub type_: String,
89    pub id: String,
90    #[serde(skip_serializing_if = "Option::is_none")]
91    pub transports: Option<Vec<String>>,
92}
93
94#[derive(Serialize, Deserialize, Debug, Clone)]
95#[serde(rename_all = "camelCase")]
96pub struct AuthenticatorSelection {
97    #[serde(skip_serializing_if = "Option::is_none")]
98    pub authenticator_attachment: Option<String>,
99    #[serde(skip_serializing_if = "Option::is_none")]
100    pub require_resident_key: Option<bool>,
101    #[serde(skip_serializing_if = "Option::is_none")]
102    pub resident_key: Option<String>,
103    #[serde(skip_serializing_if = "Option::is_none")]
104    pub user_verification: Option<String>,
105}
106
107// Client response types
108
109#[derive(Serialize, Deserialize, Debug, Clone)]
110#[serde(rename_all = "camelCase")]
111pub struct RegistrationResponse {
112    pub id: String,
113    pub raw_id: String,
114    #[serde(rename = "type")]
115    pub type_: String,
116    pub response: AttestationResponse,
117    #[serde(skip_serializing_if = "Option::is_none")]
118    pub client_extension_results: Option<serde_json::Value>,
119    // Extension: Allow defining a name for the credential
120    pub name: Option<String>,
121}
122
123#[derive(Serialize, Deserialize, Debug, Clone)]
124#[serde(rename_all = "camelCase")]
125pub struct AttestationResponse {
126    #[serde(rename = "clientDataJSON")]
127    pub client_data_json: String,
128    pub attestation_object: String,
129}
130
131#[derive(Serialize, Deserialize, Debug, Clone)]
132#[serde(rename_all = "camelCase")]
133pub struct LoginResponse {
134    pub id: String,
135    pub raw_id: String,
136    #[serde(rename = "type")]
137    pub type_: String,
138    pub response: AssertionResponse,
139    #[serde(skip_serializing_if = "Option::is_none")]
140    pub client_extension_results: Option<serde_json::Value>,
141}
142
143#[derive(Serialize, Deserialize, Debug, Clone)]
144#[serde(rename_all = "camelCase")]
145pub struct AssertionResponse {
146    #[serde(rename = "clientDataJSON")]
147    pub client_data_json: String,
148    pub authenticator_data: String,
149    pub signature: String,
150    #[serde(skip_serializing_if = "Option::is_none")]
151    pub user_handle: Option<String>,
152}