diff --git a/services/identity/src/constants.rs b/services/identity/src/constants.rs --- a/services/identity/src/constants.rs +++ b/services/identity/src/constants.rs @@ -279,6 +279,7 @@ pub const USER_ID: &str = "user_id"; pub const DEVICE_ID: &str = "device_id"; pub const ACCESS_TOKEN: &str = "access_token"; + pub const SERVICES_TOKEN: &str = "services_token"; } // CORS 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 @@ -3,9 +3,7 @@ use crate::comm_service::{backup, blob, tunnelbroker}; use crate::config::CONFIG; use crate::constants::staff::AUTHORITATIVE_KEYSERVER_OWNER_USER_ID; -use crate::database::{ - DeviceListRow, DeviceListUpdate, PlatformDetails, Prekey, -}; +use crate::database::{DeviceListRow, DeviceListUpdate, PlatformDetails}; use crate::device_list::validation::DeviceListValidator; use crate::device_list::SignedDeviceList; use crate::error::consume_error; @@ -18,7 +16,7 @@ grpc_services::shared::{get_platform_metadata, get_value}, }; use chrono::DateTime; -use comm_lib::auth::AuthService; +use comm_lib::auth::{AuthService, ServicesAuthToken}; use comm_lib::blob::client::BlobServiceClient; use comm_opaque2::grpc::protocol_error_to_grpc_status; use tonic::{Request, Response, Status}; @@ -63,19 +61,43 @@ pub fn auth_interceptor( req: Request<()>, db_client: &DatabaseClient, + auth_service: &comm_lib::auth::AuthService, ) -> Result<Request<()>, Status> { + use tonic_status_messages as msg; + trace!("Intercepting request to check auth info: {:?}", req); + let handle = tokio::runtime::Handle::current(); - let (user_id, device_id, access_token) = - get_auth_info(&req).ok_or_else(|| { - Status::unauthenticated(tonic_status_messages::MISSING_CREDENTIALS) - })?; + if let Some(s2s_token) = get_value(&req, request_metadata::SERVICES_TOKEN) { + let auth_credential = ServicesAuthToken::new(s2s_token); + let auth_service = auth_service.clone(); - let handle = tokio::runtime::Handle::current(); - let new_db_client = db_client.clone(); + // This function cannot be `async`, yet must call the async db call + // Force tokio to resolve future in current thread without an explicit .await + let verification_result = tokio::task::block_in_place(move || { + handle + .block_on(auth_service.verify_auth_credential(&auth_credential.into())) + }); + + return match verification_result { + Ok(true) => Ok(req), + Ok(false) => Err(Status::aborted(msg::BAD_CREDENTIALS)), + Err(err) => { + tracing::error!( + errorType = error_types::HTTP_LOG, + "Failed to verify service-to-service token: {err:?}", + ); + Err(tonic::Status::aborted(msg::UNEXPECTED_ERROR)) + } + }; + } + + let (user_id, device_id, access_token) = get_auth_info(&req) + .ok_or_else(|| Status::unauthenticated(msg::MISSING_CREDENTIALS))?; // This function cannot be `async`, yet must call the async db call // Force tokio to resolve future in current thread without an explicit .await + let new_db_client = db_client.clone(); let valid_token = tokio::task::block_in_place(move || { handle.block_on(new_db_client.verify_access_token( user_id, @@ -85,7 +107,7 @@ })?; if !valid_token { - return Err(Status::aborted(tonic_status_messages::BAD_CREDENTIALS)); + return Err(Status::aborted(msg::BAD_CREDENTIALS)); } Ok(req) 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 @@ -116,13 +116,17 @@ let inner_auth_service = AuthenticatedService::new( database_client.clone(), blob_client, - comm_auth_service, + comm_auth_service.clone(), ); let db_client = database_client.clone(); let auth_service = AuthServer::with_interceptor(inner_auth_service, move |req| { - grpc_services::authenticated::auth_interceptor(req, &db_client) - .and_then(grpc_services::shared::version_interceptor) + grpc_services::authenticated::auth_interceptor( + req, + &db_client, + &comm_auth_service, + ) + .and_then(grpc_services::shared::version_interceptor) }); info!("Listening to gRPC traffic on {}", addr);