Changeset View
Changeset View
Standalone View
Standalone View
services/identity/src/client_service.rs
pub mod client_proto { | pub mod client_proto { | ||||
tonic::include_proto!("identity.client"); | tonic::include_proto!("identity.client"); | ||||
} | } | ||||
use std::str::FromStr; | use std::str::FromStr; | ||||
use crate::{ | use crate::{ | ||||
client_service::client_proto::{ | client_service::client_proto::{ | ||||
DeleteUserRequest, Empty, GenerateNonceResponse, KeyserverKeysRequest, | DeleteUserRequest, Empty, GenerateNonceResponse, KeyserverKeysRequest, | ||||
KeyserverKeysResponse, OpaqueLoginFinishRequest, OpaqueLoginFinishResponse, | KeyserverKeysResponse, OpaqueLoginFinishRequest, OpaqueLoginFinishResponse, | ||||
OpaqueLoginStartRequest, OpaqueLoginStartResponse, | OpaqueLoginStartRequest, OpaqueLoginStartResponse, | ||||
ReceiverKeysForUserRequest, ReceiverKeysForUserResponse, | ReceiverKeysForUserRequest, ReceiverKeysForUserResponse, | ||||
RefreshUserPreKeysRequest, RegistrationFinishRequest, | RefreshUserPreKeysRequest, RegistrationFinishRequest, | ||||
RegistrationFinishResponse, RegistrationStartRequest, | RegistrationFinishResponse, RegistrationStartRequest, | ||||
RegistrationStartResponse, SenderKeysForUserRequest, | RegistrationStartResponse, SenderKeysForUserRequest, | ||||
SenderKeysForUserResponse, UpdateUserPasswordFinishRequest, | SenderKeysForUserResponse, UpdateUserPasswordFinishRequest, | ||||
UpdateUserPasswordFinishResponse, UpdateUserPasswordStartRequest, | UpdateUserPasswordStartRequest, UpdateUserPasswordStartResponse, | ||||
UpdateUserPasswordStartResponse, UploadOneTimeKeysRequest, | UploadOneTimeKeysRequest, VerifyUserAccessTokenRequest, | ||||
VerifyUserAccessTokenRequest, VerifyUserAccessTokenResponse, | VerifyUserAccessTokenResponse, WalletLoginRequest, WalletLoginResponse, | ||||
WalletLoginRequest, WalletLoginResponse, | |||||
}, | }, | ||||
config::CONFIG, | config::CONFIG, | ||||
database::{DatabaseClient, Error as DBError, KeyPayload}, | database::{DatabaseClient, Error as DBError, KeyPayload}, | ||||
id::generate_uuid, | id::generate_uuid, | ||||
nonce::generate_nonce_data, | nonce::generate_nonce_data, | ||||
siwe::parse_and_verify_siwe_message, | siwe::parse_and_verify_siwe_message, | ||||
token::{AccessTokenData, AuthType}, | token::{AccessTokenData, AuthType}, | ||||
}; | }; | ||||
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 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(UserRegistrationInfo), | Registration(UserRegistrationInfo), | ||||
Login(UserLoginInfo), | Login(UserLoginInfo), | ||||
Update(UpdateState), | |||||
} | } | ||||
#[derive(Clone)] | #[derive(Clone)] | ||||
pub struct UserRegistrationInfo { | pub struct UserRegistrationInfo { | ||||
pub username: String, | pub username: String, | ||||
pub flattened_device_key_upload: FlattenedDeviceKeyUpload, | pub flattened_device_key_upload: FlattenedDeviceKeyUpload, | ||||
} | } | ||||
#[derive(Clone)] | #[derive(Clone)] | ||||
pub struct UserLoginInfo { | pub struct UserLoginInfo { | ||||
pub user_id: String, | pub user_id: String, | ||||
pub flattened_device_key_upload: FlattenedDeviceKeyUpload, | pub flattened_device_key_upload: FlattenedDeviceKeyUpload, | ||||
pub opaque_server_login: comm_opaque2::server::Login, | pub opaque_server_login: comm_opaque2::server::Login, | ||||
} | } | ||||
#[derive(Clone)] | #[derive(Clone)] | ||||
pub struct UpdateState { | |||||
pub user_id: String, | |||||
} | |||||
#[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, | ||||
pub identity_onetime_keys: Vec<String>, | pub identity_onetime_keys: Vec<String>, | ||||
pub notif_prekey: String, | pub notif_prekey: String, | ||||
▲ Show 20 Lines • Show All 139 Lines • ▼ Show 20 Lines | if let Some(WorkflowInProgress::Registration(state)) = | ||||
Ok(Response::new(response)) | Ok(Response::new(response)) | ||||
} else { | } else { | ||||
Err(tonic::Status::not_found("session not found")) | Err(tonic::Status::not_found("session not found")) | ||||
} | } | ||||
} | } | ||||
async fn update_user_password_start( | async fn update_user_password_start( | ||||
&self, | &self, | ||||
_request: tonic::Request<UpdateUserPasswordStartRequest>, | request: tonic::Request<UpdateUserPasswordStartRequest>, | ||||
) -> Result<tonic::Response<UpdateUserPasswordStartResponse>, tonic::Status> | ) -> Result<tonic::Response<UpdateUserPasswordStartResponse>, tonic::Status> | ||||
{ | { | ||||
unimplemented!(); | let message = request.into_inner(); | ||||
let access_token = self | |||||
.client | |||||
.get_access_token_data(message.user_id.clone(), message.device_id_key) | |||||
.await | |||||
.map_err(handle_db_error)?; | |||||
if let Some(token) = access_token { | |||||
if !token.is_valid() || token.access_token != message.access_token { | |||||
return Err(tonic::Status::permission_denied("bad token")); | |||||
} | |||||
let server_registration = comm_opaque2::server::Registration::new(); | |||||
let server_message = server_registration | |||||
.start( | |||||
&CONFIG.server_setup, | |||||
&message.opaque_registration_request, | |||||
message.user_id.as_bytes(), | |||||
) | |||||
.map_err(protocol_error_to_grpc_status)?; | |||||
let update_state = UpdateState { | |||||
user_id: message.user_id, | |||||
}; | |||||
let session_id = generate_uuid(); | |||||
self | |||||
.cache | |||||
.insert(session_id.clone(), WorkflowInProgress::Update(update_state)) | |||||
.await; | |||||
let response = UpdateUserPasswordStartResponse { | |||||
session_id, | |||||
opaque_registration_response: server_message, | |||||
}; | |||||
Ok(Response::new(response)) | |||||
} else { | |||||
Err(tonic::Status::permission_denied("bad token")) | |||||
} | |||||
} | } | ||||
async fn update_user_password_finish( | async fn update_user_password_finish( | ||||
&self, | &self, | ||||
_request: tonic::Request<UpdateUserPasswordFinishRequest>, | request: tonic::Request<UpdateUserPasswordFinishRequest>, | ||||
) -> Result<tonic::Response<UpdateUserPasswordFinishResponse>, tonic::Status> | ) -> Result<tonic::Response<Empty>, tonic::Status> { | ||||
let message = request.into_inner(); | |||||
if let Some(WorkflowInProgress::Update(state)) = | |||||
self.cache.get(&message.session_id) | |||||
{ | { | ||||
unimplemented!(); | self.cache.invalidate(&message.session_id).await; | ||||
let server_registration = comm_opaque2::server::Registration::new(); | |||||
let password_file = server_registration | |||||
.finish(&message.opaque_registration_upload) | |||||
.map_err(protocol_error_to_grpc_status)?; | |||||
self | |||||
.client | |||||
.update_user_password(state.user_id, password_file) | |||||
.await | |||||
.map_err(handle_db_error)?; | |||||
let response = Empty {}; | |||||
Ok(Response::new(response)) | |||||
} else { | |||||
Err(tonic::Status::not_found("session not found")) | |||||
} | |||||
} | } | ||||
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> { | ||||
let message = request.into_inner(); | let message = request.into_inner(); | ||||
▲ Show 20 Lines • Show All 227 Lines • ▼ Show 20 Lines | ) -> Result<tonic::Response<WalletLoginResponse>, tonic::Status> { | ||||
self | self | ||||
.client | .client | ||||
.put_access_token_data(token) | .put_access_token_data(token) | ||||
.await | .await | ||||
.map_err(handle_db_error)?; | .map_err(handle_db_error)?; | ||||
let response = WalletLoginResponse { | let response = WalletLoginResponse { | ||||
user_id: user_id, | user_id, | ||||
access_token, | access_token, | ||||
}; | }; | ||||
Ok(Response::new(response)) | Ok(Response::new(response)) | ||||
} | } | ||||
async fn delete_user( | async fn delete_user( | ||||
&self, | &self, | ||||
request: tonic::Request<DeleteUserRequest>, | request: tonic::Request<DeleteUserRequest>, | ||||
▲ Show 20 Lines • Show All 103 Lines • Show Last 20 Lines |