smart_account_auth/
credential.rs1use saa_schema::{saa_derivable, saa_type};
2use saa_common::{Binary, String, CredentialId};
3
4pub use saa_auth::caller::Caller;
5#[cfg(feature = "ethereum")]
6pub use saa_auth::eth::EthPersonalSign;
7#[cfg(feature = "cosmos")]
8pub use saa_auth::cosmos::CosmosArbitrary;
9#[cfg(feature = "passkeys")]
10pub use saa_auth::passkey::PasskeyCredential;
11#[cfg(feature = "ed25519")]
12pub use saa_curves::ed25519::Ed25519;
13#[cfg(feature = "curves")]
14pub use saa_curves::{secp256k1::Secp256k1, secp256r1::Secp256r1};
15
16
17
18#[saa_derivable(name(CredentialName))]
19pub enum Credential {
20 Native(Caller),
21
22 #[cfg(feature = "ethereum")]
23 EthPersonalSign(EthPersonalSign),
24
25 #[cfg(feature = "cosmos")]
26 CosmosArbitrary(CosmosArbitrary),
27
28 #[cfg(feature = "passkeys")]
29 Passkey(PasskeyCredential),
30
31 #[cfg(feature = "ed25519")]
32 Ed25519(Ed25519),
33
34 #[cfg(feature = "curves")]
35 Secp256k1(Secp256k1),
36
37 #[cfg(feature = "curves")]
38 Secp256r1(Secp256r1),
39}
40
41
42
43
44
45
46#[saa_type]
47pub struct CredentialInfo {
48 pub name: CredentialName,
50 pub hrp: Option<String>,
52 pub extension: Option<Binary>,
54}
55
56
57
58pub type CredentialRecord = (CredentialId, CredentialInfo);
59
60
61
62#[allow(unused, dead_code)]
63#[cfg(feature = "wasm")]
64pub fn build_credential(
65 record : CredentialRecord,
66 msg : crate::msgs::SignedDataMsg,
67 extension : Option<Binary>,
68) -> Result<Credential, saa_common::AuthError> {
69 let (id, info) = record;
70 let message = msg.data;
71 let signature = msg.signature;
72 let name = info.name;
73
74 let credential = match name {
75
76 CredentialName::Native => Credential::Native(Caller(id)),
77
78 #[cfg(feature = "ethereum")]
79 CredentialName::EthPersonalSign => Credential::EthPersonalSign(EthPersonalSign {
80 message,
81 signature,
82 signer: id,
83 }
84 ),
85
86 #[cfg(feature = "cosmos")]
87 CredentialName::CosmosArbitrary => Credential::CosmosArbitrary(CosmosArbitrary {
88 pubkey: Binary::from_base64(&id)?,
89 message,
90 signature,
91 hrp: info.hrp,
92 }),
93
94 #[cfg(feature = "passkeys")]
95 CredentialName::Passkey => {
96 use saa_auth::passkey::{
97 ClientData, PasskeyInfo, PasskeyPayload, utils::base64_to_url
98 };
99
100 let stored_info = info.extension
101 .map(|e| saa_common::from_json::<PasskeyInfo>(e).ok() )
102 .flatten()
103 .ok_or_else(|| saa_common::AuthError::generic("Missing passkey info"))?;
104
105 let (origin, other_keys) = match extension
106 .map(|e| saa_common::from_json::<PasskeyPayload>(e).ok())
107 .flatten()
108 {
109 Some(payload) => (payload.origin, payload.other_keys),
110 None => (None, None),
111 };
112
113 let client_data = ClientData::new(
114 "webauthn.get",
115 base64_to_url(message.to_base64().as_str()),
116 origin.unwrap_or(stored_info.origin),
117 stored_info.cross_origin,
118 other_keys
119 );
120
121 Credential::Passkey(PasskeyCredential {
122 id,
123 signature,
124 client_data,
125 pubkey: Some(stored_info.pubkey),
126 authenticator_data: stored_info.authenticator_data,
127 user_handle: stored_info.user_handle,
128 })
129 },
130 #[cfg(feature = "ed25519")]
131 CredentialName::Ed25519 => Credential::Ed25519(Ed25519 {
132 pubkey: Binary::from_base64(&id)?,
133 signature,
134 message,
135 }),
136 #[cfg(feature = "curves")]
137 curves => {
138 let pubkey = Binary::from_base64(&id)?;
139 match curves {
140 CredentialName::Secp256k1 => Credential::Secp256k1(Secp256k1 {
141 pubkey,
142 signature,
143 message,
144 hrp: info.hrp,
145 }),
146 _ => return Err(saa_common::AuthError::generic("Unsupported curve")),
147 }
148 }
149 };
150 Ok(credential)
151}