Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3514063
D8434.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
6 KB
Referenced Files
None
Subscribers
None
D8434.diff
View Options
diff --git a/services/identity/Dockerfile b/services/identity/Dockerfile
--- a/services/identity/Dockerfile
+++ b/services/identity/Dockerfile
@@ -13,10 +13,16 @@
RUN mkdir -p /home/comm/app/identity
WORKDIR /home/comm/app/identity
+RUN cargo init --bin
+
+COPY services/identity/Cargo.toml services/identity/Cargo.lock ./
+COPY shared/ ../../shared/
+
+# Cache build dependencies in a new layer
+RUN cargo build --release
+RUN rm src/*.rs
COPY services/identity .
-COPY shared/protos/identity_client.proto ../../shared/protos/
-COPY shared/comm-opaque2 ../../shared/comm-opaque2
RUN cargo install --locked --path .
diff --git a/services/identity/build.rs b/services/identity/build.rs
--- a/services/identity/build.rs
+++ b/services/identity/build.rs
@@ -3,7 +3,10 @@
.build_server(true)
.build_client(false)
.compile(
- &["../../shared/protos/identity_client.proto"],
+ &[
+ "../../shared/protos/identity_client.proto",
+ "../../shared/protos/identity_authenticated.proto",
+ ],
&["../../shared/protos/"],
)?;
Ok(())
diff --git a/services/identity/src/grpc_services/authenticated.rs b/services/identity/src/grpc_services/authenticated.rs
new file mode 100644
--- /dev/null
+++ b/services/identity/src/grpc_services/authenticated.rs
@@ -0,0 +1,79 @@
+use crate::{client_service::handle_db_error, database::DatabaseClient};
+use tonic::{Request, Response, Status};
+
+// This must be named client, because generated code from the authenticated
+// protobuf file references message structs from the client protobuf file
+// with the client:: namespace
+pub mod client {
+ tonic::include_proto!("identity.client");
+}
+pub mod auth_proto {
+ tonic::include_proto!("identity.authenticated");
+}
+use auth_proto::{
+ identity_client_service_server::IdentityClientService,
+ RefreshUserPreKeysRequest,
+};
+use client::Empty;
+use tracing::debug;
+
+#[derive(derive_more::Constructor)]
+pub struct AuthenticatedService {
+ db_client: DatabaseClient,
+}
+
+fn get_value<T>(req: &Request<T>, key: &str) -> Option<String> {
+ 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);
+
+ let user_id = get_value(req, "user_id")?;
+ let device_id = get_value(req, "device_id")?;
+ let access_token = get_value(req, "access_token")?;
+
+ Some((user_id, device_id, access_token))
+}
+
+pub fn auth_intercept(
+ req: Request<()>,
+ db_client: &DatabaseClient,
+) -> Result<Request<()>, Status> {
+ println!("Intercepting request: {:?}", req);
+
+ let (user_id, device_id, access_token) = get_auth_info(&req)
+ .ok_or(Status::unauthenticated("Missing credentials"))?;
+
+ 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 valid_token = tokio::task::block_in_place(move || {
+ handle
+ .block_on(new_db_client.verify_access_token(
+ user_id,
+ device_id,
+ access_token,
+ ))
+ .map_err(handle_db_error)
+ })?;
+
+ if !valid_token {
+ return Err(Status::aborted("Bad Credentials"));
+ }
+
+ Ok(req)
+}
+
+#[tonic::async_trait]
+impl IdentityClientService for AuthenticatedService {
+ async fn refresh_user_pre_keys(
+ &self,
+ _request: Request<RefreshUserPreKeysRequest>,
+ ) -> Result<Response<Empty>, Status> {
+ unimplemented!();
+ }
+}
diff --git a/services/identity/src/grpc_services/mod.rs b/services/identity/src/grpc_services/mod.rs
new file mode 100644
--- /dev/null
+++ b/services/identity/src/grpc_services/mod.rs
@@ -0,0 +1 @@
+pub mod authenticated;
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
@@ -9,6 +9,7 @@
mod config;
pub mod constants;
mod database;
+mod grpc_services;
mod id;
mod keygen;
mod nonce;
@@ -23,6 +24,8 @@
use tracing_subscriber::EnvFilter;
use client_service::{ClientService, IdentityClientServiceServer};
+use grpc_services::authenticated::auth_proto::identity_client_service_server::IdentityClientServiceServer as AuthServer;
+use grpc_services::authenticated::AuthenticatedService;
#[derive(Parser)]
#[clap(author, version, about, long_about = None)]
@@ -70,12 +73,19 @@
.time_to_live(Duration::from_secs(10))
.build();
let client_service = IdentityClientServiceServer::new(
- ClientService::new(database_client, workflow_cache),
+ ClientService::new(database_client.clone(), workflow_cache),
);
+ let raw_auth_service = AuthenticatedService::new(database_client.clone());
+ let auth_service =
+ AuthServer::with_interceptor(raw_auth_service, move |mut req| {
+ grpc_services::authenticated::auth_intercept(req, &database_client)
+ });
+
info!("Listening to gRPC traffic on {}", addr);
Server::builder()
.accept_http1(true)
.add_service(tonic_web::enable(client_service))
+ .add_service(auth_service)
.serve(addr)
.await?;
}
diff --git a/shared/protos/identity_authenticated.proto b/shared/protos/identity_authenticated.proto
new file mode 100644
--- /dev/null
+++ b/shared/protos/identity_authenticated.proto
@@ -0,0 +1,27 @@
+syntax = "proto3";
+
+import "identity_client.proto";
+
+package identity.authenticated;
+
+// RPCs from a client (iOS, Android, or web) to identity service
+//
+// This service will assert authenticity of a device by verifying the access
+// token through an interceptor, thus avoiding the need to explicitly pass
+// the credentials on every request
+service IdentityClientService {
+
+ // Rotate a devices preKey and preKey signature
+ // Rotated for deniability of older messages
+ rpc RefreshUserPreKeys(RefreshUserPreKeysRequest)
+ returns (identity.client.Empty) {}
+}
+
+// Helper types
+
+// RefreshUserPreKeys
+
+message RefreshUserPreKeysRequest {
+ identity.client.PreKey newContentPreKeys = 1;
+ identity.client.PreKey newNotifPreKeys = 2;
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Dec 23, 3:22 AM (18 h, 38 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2693348
Default Alt Text
D8434.diff (6 KB)
Attached To
Mode
D8434: [Identity] Add authenticated gRPC service
Attached
Detach File
Event Timeline
Log In to Comment