diff --git a/keyserver/addons/rust-node-addon/src/identity_client/add_reserved_usernames.rs b/keyserver/addons/rust-node-addon/src/identity_client/add_reserved_usernames.rs index 341246c18..320409a58 100644 --- a/keyserver/addons/rust-node-addon/src/identity_client/add_reserved_usernames.rs +++ b/keyserver/addons/rust-node-addon/src/identity_client/add_reserved_usernames.rs @@ -1,22 +1,22 @@ use super::*; #[napi] #[instrument(skip_all)] pub async fn add_reserved_usernames( message: String, signature: String, ) -> Result<()> { // Set up the gRPC client that will be used to talk to the Identity service - let mut identity_client = get_identity_client_service_channel().await?; + let mut identity_client = get_identity_client().await?; let add_reserved_usernames_request = AddReservedUsernamesRequest { message, signature }; identity_client .add_reserved_usernames(add_reserved_usernames_request) .await .map_err(|e| Error::new(Status::GenericFailure, e.to_string()))? .into_inner(); Ok(()) } diff --git a/keyserver/addons/rust-node-addon/src/identity_client/get_inbound_keys_for_user.rs b/keyserver/addons/rust-node-addon/src/identity_client/get_inbound_keys_for_user.rs index 071bc9c34..f30973fc3 100644 --- a/keyserver/addons/rust-node-addon/src/identity_client/get_inbound_keys_for_user.rs +++ b/keyserver/addons/rust-node-addon/src/identity_client/get_inbound_keys_for_user.rs @@ -1,36 +1,39 @@ +use grpc_clients::identity::protos::client::{ + inbound_keys_for_user_request::Identifier, InboundKeysForUserRequest, +}; + use super::*; #[napi] #[instrument(skip_all)] pub async fn get_inbound_keys_for_user_device( identifier_type: String, identifier_value: String, device_id: String, ) -> Result { // Set up the gRPC client that will be used to talk to the Identity service - let channel = get_identity_service_channel().await?; - let mut identity_client = IdentityClientServiceClient::new(channel); + let mut identity_client = get_identity_client().await?; let identifier = match identifier_type.as_str() { "walletAddress" => Some(Identifier::WalletAddress(identifier_value)), "username" => Some(Identifier::Username(identifier_value)), _ => return Err(Error::from_status(Status::GenericFailure)), }; let inbound_keys_for_user_request = InboundKeysForUserRequest { identifier }; let mut response = identity_client .get_inbound_keys_for_user(inbound_keys_for_user_request) .await .map_err(|e| Error::new(Status::GenericFailure, e.to_string()))? .into_inner(); let inbound_key_info = InboundKeyInfoResponse::try_from( response .devices .remove(&device_id) .ok_or(Error::from_status(Status::GenericFailure))?, )?; Ok(inbound_key_info) } diff --git a/keyserver/addons/rust-node-addon/src/identity_client/login.rs b/keyserver/addons/rust-node-addon/src/identity_client/login.rs index 0a057f52b..f36b53f3b 100644 --- a/keyserver/addons/rust-node-addon/src/identity_client/login.rs +++ b/keyserver/addons/rust-node-addon/src/identity_client/login.rs @@ -1,86 +1,86 @@ use super::*; use comm_opaque2::client::Login; use grpc_clients::identity::protos::unauthenticated::{ OpaqueLoginFinishRequest, OpaqueLoginStartRequest, }; use tracing::debug; #[napi] #[instrument(skip_all)] pub async fn login_user( username: String, password: String, signed_identity_keys_blob: SignedIdentityKeysBlob, content_prekey: String, content_prekey_signature: String, notif_prekey: String, notif_prekey_signature: String, content_one_time_keys: Vec, notif_one_time_keys: Vec, ) -> Result { debug!("Attempting to login user: {}", username); // Set up the gRPC client that will be used to talk to the Identity service - let mut identity_client = get_identity_client_service_channel().await?; + let mut identity_client = get_identity_client().await?; // Start OPAQUE registration and send initial registration request let mut client_login = Login::new(); let opaque_login_request = client_login .start(&password) .map_err(|_| Error::from_reason("Failed to create opaque login request"))?; let login_start_request = OpaqueLoginStartRequest { opaque_login_request, username, device_key_upload: Some(DeviceKeyUpload { device_key_info: Some(IdentityKeyInfo { payload: signed_identity_keys_blob.payload, payload_signature: signed_identity_keys_blob.signature, social_proof: None, }), content_upload: Some(PreKey { pre_key: content_prekey, pre_key_signature: content_prekey_signature, }), notif_upload: Some(PreKey { pre_key: notif_prekey, pre_key_signature: notif_prekey_signature, }), one_time_content_prekeys: content_one_time_keys, one_time_notif_prekeys: notif_one_time_keys, device_type: DeviceType::Keyserver.into(), }), }; debug!("Starting login to identity service"); let login_start_response = identity_client .login_password_user_start(login_start_request) .await .map_err(handle_grpc_error)? .into_inner(); debug!("Received login response from identity service"); let opaque_login_upload = client_login .finish(&login_start_response.opaque_login_response) .map_err(|_| Error::from_reason("Failed to finish opaque login request"))?; let login_finish_request = OpaqueLoginFinishRequest { session_id: login_start_response.session_id, opaque_login_upload, }; debug!("Attempting to finalize opaque login exchange with identity service"); let login_finish_response = identity_client .login_password_user_finish(login_finish_request) .await .map_err(handle_grpc_error)? .into_inner(); debug!("Finished login with identity service"); let user_info = UserLoginInfo { user_id: login_finish_response.user_id, access_token: login_finish_response.access_token, }; Ok(user_info) } diff --git a/keyserver/addons/rust-node-addon/src/identity_client/mod.rs b/keyserver/addons/rust-node-addon/src/identity_client/mod.rs index 93ba28924..7a0a652a7 100644 --- a/keyserver/addons/rust-node-addon/src/identity_client/mod.rs +++ b/keyserver/addons/rust-node-addon/src/identity_client/mod.rs @@ -1,192 +1,193 @@ pub mod add_reserved_usernames; +pub mod get_inbound_keys_for_user; pub mod login; pub mod prekey; pub mod register_user; pub mod remove_reserved_usernames; pub mod upload_one_time_keys; use client_proto::identity_client_service_client::IdentityClientServiceClient; use client_proto::{ AddReservedUsernamesRequest, DeviceKeyUpload, DeviceType, IdentityKeyInfo, InboundKeyInfo, PreKey, RegistrationFinishRequest, RegistrationStartRequest, RemoveReservedUsernameRequest, UploadOneTimeKeysRequest, }; use grpc_clients::identity::authenticated::ChainedInterceptedAuthClient; use grpc_clients::identity::protos::unauthenticated as client_proto; use grpc_clients::identity::shared::CodeVersionLayer; use lazy_static::lazy_static; use napi::bindgen_prelude::*; use serde::{Deserialize, Serialize}; use std::env::var; use tonic::codegen::InterceptedService; use tonic::{transport::Channel, Request}; use tracing::{self, info, instrument, warn, Level}; use tracing_subscriber::EnvFilter; mod generated { // We get the CODE_VERSION from this generated file include!(concat!(env!("OUT_DIR"), "/version.rs")); } pub use generated::CODE_VERSION; pub const DEVICE_TYPE: &str = "keyserver"; lazy_static! { static ref IDENTITY_SERVICE_CONFIG: IdentityServiceConfig = { let filter = EnvFilter::builder() .with_default_directive(Level::INFO.into()) .with_env_var(EnvFilter::DEFAULT_ENV) .from_env_lossy(); let subscriber = tracing_subscriber::fmt().with_env_filter(filter).finish(); tracing::subscriber::set_global_default(subscriber) .expect("Unable to configure tracing"); let config_json_string = var("COMM_JSONCONFIG_secrets_identity_service_config"); match config_json_string { Ok(json) => serde_json::from_str(&json).unwrap(), Err(_) => IdentityServiceConfig::default(), } }; } #[derive(Serialize, Deserialize)] #[serde(rename_all = "camelCase")] struct IdentityServiceConfig { identity_socket_addr: String, } impl Default for IdentityServiceConfig { fn default() -> Self { info!("Using default identity configuration"); Self { identity_socket_addr: "http://[::1]:50054".to_string(), } } } -async fn get_identity_client_service_channel() -> Result< +async fn get_identity_client() -> Result< IdentityClientServiceClient>, > { info!("Connecting to identity service"); grpc_clients::identity::get_unauthenticated_client( &IDENTITY_SERVICE_CONFIG.identity_socket_addr, CODE_VERSION, DEVICE_TYPE.to_string(), ) .await .map_err(|_| { Error::new( Status::GenericFailure, "Unable to connect to identity service".to_string(), ) }) } -async fn get_identity_authenticated_service_channel( +async fn get_authenticated_identity_client( user_id: String, device_id: String, access_token: String, ) -> Result { info!("Connecting to identity service"); grpc_clients::identity::get_auth_client( &IDENTITY_SERVICE_CONFIG.identity_socket_addr, user_id, device_id, access_token, CODE_VERSION, DEVICE_TYPE.to_string(), ) .await .map_err(|_| { Error::new( Status::GenericFailure, "Unable to connect to identity service".to_string(), ) }) } #[napi(object)] pub struct SignedIdentityKeysBlob { pub payload: String, pub signature: String, } #[napi(object)] pub struct UserLoginInfo { pub user_id: String, pub access_token: String, } #[napi(object)] pub struct InboundKeyInfoResponse { pub payload: String, pub payload_signature: String, pub social_proof: Option, pub content_prekey: String, pub content_prekey_signature: String, pub notif_prekey: String, pub notif_prekey_signature: String, } impl TryFrom for InboundKeyInfoResponse { type Error = Error; fn try_from(key_info: InboundKeyInfo) -> Result { let identity_info = key_info .identity_info .ok_or(Error::from_status(Status::GenericFailure))?; let IdentityKeyInfo { payload, payload_signature, social_proof, } = identity_info; let content_prekey = key_info .content_prekey .ok_or(Error::from_status(Status::GenericFailure))?; let PreKey { pre_key: content_prekey_value, pre_key_signature: content_prekey_signature, } = content_prekey; let notif_prekey = key_info .notif_prekey .ok_or(Error::from_status(Status::GenericFailure))?; let PreKey { pre_key: notif_prekey_value, pre_key_signature: notif_prekey_signature, } = notif_prekey; Ok(Self { payload, payload_signature, social_proof, content_prekey: content_prekey_value, content_prekey_signature, notif_prekey: notif_prekey_value, notif_prekey_signature, }) } } pub fn handle_grpc_error(error: tonic::Status) -> napi::Error { warn!("Received error: {}", error.message()); Error::new(Status::GenericFailure, error.message()) } #[cfg(test)] mod tests { use super::CODE_VERSION; #[test] fn test_code_version_exists() { assert!(CODE_VERSION > 0); } } diff --git a/keyserver/addons/rust-node-addon/src/identity_client/prekey.rs b/keyserver/addons/rust-node-addon/src/identity_client/prekey.rs index 0cf1d01a6..341acc1b2 100644 --- a/keyserver/addons/rust-node-addon/src/identity_client/prekey.rs +++ b/keyserver/addons/rust-node-addon/src/identity_client/prekey.rs @@ -1,48 +1,44 @@ -use super::get_identity_authenticated_service_channel; +use super::get_authenticated_identity_client; use super::{Error, Status}; use grpc_clients::identity::protos::{ authenticated::RefreshUserPreKeysRequest, unauthenticated::PreKey, }; use napi::Result; use tracing::warn; #[napi] pub async fn publish_prekeys( user_id: String, device_id: String, access_token: String, content_prekey: String, content_prekey_signature: String, notif_prekey: String, notif_prekey_signature: String, ) -> Result { // Once this rust addon can do getCommConfig, remove explicit passing of user // credentials within this scope - let mut client = get_identity_authenticated_service_channel( - user_id, - device_id, - access_token, - ) - .await?; + let mut client = + get_authenticated_identity_client(user_id, device_id, access_token).await?; let message = RefreshUserPreKeysRequest { new_content_pre_keys: Some(PreKey { pre_key: content_prekey, pre_key_signature: content_prekey_signature, }), new_notif_pre_keys: Some(PreKey { pre_key: notif_prekey, pre_key_signature: notif_prekey_signature, }), }; client.refresh_user_pre_keys(message).await.map_err(|e| { warn!( "Failed to upload new prekeys to identity service: {:?}", e.message() ); Error::from_status(Status::GenericFailure) })?; Ok(true) } diff --git a/keyserver/addons/rust-node-addon/src/identity_client/register_user.rs b/keyserver/addons/rust-node-addon/src/identity_client/register_user.rs index bfb74772d..638c9f1be 100644 --- a/keyserver/addons/rust-node-addon/src/identity_client/register_user.rs +++ b/keyserver/addons/rust-node-addon/src/identity_client/register_user.rs @@ -1,84 +1,84 @@ use super::*; use tracing::{debug, warn}; #[napi] #[instrument(skip_all)] pub async fn register_user( username: String, password: String, signed_identity_keys_blob: SignedIdentityKeysBlob, content_prekey: String, content_prekey_signature: String, notif_prekey: String, notif_prekey_signature: String, content_one_time_keys: Vec, notif_one_time_keys: Vec, ) -> Result { debug!("Attempting to register user: {}", username); // Set up the gRPC client that will be used to talk to the Identity service - let mut identity_client = get_identity_client_service_channel().await?; + let mut identity_client = get_identity_client().await?; // Start OPAQUE registration and send initial registration request let mut opaque_registration = comm_opaque2::client::Registration::new(); let opaque_registration_request = opaque_registration .start(&password) .map_err(|_| Error::from_status(Status::GenericFailure))?; let device_key_upload = DeviceKeyUpload { device_key_info: Some(IdentityKeyInfo { payload: signed_identity_keys_blob.payload, payload_signature: signed_identity_keys_blob.signature, social_proof: None, }), content_upload: Some(PreKey { pre_key: content_prekey, pre_key_signature: content_prekey_signature, }), notif_upload: Some(PreKey { pre_key: notif_prekey, pre_key_signature: notif_prekey_signature, }), one_time_content_prekeys: content_one_time_keys, one_time_notif_prekeys: notif_one_time_keys, device_type: DeviceType::Keyserver.into(), }; let registration_start_request = Request::new(RegistrationStartRequest { opaque_registration_request, username, device_key_upload: Some(device_key_upload), }); // Finish OPAQUE registration and send final registration request let registration_start_response = identity_client .register_password_user_start(registration_start_request) .await .map_err(handle_grpc_error)? .into_inner(); debug!("Received registration start response"); let opaque_registration_upload = opaque_registration .finish( &password, ®istration_start_response.opaque_registration_response, ) .map_err(|_| Error::from_status(Status::GenericFailure))?; let registration_finish_request = Request::new(RegistrationFinishRequest { session_id: registration_start_response.session_id, opaque_registration_upload, }); let registration_response = identity_client .register_password_user_finish(registration_finish_request) .await .map_err(handle_grpc_error)? .into_inner(); let user_info = UserLoginInfo { user_id: registration_response.user_id, access_token: registration_response.access_token, }; Ok(user_info) } diff --git a/keyserver/addons/rust-node-addon/src/identity_client/remove_reserved_usernames.rs b/keyserver/addons/rust-node-addon/src/identity_client/remove_reserved_usernames.rs index 133de60f3..08b3c10c6 100644 --- a/keyserver/addons/rust-node-addon/src/identity_client/remove_reserved_usernames.rs +++ b/keyserver/addons/rust-node-addon/src/identity_client/remove_reserved_usernames.rs @@ -1,22 +1,22 @@ use super::*; #[napi] #[instrument(skip_all)] pub async fn remove_reserved_username( message: String, signature: String, ) -> Result<()> { // Set up the gRPC client that will be used to talk to the Identity service - let mut identity_client = get_identity_client_service_channel().await?; + let mut identity_client = get_identity_client().await?; let remove_reserved_username_request = RemoveReservedUsernameRequest { message, signature }; identity_client .remove_reserved_username(remove_reserved_username_request) .await .map_err(|e| Error::new(Status::GenericFailure, e.to_string()))? .into_inner(); Ok(()) } diff --git a/keyserver/addons/rust-node-addon/src/identity_client/upload_one_time_keys.rs b/keyserver/addons/rust-node-addon/src/identity_client/upload_one_time_keys.rs index 23f7b8d68..863a5ac33 100644 --- a/keyserver/addons/rust-node-addon/src/identity_client/upload_one_time_keys.rs +++ b/keyserver/addons/rust-node-addon/src/identity_client/upload_one_time_keys.rs @@ -1,32 +1,32 @@ use super::*; use tracing::debug; #[napi] #[instrument(skip_all)] pub async fn upload_one_time_keys( user_id: String, device_id: String, access_token: String, content_one_time_pre_keys: Vec, notif_one_time_pre_keys: Vec, ) -> Result { // Set up the gRPC client that will be used to talk to the Identity service - let mut identity_client = get_identity_client_service_channel().await?; + let mut identity_client = get_identity_client().await?; let upload_request = UploadOneTimeKeysRequest { user_id, device_id, access_token, content_one_time_pre_keys, notif_one_time_pre_keys, }; debug!("Sending one time keys to Identity service"); identity_client .upload_one_time_keys(upload_request) .await .map_err(handle_grpc_error)?; Ok(true) }