diff --git a/keyserver/addons/rust-node-addon/src/identity_client/login.rs b/keyserver/addons/rust-node-addon/src/identity_client/login.rs --- a/keyserver/addons/rust-node-addon/src/identity_client/login.rs +++ b/keyserver/addons/rust-node-addon/src/identity_client/login.rs @@ -54,20 +54,34 @@ }; debug!("Starting login to identity service"); - let login_start_response = identity_client + let response = identity_client .login_password_user_start(login_start_request) .await - .map_err(handle_grpc_error)? - .into_inner(); - + .map_err(handle_grpc_error)?; debug!("Received login response from identity service"); + + // We need to get the load balancer cookie from from the response and send it + // in the subsequent request to ensure it is routed to the same identity + // service instance as the first request + let cookie = response.metadata().get("set-cookie").cloned(); + + let login_start_response = response.into_inner(); + 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 { + + let mut login_finish_request = Request::new(OpaqueLoginFinishRequest { session_id: login_start_response.session_id, opaque_login_upload, - }; + }); + + // Cookie won't be available in local dev environments + if let Some(cookie_metadata) = cookie { + login_finish_request + .metadata_mut() + .insert("cookie", cookie_metadata); + } debug!("Attempting to finalize opaque login exchange with identity service"); let login_finish_response = identity_client 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 --- a/keyserver/addons/rust-node-addon/src/identity_client/register_user.rs +++ b/keyserver/addons/rust-node-addon/src/identity_client/register_user.rs @@ -50,13 +50,19 @@ }); // Finish OPAQUE registration and send final registration request - let registration_start_response = identity_client + let response = identity_client .register_password_user_start(registration_start_request) .await - .map_err(handle_grpc_error)? - .into_inner(); + .map_err(handle_grpc_error)?; debug!("Received registration start response"); + // We need to get the load balancer cookie from from the response and send it + // in the subsequent request to ensure it is routed to the same identity + // service instance as the first request + let cookie = response.metadata().get("set-cookie").cloned(); + + let registration_start_response = response.into_inner(); + let opaque_registration_upload = opaque_registration .finish( &password, @@ -64,10 +70,18 @@ ) .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 mut registration_finish_request = + Request::new(RegistrationFinishRequest { + session_id: registration_start_response.session_id, + opaque_registration_upload, + }); + + // Cookie won't be available in local dev environments + if let Some(cookie_metadata) = cookie { + registration_finish_request + .metadata_mut() + .insert("cookie", cookie_metadata); + } let registration_response = identity_client .register_password_user_finish(registration_finish_request) diff --git a/native/native_rust_library/src/lib.rs b/native/native_rust_library/src/lib.rs --- a/native/native_rust_library/src/lib.rs +++ b/native/native_rust_library/src/lib.rs @@ -14,7 +14,7 @@ use serde::Serialize; use std::sync::Arc; use tokio::runtime::{Builder, Runtime}; -use tonic::Status; +use tonic::{Request, Status}; use tracing::instrument; mod argon2_tools; @@ -374,10 +374,16 @@ DEVICE_TYPE.as_str_name().to_lowercase(), ) .await?; - let registration_start_response = identity_client + let response = identity_client .register_password_user_start(registration_start_request) - .await? - .into_inner(); + .await?; + + // We need to get the load balancer cookie from from the response and send it + // in the subsequent request to ensure it is routed to the same identity + // service instance as the first request + let cookie = response.metadata().get("set-cookie").cloned(); + + let registration_start_response = response.into_inner(); let opaque_registration_upload = client_registration .finish( @@ -385,13 +391,23 @@ ®istration_start_response.opaque_registration_response, ) .map_err(handle_error)?; + let registration_finish_request = RegistrationFinishRequest { session_id: registration_start_response.session_id, opaque_registration_upload, }; + let mut finish_request = Request::new(registration_finish_request); + + // Cookie won't be available in local dev environments + if let Some(cookie_metadata) = cookie { + finish_request + .metadata_mut() + .insert("cookie", cookie_metadata); + } + let registration_finish_response = identity_client - .register_password_user_finish(registration_finish_request) + .register_password_user_finish(finish_request) .await? .into_inner(); let user_id_and_access_token = UserIDAndDeviceAccessToken { @@ -470,21 +486,37 @@ ) .await?; - let login_start_response = identity_client + let response = identity_client .login_password_user_start(login_start_request) - .await? - .into_inner(); + .await?; + + // We need to get the load balancer cookie from from the response and send it + // in the subsequent request to ensure it is routed to the same identity + // service instance as the first request + let cookie = response.metadata().get("set-cookie").cloned(); + + let login_start_response = response.into_inner(); let opaque_login_upload = client_login .finish(&login_start_response.opaque_login_response) .map_err(handle_error)?; + let login_finish_request = OpaqueLoginFinishRequest { session_id: login_start_response.session_id, opaque_login_upload, }; + let mut finish_request = Request::new(login_finish_request); + + // Cookie won't be available in local dev environments + if let Some(cookie_metadata) = cookie { + finish_request + .metadata_mut() + .insert("cookie", cookie_metadata); + } + let login_finish_response = identity_client - .login_password_user_finish(login_finish_request) + .login_password_user_finish(finish_request) .await? .into_inner(); let user_id_and_access_token = UserIDAndDeviceAccessToken { @@ -633,10 +665,16 @@ ) .await?; - let update_password_start_response = identity_client + let response = identity_client .update_user_password_start(update_password_start_request) - .await? - .into_inner(); + .await?; + + // We need to get the load balancer cookie from from the response and send it + // in the subsequent request to ensure it is routed to the same identity + // service instance as the first request + let cookie = response.metadata().get("set-cookie").cloned(); + + let update_password_start_response = response.into_inner(); let opaque_registration_upload = client_registration .finish( @@ -644,13 +682,23 @@ &update_password_start_response.opaque_registration_response, ) .map_err(handle_error)?; + let update_password_finish_request = UpdateUserPasswordFinishRequest { session_id: update_password_start_response.session_id, opaque_registration_upload, }; + let mut finish_request = Request::new(update_password_finish_request); + + // Cookie won't be available in local dev environments + if let Some(cookie_metadata) = cookie { + finish_request + .metadata_mut() + .insert("cookie", cookie_metadata); + } + identity_client - .update_user_password_finish(update_password_finish_request) + .update_user_password_finish(finish_request) .await?; Ok(())