Changeset View
Changeset View
Standalone View
Standalone View
services/identity/src/client_service.rs
Show All 23 Lines | use crate::{ | ||||
nonce::generate_nonce_data, | nonce::generate_nonce_data, | ||||
token::AccessTokenData, | token::AccessTokenData, | ||||
utils::{generate_uuid, username_reserved}, | utils::{generate_uuid, username_reserved}, | ||||
}; | }; | ||||
use aws_sdk_dynamodb::Error as DynamoDBError; | use aws_sdk_dynamodb::Error as DynamoDBError; | ||||
pub use client_proto::identity_client_service_server::{ | pub use client_proto::identity_client_service_server::{ | ||||
IdentityClientService, IdentityClientServiceServer, | IdentityClientService, IdentityClientServiceServer, | ||||
}; | }; | ||||
use comm_opaque2::grpc::protocol_error_to_grpc_status; | |||||
use moka::future::Cache; | use moka::future::Cache; | ||||
use rand::rngs::OsRng; | use rand::rngs::OsRng; | ||||
use tonic::Response; | use tonic::Response; | ||||
use tracing::error; | use tracing::error; | ||||
#[derive(Clone)] | #[derive(Clone)] | ||||
pub enum WorkflowInProgress { | pub enum WorkflowInProgress { | ||||
Registration(RegistrationState), | Registration(RegistrationState), | ||||
Login(LoginState), | Login(LoginState), | ||||
} | } | ||||
#[derive(Clone)] | #[derive(Clone)] | ||||
pub struct RegistrationState { | pub struct RegistrationState { | ||||
pub username: String, | pub username: String, | ||||
pub flattened_device_key_upload: FlattenedDeviceKeyUpload, | pub flattened_device_key_upload: FlattenedDeviceKeyUpload, | ||||
} | } | ||||
#[derive(Clone)] | #[derive(Clone)] | ||||
pub struct LoginState(FlattenedDeviceKeyUpload); | pub struct LoginState { | ||||
pub flattened_device_key_upload: FlattenedDeviceKeyUpload, | |||||
pub opaque_server_login: comm_opaque2::server::Login, | |||||
} | |||||
#[derive(Clone)] | #[derive(Clone)] | ||||
pub struct FlattenedDeviceKeyUpload { | pub struct FlattenedDeviceKeyUpload { | ||||
pub device_id_key: String, | pub device_id_key: String, | ||||
pub key_payload: String, | pub key_payload: String, | ||||
pub key_payload_signature: String, | pub key_payload_signature: String, | ||||
pub identity_prekey: String, | pub identity_prekey: String, | ||||
pub identity_prekey_signature: String, | pub identity_prekey_signature: String, | ||||
▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | if let client_proto::RegistrationStartRequest { | ||||
onetime_identity_prekeys, | onetime_identity_prekeys, | ||||
onetime_notif_prekeys, | onetime_notif_prekeys, | ||||
}), | }), | ||||
} = message | } = message | ||||
{ | { | ||||
let server_registration = comm_opaque2::server::Registration::new(); | let server_registration = comm_opaque2::server::Registration::new(); | ||||
let server_message = server_registration | let server_message = server_registration | ||||
.start(&CONFIG.server_setup, ®ister_message, username.as_bytes()) | .start(&CONFIG.server_setup, ®ister_message, username.as_bytes()) | ||||
.map_err(comm_opaque2::grpc::protocol_error_to_grpc_status)?; | .map_err(protocol_error_to_grpc_status)?; | ||||
let key_info = KeyPayload::from_str(&payload) | let key_info = KeyPayload::from_str(&payload) | ||||
.map_err(|_| tonic::Status::invalid_argument("malformed payload"))?; | .map_err(|_| tonic::Status::invalid_argument("malformed payload"))?; | ||||
let registration_state = RegistrationState { | let registration_state = RegistrationState { | ||||
username, | username, | ||||
flattened_device_key_upload: FlattenedDeviceKeyUpload { | flattened_device_key_upload: FlattenedDeviceKeyUpload { | ||||
device_id_key: key_info.primary_identity_public_keys.curve25519, | device_id_key: key_info.primary_identity_public_keys.curve25519, | ||||
key_payload: payload, | key_payload: payload, | ||||
key_payload_signature: payload_signature, | key_payload_signature: payload_signature, | ||||
Show All 33 Lines | ) -> Result<tonic::Response<RegistrationFinishResponse>, tonic::Status> { | ||||
if let Some(WorkflowInProgress::Registration(state)) = | if let Some(WorkflowInProgress::Registration(state)) = | ||||
self.cache.get(&message.session_id) | self.cache.get(&message.session_id) | ||||
{ | { | ||||
self.cache.invalidate(&message.session_id).await; | self.cache.invalidate(&message.session_id).await; | ||||
let server_registration = comm_opaque2::server::Registration::new(); | let server_registration = comm_opaque2::server::Registration::new(); | ||||
let password_file = server_registration | let password_file = server_registration | ||||
.finish(&message.opaque_registration_upload) | .finish(&message.opaque_registration_upload) | ||||
.map_err(comm_opaque2::grpc::protocol_error_to_grpc_status)?; | .map_err(protocol_error_to_grpc_status)?; | ||||
let device_id = state.flattened_device_key_upload.device_id_key.clone(); | let device_id = state.flattened_device_key_upload.device_id_key.clone(); | ||||
let user_id = self | let user_id = self | ||||
.client | .client | ||||
.add_user_to_users_table(state, password_file) | .add_user_to_users_table(state, password_file) | ||||
.await | .await | ||||
.map_err(handle_db_error)?; | .map_err(handle_db_error)?; | ||||
Show All 36 Lines | async fn update_user_password_finish( | ||||
_request: tonic::Request<UpdateUserPasswordFinishRequest>, | _request: tonic::Request<UpdateUserPasswordFinishRequest>, | ||||
) -> Result<tonic::Response<UpdateUserPasswordFinishResponse>, tonic::Status> | ) -> Result<tonic::Response<UpdateUserPasswordFinishResponse>, tonic::Status> | ||||
{ | { | ||||
unimplemented!(); | unimplemented!(); | ||||
} | } | ||||
async fn login_password_user_start( | async fn login_password_user_start( | ||||
&self, | &self, | ||||
_request: tonic::Request<OpaqueLoginStartRequest>, | request: tonic::Request<OpaqueLoginStartRequest>, | ||||
) -> Result<tonic::Response<OpaqueLoginStartResponse>, tonic::Status> { | ) -> Result<tonic::Response<OpaqueLoginStartResponse>, tonic::Status> { | ||||
unimplemented!(); | let message = request.into_inner(); | ||||
let password_file_bytes = if let Some(bytes) = self | |||||
.client | |||||
.get_password_file_from_username(&message.username) | |||||
.await | |||||
.map_err(handle_db_error)? | |||||
{ | |||||
bytes | |||||
} else { | |||||
return Err(tonic::Status::not_found("user not found")); | |||||
}; | |||||
jon: I think this should work, not a fan of a nested if let | |||||
if let client_proto::OpaqueLoginStartRequest { | |||||
opaque_login_request: login_message, | |||||
username, | |||||
device_key_upload: | |||||
Some(client_proto::DeviceKeyUpload { | |||||
device_key_info: | |||||
Some(client_proto::IdentityKeyInfo { | |||||
payload, | |||||
payload_signature, | |||||
social_proof: _social_proof, | |||||
}), | |||||
identity_upload: | |||||
Some(client_proto::PreKey { | |||||
pre_key: identity_prekey, | |||||
pre_key_signature: identity_prekey_signature, | |||||
}), | |||||
notif_upload: | |||||
Some(client_proto::PreKey { | |||||
pre_key: notif_prekey, | |||||
pre_key_signature: notif_prekey_signature, | |||||
}), | |||||
onetime_identity_prekeys, | |||||
onetime_notif_prekeys, | |||||
}), | |||||
} = message | |||||
{ | |||||
let mut server_login = comm_opaque2::server::Login::new(); | |||||
let server_response = server_login | |||||
.start( | |||||
&CONFIG.server_setup, | |||||
&password_file_bytes, | |||||
&login_message, | |||||
username.as_bytes(), | |||||
) | |||||
.map_err(protocol_error_to_grpc_status)?; | |||||
let key_info = KeyPayload::from_str(&payload) | |||||
.map_err(|_| tonic::Status::invalid_argument("malformed payload"))?; | |||||
let login_state = LoginState { | |||||
opaque_server_login: server_login, | |||||
flattened_device_key_upload: FlattenedDeviceKeyUpload { | |||||
device_id_key: key_info.primary_identity_public_keys.curve25519, | |||||
key_payload: payload, | |||||
key_payload_signature: payload_signature, | |||||
identity_prekey, | |||||
identity_prekey_signature, | |||||
identity_onetime_keys: onetime_identity_prekeys, | |||||
notif_prekey, | |||||
notif_prekey_signature, | |||||
notif_onetime_keys: onetime_notif_prekeys, | |||||
}, | |||||
}; | |||||
let session_id = generate_uuid(); | |||||
self | |||||
.cache | |||||
.insert(session_id.clone(), WorkflowInProgress::Login(login_state)) | |||||
.await; | |||||
let response = Response::new(OpaqueLoginStartResponse { | |||||
session_id, | |||||
opaque_login_response: server_response, | |||||
}); | |||||
Ok(response) | |||||
} else { | |||||
Err(tonic::Status::invalid_argument("unexpected message data")) | |||||
} | |||||
} | } | ||||
async fn login_password_user_finish( | async fn login_password_user_finish( | ||||
&self, | &self, | ||||
_request: tonic::Request<OpaqueLoginFinishRequest>, | _request: tonic::Request<OpaqueLoginFinishRequest>, | ||||
) -> Result<tonic::Response<OpaqueLoginFinishResponse>, tonic::Status> { | ) -> Result<tonic::Response<OpaqueLoginFinishResponse>, tonic::Status> { | ||||
unimplemented!(); | unimplemented!(); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 90 Lines • Show Last 20 Lines |
I think this should work, not a fan of a nested if let