diff --git a/native/native_rust_library/src/identity.rs b/native/native_rust_library/src/identity.rs index 50cc2166d..3e1d6e9fe 100644 --- a/native/native_rust_library/src/identity.rs +++ b/native/native_rust_library/src/identity.rs @@ -1,139 +1,168 @@ use grpc_clients::identity::get_unauthenticated_client; use grpc_clients::identity::protos::unauth::{AuthResponse, Empty}; use serde::Serialize; use crate::utils::jsi_callbacks::{ handle_bool_result_as_callback, handle_string_result_as_callback, }; use crate::{Error, RUNTIME}; use crate::{CODE_VERSION, DEVICE_TYPE, IDENTITY_SOCKET_ADDR}; pub mod account_actions; pub mod device_list; pub mod exact_user_search; pub mod farcaster; pub mod find_user_identities; pub mod login; pub mod registration; pub mod x3dh; pub mod ffi { use super::*; pub use account_actions::ffi::*; pub use device_list::ffi::*; pub use exact_user_search::ffi::*; pub use farcaster::ffi::*; pub use find_user_identities::ffi::*; pub use login::ffi::*; pub use registration::ffi::*; pub use x3dh::ffi::*; pub fn generate_nonce(promise_id: u32) { RUNTIME.spawn(async move { let result = fetch_nonce().await; handle_string_result_as_callback(result, promise_id); }); } pub fn version_supported(promise_id: u32) { RUNTIME.spawn(async move { let result = version_supported_helper().await; handle_bool_result_as_callback(result, promise_id); }); } } // helper structs pub struct AuthInfo { pub user_id: String, pub device_id: String, pub access_token: String, } -pub struct PasswordUserInfo { - pub username: String, - pub password: String, +pub struct DeviceKeys { pub key_payload: String, pub key_payload_signature: String, pub content_prekey: String, pub content_prekey_signature: String, pub notif_prekey: String, pub notif_prekey_signature: String, pub content_one_time_keys: Vec, pub notif_one_time_keys: Vec, +} + +pub struct LogInPasswordUserInfo { + pub username: String, + pub password: String, + pub device_keys: DeviceKeys, +} + +pub struct RegisterPasswordUserInfo { + pub username: String, + pub password: String, + pub device_keys: DeviceKeys, pub farcaster_id: Option, + pub initial_device_list: String, } -pub struct WalletUserInfo { +pub struct RegisterReservedPasswordUserInfo { + pub username: String, + pub password: String, + pub device_keys: DeviceKeys, + pub keyserver_message: String, + pub keyserver_signature: String, + pub initial_device_list: String, +} + +pub struct LogInWalletUserInfo { pub siwe_message: String, pub siwe_signature: String, - pub key_payload: String, - pub key_payload_signature: String, - pub content_prekey: String, - pub content_prekey_signature: String, - pub notif_prekey: String, - pub notif_prekey_signature: String, - pub content_one_time_keys: Vec, - pub notif_one_time_keys: Vec, + pub device_keys: DeviceKeys, +} + +pub struct RegisterWalletUserInfo { + pub siwe_message: String, + pub siwe_signature: String, + pub device_keys: DeviceKeys, pub farcaster_id: Option, + pub initial_device_list: String, +} + +pub struct RegisterReservedWalletUserInfo { + pub siwe_message: String, + pub siwe_signature: String, + pub device_keys: DeviceKeys, + pub keyserver_message: String, + pub keyserver_signature: String, + pub initial_device_list: String, } #[derive(Serialize)] #[serde(rename_all = "camelCase")] pub struct UserIDAndDeviceAccessToken { #[serde(rename = "userID")] user_id: String, access_token: String, } impl From for UserIDAndDeviceAccessToken { fn from(value: AuthResponse) -> Self { let AuthResponse { user_id, access_token, } = value; Self { user_id, access_token, } } } // API implementation helpers async fn fetch_nonce() -> Result { let mut identity_client = get_unauthenticated_client( IDENTITY_SOCKET_ADDR, CODE_VERSION, DEVICE_TYPE.as_str_name().to_lowercase(), ) .await?; let nonce = identity_client .generate_nonce(Empty {}) .await? .into_inner() .nonce; Ok(nonce) } async fn version_supported_helper() -> Result { let mut identity_client = get_unauthenticated_client( IDENTITY_SOCKET_ADDR, CODE_VERSION, DEVICE_TYPE.as_str_name().to_lowercase(), ) .await?; let response = identity_client.ping(Empty {}).await; match response { Ok(_) => Ok(true), Err(e) => { if grpc_clients::error::is_version_unsupported(&e) { Ok(false) } else { Err(e.into()) } } } } diff --git a/native/native_rust_library/src/identity/login.rs b/native/native_rust_library/src/identity/login.rs index acb47c962..89f6baf53 100644 --- a/native/native_rust_library/src/identity/login.rs +++ b/native/native_rust_library/src/identity/login.rs @@ -1,307 +1,323 @@ use comm_opaque2::client::Login; use grpc_clients::identity::{ get_unauthenticated_client, protos::unauth::{ DeviceKeyUpload, ExistingDeviceLoginRequest, IdentityKeyInfo, OpaqueLoginFinishRequest, OpaqueLoginStartRequest, Prekey, SecondaryDeviceKeysUploadRequest, WalletAuthRequest, }, }; use tracing::instrument; -use super::{PasswordUserInfo, UserIDAndDeviceAccessToken, WalletUserInfo}; +use super::{ + LogInPasswordUserInfo, LogInWalletUserInfo, UserIDAndDeviceAccessToken, +}; use crate::utils::jsi_callbacks::handle_string_result_as_callback; use crate::{Error, CODE_VERSION, DEVICE_TYPE, IDENTITY_SOCKET_ADDR, RUNTIME}; pub mod ffi { + use crate::identity::{ + DeviceKeys, LogInPasswordUserInfo, LogInWalletUserInfo, + }; + use super::*; #[instrument] pub fn log_in_password_user( username: String, password: String, key_payload: String, key_payload_signature: String, content_prekey: String, content_prekey_signature: String, notif_prekey: String, notif_prekey_signature: String, promise_id: u32, ) { RUNTIME.spawn(async move { - let password_user_info = PasswordUserInfo { + let password_user_info = LogInPasswordUserInfo { username, password, - key_payload, - key_payload_signature, - content_prekey, - content_prekey_signature, - notif_prekey, - notif_prekey_signature, - content_one_time_keys: Vec::new(), - notif_one_time_keys: Vec::new(), - farcaster_id: None, + device_keys: DeviceKeys { + key_payload, + key_payload_signature, + content_prekey, + content_prekey_signature, + notif_prekey, + notif_prekey_signature, + content_one_time_keys: Vec::new(), + notif_one_time_keys: Vec::new(), + }, }; let result = log_in_password_user_helper(password_user_info).await; handle_string_result_as_callback(result, promise_id); }); } #[instrument] pub fn log_in_wallet_user( siwe_message: String, siwe_signature: String, key_payload: String, key_payload_signature: String, content_prekey: String, content_prekey_signature: String, notif_prekey: String, notif_prekey_signature: String, promise_id: u32, ) { RUNTIME.spawn(async move { - let wallet_user_info = WalletUserInfo { + let wallet_user_info = LogInWalletUserInfo { siwe_message, siwe_signature, - key_payload, - key_payload_signature, - content_prekey, - content_prekey_signature, - notif_prekey, - notif_prekey_signature, - content_one_time_keys: Vec::new(), - notif_one_time_keys: Vec::new(), - farcaster_id: None, + device_keys: DeviceKeys { + key_payload, + key_payload_signature, + content_prekey, + content_prekey_signature, + notif_prekey, + notif_prekey_signature, + content_one_time_keys: Vec::new(), + notif_one_time_keys: Vec::new(), + }, }; let result = log_in_wallet_user_helper(wallet_user_info).await; handle_string_result_as_callback(result, promise_id); }); } // QR code device log in pub fn upload_secondary_device_keys_and_log_in( user_id: String, nonce: String, nonce_signature: String, key_payload: String, key_payload_signature: String, content_prekey: String, content_prekey_signature: String, notif_prekey: String, notif_prekey_signature: String, content_one_time_keys: Vec, notif_one_time_keys: Vec, promise_id: u32, ) { RUNTIME.spawn(async move { let device_key_upload = DeviceKeyUpload { device_key_info: Some(IdentityKeyInfo { payload: key_payload, payload_signature: key_payload_signature, }), content_upload: Some(Prekey { prekey: content_prekey, prekey_signature: content_prekey_signature, }), notif_upload: Some(Prekey { prekey: notif_prekey, prekey_signature: notif_prekey_signature, }), one_time_content_prekeys: content_one_time_keys, one_time_notif_prekeys: notif_one_time_keys, device_type: DEVICE_TYPE.into(), }; let result = upload_secondary_device_keys_and_log_in_helper( user_id, nonce, nonce_signature, device_key_upload, ) .await; handle_string_result_as_callback(result, promise_id); }); } pub fn log_in_existing_device( user_id: String, device_id: String, nonce: String, nonce_signature: String, promise_id: u32, ) { RUNTIME.spawn(async move { let result = log_in_existing_device_helper( user_id, device_id, nonce, nonce_signature, ) .await; handle_string_result_as_callback(result, promise_id); }); } } async fn log_in_password_user_helper( - password_user_info: PasswordUserInfo, + password_user_info: LogInPasswordUserInfo, ) -> Result { let mut client_login = Login::new(); let opaque_login_request = client_login .start(&password_user_info.password) .map_err(crate::handle_error)?; let login_start_request = OpaqueLoginStartRequest { opaque_login_request, username: password_user_info.username, device_key_upload: Some(DeviceKeyUpload { device_key_info: Some(IdentityKeyInfo { - payload: password_user_info.key_payload, - payload_signature: password_user_info.key_payload_signature, + payload: password_user_info.device_keys.key_payload, + payload_signature: password_user_info.device_keys.key_payload_signature, }), content_upload: Some(Prekey { - prekey: password_user_info.content_prekey, - prekey_signature: password_user_info.content_prekey_signature, + prekey: password_user_info.device_keys.content_prekey, + prekey_signature: password_user_info + .device_keys + .content_prekey_signature, }), notif_upload: Some(Prekey { - prekey: password_user_info.notif_prekey, - prekey_signature: password_user_info.notif_prekey_signature, + prekey: password_user_info.device_keys.notif_prekey, + prekey_signature: password_user_info.device_keys.notif_prekey_signature, }), - one_time_content_prekeys: password_user_info.content_one_time_keys, - one_time_notif_prekeys: password_user_info.notif_one_time_keys, + one_time_content_prekeys: password_user_info + .device_keys + .content_one_time_keys, + one_time_notif_prekeys: password_user_info + .device_keys + .notif_one_time_keys, device_type: DEVICE_TYPE.into(), }), force: None, }; let mut identity_client = get_unauthenticated_client( IDENTITY_SOCKET_ADDR, CODE_VERSION, DEVICE_TYPE.as_str_name().to_lowercase(), ) .await?; let response = identity_client .log_in_password_user_start(login_start_request) .await?; let login_start_response = response.into_inner(); let opaque_login_upload = client_login .finish(&login_start_response.opaque_login_response) .map_err(crate::handle_error)?; let login_finish_request = OpaqueLoginFinishRequest { session_id: login_start_response.session_id, opaque_login_upload, }; let login_finish_response = identity_client .log_in_password_user_finish(login_finish_request) .await? .into_inner(); let user_id_and_access_token = UserIDAndDeviceAccessToken::from(login_finish_response); Ok(serde_json::to_string(&user_id_and_access_token)?) } async fn log_in_wallet_user_helper( - wallet_user_info: WalletUserInfo, + wallet_user_info: LogInWalletUserInfo, ) -> Result { let login_request = WalletAuthRequest { siwe_message: wallet_user_info.siwe_message, siwe_signature: wallet_user_info.siwe_signature, device_key_upload: Some(DeviceKeyUpload { device_key_info: Some(IdentityKeyInfo { - payload: wallet_user_info.key_payload, - payload_signature: wallet_user_info.key_payload_signature, + payload: wallet_user_info.device_keys.key_payload, + payload_signature: wallet_user_info.device_keys.key_payload_signature, }), content_upload: Some(Prekey { - prekey: wallet_user_info.content_prekey, - prekey_signature: wallet_user_info.content_prekey_signature, + prekey: wallet_user_info.device_keys.content_prekey, + prekey_signature: wallet_user_info.device_keys.content_prekey_signature, }), notif_upload: Some(Prekey { - prekey: wallet_user_info.notif_prekey, - prekey_signature: wallet_user_info.notif_prekey_signature, + prekey: wallet_user_info.device_keys.notif_prekey, + prekey_signature: wallet_user_info.device_keys.notif_prekey_signature, }), - one_time_content_prekeys: wallet_user_info.content_one_time_keys, - one_time_notif_prekeys: wallet_user_info.notif_one_time_keys, + one_time_content_prekeys: wallet_user_info + .device_keys + .content_one_time_keys, + one_time_notif_prekeys: wallet_user_info.device_keys.notif_one_time_keys, device_type: DEVICE_TYPE.into(), }), farcaster_id: None, initial_device_list: "".to_string(), }; let mut identity_client = get_unauthenticated_client( IDENTITY_SOCKET_ADDR, CODE_VERSION, DEVICE_TYPE.as_str_name().to_lowercase(), ) .await?; let login_response = identity_client .log_in_wallet_user(login_request) .await? .into_inner(); let user_id_and_access_token = UserIDAndDeviceAccessToken::from(login_response); Ok(serde_json::to_string(&user_id_and_access_token)?) } async fn upload_secondary_device_keys_and_log_in_helper( user_id: String, nonce: String, nonce_signature: String, device_key_upload: DeviceKeyUpload, ) -> Result { let mut identity_client = get_unauthenticated_client( IDENTITY_SOCKET_ADDR, CODE_VERSION, DEVICE_TYPE.as_str_name().to_lowercase(), ) .await?; let request = SecondaryDeviceKeysUploadRequest { user_id, nonce, nonce_signature, device_key_upload: Some(device_key_upload), }; let response = identity_client .upload_keys_for_registered_device_and_log_in(request) .await? .into_inner(); let user_id_and_access_token = UserIDAndDeviceAccessToken::from(response); Ok(serde_json::to_string(&user_id_and_access_token)?) } async fn log_in_existing_device_helper( user_id: String, device_id: String, nonce: String, nonce_signature: String, ) -> Result { let mut identity_client = get_unauthenticated_client( IDENTITY_SOCKET_ADDR, CODE_VERSION, DEVICE_TYPE.as_str_name().to_lowercase(), ) .await?; let request = ExistingDeviceLoginRequest { user_id, device_id, nonce, nonce_signature, }; let response = identity_client .log_in_existing_device(request) .await? .into_inner(); let user_id_and_access_token = UserIDAndDeviceAccessToken::from(response); Ok(serde_json::to_string(&user_id_and_access_token)?) } diff --git a/native/native_rust_library/src/identity/registration.rs b/native/native_rust_library/src/identity/registration.rs index 41c8d996e..0b4de0e22 100644 --- a/native/native_rust_library/src/identity/registration.rs +++ b/native/native_rust_library/src/identity/registration.rs @@ -1,208 +1,220 @@ use crate::{ utils::jsi_callbacks::handle_string_result_as_callback, Error, CODE_VERSION, DEVICE_TYPE, IDENTITY_SOCKET_ADDR, RUNTIME, }; use comm_opaque2::client::Registration; use grpc_clients::identity::{ get_unauthenticated_client, protos::unauth::{ DeviceKeyUpload, IdentityKeyInfo, Prekey, RegistrationFinishRequest, RegistrationStartRequest, WalletAuthRequest, }, }; use tracing::instrument; use super::{ - farcaster::farcaster_id_string_to_option, PasswordUserInfo, - UserIDAndDeviceAccessToken, WalletUserInfo, + farcaster::farcaster_id_string_to_option, RegisterPasswordUserInfo, + RegisterWalletUserInfo, UserIDAndDeviceAccessToken, }; pub mod ffi { + use crate::identity::{ + DeviceKeys, RegisterPasswordUserInfo, RegisterWalletUserInfo, + }; + use super::*; #[instrument] pub fn register_password_user( username: String, password: String, key_payload: String, key_payload_signature: String, content_prekey: String, content_prekey_signature: String, notif_prekey: String, notif_prekey_signature: String, content_one_time_keys: Vec, notif_one_time_keys: Vec, farcaster_id: String, initial_device_list: String, promise_id: u32, ) { RUNTIME.spawn(async move { - let password_user_info = PasswordUserInfo { + let password_user_info = RegisterPasswordUserInfo { username, password, - key_payload, - key_payload_signature, - content_prekey, - content_prekey_signature, - notif_prekey, - notif_prekey_signature, - content_one_time_keys, - notif_one_time_keys, + device_keys: DeviceKeys { + key_payload, + key_payload_signature, + content_prekey, + content_prekey_signature, + notif_prekey, + notif_prekey_signature, + content_one_time_keys, + notif_one_time_keys, + }, farcaster_id: farcaster_id_string_to_option(&farcaster_id), + initial_device_list, }; - let result = - register_password_user_helper(password_user_info, initial_device_list) - .await; + let result = register_password_user_helper(password_user_info).await; handle_string_result_as_callback(result, promise_id); }); } #[instrument] pub fn register_wallet_user( siwe_message: String, siwe_signature: String, key_payload: String, key_payload_signature: String, content_prekey: String, content_prekey_signature: String, notif_prekey: String, notif_prekey_signature: String, content_one_time_keys: Vec, notif_one_time_keys: Vec, farcaster_id: String, initial_device_list: String, promise_id: u32, ) { RUNTIME.spawn(async move { - let wallet_user_info = WalletUserInfo { + let wallet_user_info = RegisterWalletUserInfo { siwe_message, siwe_signature, - key_payload, - key_payload_signature, - content_prekey, - content_prekey_signature, - notif_prekey, - notif_prekey_signature, - content_one_time_keys, - notif_one_time_keys, + device_keys: DeviceKeys { + key_payload, + key_payload_signature, + content_prekey, + content_prekey_signature, + notif_prekey, + notif_prekey_signature, + content_one_time_keys, + notif_one_time_keys, + }, farcaster_id: farcaster_id_string_to_option(&farcaster_id), + initial_device_list, }; - let result = - register_wallet_user_helper(wallet_user_info, initial_device_list) - .await; + let result = register_wallet_user_helper(wallet_user_info).await; handle_string_result_as_callback(result, promise_id); }); } } async fn register_password_user_helper( - password_user_info: PasswordUserInfo, - initial_device_list: String, + password_user_info: RegisterPasswordUserInfo, ) -> Result { let mut client_registration = Registration::new(); let opaque_registration_request = client_registration .start(&password_user_info.password) .map_err(crate::handle_error)?; let registration_start_request = RegistrationStartRequest { opaque_registration_request, username: password_user_info.username, device_key_upload: Some(DeviceKeyUpload { device_key_info: Some(IdentityKeyInfo { - payload: password_user_info.key_payload, - payload_signature: password_user_info.key_payload_signature, + payload: password_user_info.device_keys.key_payload, + payload_signature: password_user_info.device_keys.key_payload_signature, }), content_upload: Some(Prekey { - prekey: password_user_info.content_prekey, - prekey_signature: password_user_info.content_prekey_signature, + prekey: password_user_info.device_keys.content_prekey, + prekey_signature: password_user_info + .device_keys + .content_prekey_signature, }), notif_upload: Some(Prekey { - prekey: password_user_info.notif_prekey, - prekey_signature: password_user_info.notif_prekey_signature, + prekey: password_user_info.device_keys.notif_prekey, + prekey_signature: password_user_info.device_keys.notif_prekey_signature, }), - one_time_content_prekeys: password_user_info.content_one_time_keys, - one_time_notif_prekeys: password_user_info.notif_one_time_keys, + one_time_content_prekeys: password_user_info + .device_keys + .content_one_time_keys, + one_time_notif_prekeys: password_user_info + .device_keys + .notif_one_time_keys, device_type: DEVICE_TYPE.into(), }), farcaster_id: password_user_info.farcaster_id, - initial_device_list, + initial_device_list: password_user_info.initial_device_list, }; let mut identity_client = get_unauthenticated_client( IDENTITY_SOCKET_ADDR, CODE_VERSION, DEVICE_TYPE.as_str_name().to_lowercase(), ) .await?; let response = identity_client .register_password_user_start(registration_start_request) .await?; let registration_start_response = response.into_inner(); let opaque_registration_upload = client_registration .finish( &password_user_info.password, ®istration_start_response.opaque_registration_response, ) .map_err(crate::handle_error)?; let registration_finish_request = RegistrationFinishRequest { session_id: registration_start_response.session_id, opaque_registration_upload, }; let registration_finish_response = identity_client .register_password_user_finish(registration_finish_request) .await? .into_inner(); let user_id_and_access_token = UserIDAndDeviceAccessToken::from(registration_finish_response); Ok(serde_json::to_string(&user_id_and_access_token)?) } async fn register_wallet_user_helper( - wallet_user_info: WalletUserInfo, - initial_device_list: String, + wallet_user_info: RegisterWalletUserInfo, ) -> Result { let registration_request = WalletAuthRequest { siwe_message: wallet_user_info.siwe_message, siwe_signature: wallet_user_info.siwe_signature, device_key_upload: Some(DeviceKeyUpload { device_key_info: Some(IdentityKeyInfo { - payload: wallet_user_info.key_payload, - payload_signature: wallet_user_info.key_payload_signature, + payload: wallet_user_info.device_keys.key_payload, + payload_signature: wallet_user_info.device_keys.key_payload_signature, }), content_upload: Some(Prekey { - prekey: wallet_user_info.content_prekey, - prekey_signature: wallet_user_info.content_prekey_signature, + prekey: wallet_user_info.device_keys.content_prekey, + prekey_signature: wallet_user_info.device_keys.content_prekey_signature, }), notif_upload: Some(Prekey { - prekey: wallet_user_info.notif_prekey, - prekey_signature: wallet_user_info.notif_prekey_signature, + prekey: wallet_user_info.device_keys.notif_prekey, + prekey_signature: wallet_user_info.device_keys.notif_prekey_signature, }), - one_time_content_prekeys: wallet_user_info.content_one_time_keys, - one_time_notif_prekeys: wallet_user_info.notif_one_time_keys, + one_time_content_prekeys: wallet_user_info + .device_keys + .content_one_time_keys, + one_time_notif_prekeys: wallet_user_info.device_keys.notif_one_time_keys, device_type: DEVICE_TYPE.into(), }), farcaster_id: wallet_user_info.farcaster_id, - initial_device_list, + initial_device_list: wallet_user_info.initial_device_list, }; let mut identity_client = get_unauthenticated_client( IDENTITY_SOCKET_ADDR, CODE_VERSION, DEVICE_TYPE.as_str_name().to_lowercase(), ) .await?; let registration_response = identity_client .register_wallet_user(registration_request) .await? .into_inner(); let user_id_and_access_token = UserIDAndDeviceAccessToken { user_id: registration_response.user_id, access_token: registration_response.access_token, }; Ok(serde_json::to_string(&user_id_and_access_token)?) }