diff --git a/services/identity/src/client_service.rs b/services/identity/src/client_service.rs --- a/services/identity/src/client_service.rs +++ b/services/identity/src/client_service.rs @@ -19,13 +19,13 @@ LogoutRequest, OpaqueLoginFinishRequest, OpaqueLoginFinishResponse, OpaqueLoginStartRequest, OpaqueLoginStartResponse, OutboundKeyInfo, OutboundKeysForUserRequest, OutboundKeysForUserResponse, - RefreshUserPreKeysRequest, RegistrationFinishRequest, - RegistrationFinishResponse, RegistrationStartRequest, - RegistrationStartResponse, RemoveReservedUsernameRequest, - ReservedRegistrationStartRequest, UpdateUserPasswordFinishRequest, - UpdateUserPasswordStartRequest, UpdateUserPasswordStartResponse, - UploadOneTimeKeysRequest, VerifyUserAccessTokenRequest, - VerifyUserAccessTokenResponse, WalletLoginRequest, WalletLoginResponse, + RegistrationFinishRequest, RegistrationFinishResponse, + RegistrationStartRequest, RegistrationStartResponse, + RemoveReservedUsernameRequest, ReservedRegistrationStartRequest, + UpdateUserPasswordFinishRequest, UpdateUserPasswordStartRequest, + UpdateUserPasswordStartResponse, UploadOneTimeKeysRequest, + VerifyUserAccessTokenRequest, VerifyUserAccessTokenResponse, + WalletLoginRequest, WalletLoginResponse, }; use crate::config::CONFIG; use crate::database::{DatabaseClient, Device, KeyPayload}; @@ -939,13 +939,6 @@ Ok(tonic::Response::new(Empty {})) } - async fn refresh_user_pre_keys( - &self, - _request: tonic::Request, - ) -> Result, tonic::Status> { - unimplemented!(); - } - async fn verify_user_access_token( &self, request: tonic::Request, @@ -1018,6 +1011,14 @@ let response = Response::new(Empty {}); Ok(response) } + + async fn ping( + &self, + _request: tonic::Request, + ) -> Result, tonic::Status> { + let response = Response::new(Empty {}); + Ok(response) + } } pub fn handle_db_error(db_error: DBError) -> tonic::Status { diff --git a/services/identity/src/grpc_services/authenticated.rs b/services/identity/src/grpc_services/authenticated.rs --- a/services/identity/src/grpc_services/authenticated.rs +++ b/services/identity/src/grpc_services/authenticated.rs @@ -1,4 +1,7 @@ -use crate::{client_service::handle_db_error, database::DatabaseClient}; +use crate::{ + client_service::handle_db_error, database::DatabaseClient, + grpc_services::shared::get_value, +}; use tonic::{Request, Response, Status}; // This must be named client, because generated code from the authenticated @@ -23,11 +26,6 @@ db_client: DatabaseClient, } -fn get_value(req: &Request, key: &str) -> Option { - let raw_value = req.metadata().get(key)?; - raw_value.to_str().ok().map(|s| s.to_string()) -} - fn get_auth_info(req: &Request<()>) -> Option<(String, String, String)> { debug!("Retrieving auth info for request: {:?}", req); @@ -42,7 +40,7 @@ req: Request<()>, db_client: &DatabaseClient, ) -> Result, Status> { - println!("Intercepting request: {:?}", req); + debug!("Intercepting request to check auth info: {:?}", req); let (user_id, device_id, access_token) = get_auth_info(&req) .ok_or_else(|| Status::unauthenticated("Missing credentials"))?; diff --git a/services/identity/src/grpc_services/mod.rs b/services/identity/src/grpc_services/mod.rs --- a/services/identity/src/grpc_services/mod.rs +++ b/services/identity/src/grpc_services/mod.rs @@ -1 +1,2 @@ pub mod authenticated; +pub mod shared; diff --git a/services/identity/src/grpc_services/shared.rs b/services/identity/src/grpc_services/shared.rs new file mode 100644 --- /dev/null +++ b/services/identity/src/grpc_services/shared.rs @@ -0,0 +1,30 @@ +use grpc_clients::error::unsupported_version; +use tonic::{Request, Status}; +use tracing::debug; + +pub fn version_intercept(req: Request<()>) -> Result, Status> { + debug!("Intercepting request to check version: {:?}", req); + + match get_version_info(&req) { + Some((version, platform)) + if (platform == "ios" || platform == "android") && version < 270 => + { + Err(unsupported_version()) + } + _ => Ok(req), + } +} + +fn get_version_info(req: &Request<()>) -> Option<(u64, String)> { + debug!("Retrieving version info for request: {:?}", req); + + let code_version: u64 = get_value(req, "code_version")?.parse().ok()?; + let device_type = get_value(req, "device_type")?; + + Some((code_version, device_type)) +} + +pub fn get_value(req: &Request, key: &str) -> Option { + let raw_value = req.metadata().get(key)?; + raw_value.to_str().ok().map(|s| s.to_string()) +} diff --git a/services/identity/src/grpc_utils.rs b/services/identity/src/grpc_utils.rs --- a/services/identity/src/grpc_utils.rs +++ b/services/identity/src/grpc_utils.rs @@ -33,7 +33,7 @@ let mut device_info = data.device_info; let identity_info = - extract_identity_info(&mut device_info, &data.auth_type)?; + extract_identity_info(&mut device_info, data.auth_type)?; Ok(InboundKeyInfo { identity_info: Some(identity_info), @@ -58,7 +58,7 @@ let mut device_info = data.device_info; let identity_info = - extract_identity_info(&mut device_info, &data.auth_type)?; + extract_identity_info(&mut device_info, data.auth_type)?; let content_one_time_key = device_info.remove(CONTENT_ONE_TIME_KEY); let notif_one_time_key = device_info.remove(NOTIF_ONE_TIME_KEY); diff --git a/services/identity/src/main.rs b/services/identity/src/main.rs --- a/services/identity/src/main.rs +++ b/services/identity/src/main.rs @@ -76,13 +76,17 @@ let workflow_cache = Cache::builder() .time_to_live(Duration::from_secs(10)) .build(); - let client_service = IdentityClientServiceServer::new( - ClientService::new(database_client.clone(), workflow_cache), + let raw_client_service = + ClientService::new(database_client.clone(), workflow_cache); + let client_service = IdentityClientServiceServer::with_interceptor( + raw_client_service, + grpc_services::shared::version_intercept, ); let raw_auth_service = AuthenticatedService::new(database_client.clone()); let auth_service = AuthServer::with_interceptor(raw_auth_service, move |req| { grpc_services::authenticated::auth_intercept(req, &database_client) + .and_then(grpc_services::shared::version_intercept) }); info!("Listening to gRPC traffic on {}", addr); diff --git a/shared/protos/identity_authenticated.proto b/shared/protos/identity_authenticated.proto --- a/shared/protos/identity_authenticated.proto +++ b/shared/protos/identity_authenticated.proto @@ -14,7 +14,7 @@ // Replenish one-time preKeys rpc UploadOneTimeKeys(UploadOneTimeKeysRequest) returns (identity.client.Empty) {} - // Rotate a devices preKey and preKey signature + // Rotate a device's preKey and preKey signature // Rotated for deniability of older messages rpc RefreshUserPreKeys(RefreshUserPreKeysRequest) returns (identity.client.Empty) {} @@ -62,5 +62,3 @@ message OutboundKeysForUserRequest { string userID = 1; } - - diff --git a/shared/protos/identity_client.proto b/shared/protos/identity_client.proto --- a/shared/protos/identity_client.proto +++ b/shared/protos/identity_client.proto @@ -55,9 +55,6 @@ (InboundKeysForUserResponse) {} // Replenish one-time preKeys rpc UploadOneTimeKeys(UploadOneTimeKeysRequest) returns (Empty) {} - // Rotate a devices preKey and preKey signature - // Rotated for deniability of older messages - rpc RefreshUserPreKeys(RefreshUserPreKeysRequest) returns (Empty) {} // Service actions @@ -73,6 +70,11 @@ // Called by Ashoat's keyserver to remove usernames from the Identity // service's reserved list rpc RemoveReservedUsername(RemoveReservedUsernameRequest) returns (Empty) {} + + // Miscellaneous actions + + // Called by users periodically to check if their code version is supported + rpc Ping(Empty) returns (Empty) {} } // Helper types @@ -331,13 +333,6 @@ repeated string notifOneTimePreKeys = 5; } -// RefreshUserPreKeys - -message RefreshUserPreKeysRequest { - string accessToken = 1; - PreKey newPreKeys = 2; -} - // VerifyUserAccessToken message VerifyUserAccessTokenRequest {