diff --git a/services/identity/Cargo.lock b/services/identity/Cargo.lock
--- a/services/identity/Cargo.lock
+++ b/services/identity/Cargo.lock
@@ -66,6 +66,28 @@
  "event-listener",
 ]
 
+[[package]]
+name = "async-stream"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51"
+dependencies = [
+ "async-stream-impl",
+ "futures-core",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "async-stream-impl"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.28",
+]
+
 [[package]]
 name = "async-trait"
 version = "0.1.68"
@@ -1237,6 +1259,18 @@
  "subtle",
 ]
 
+[[package]]
+name = "grpc_clients"
+version = "0.1.0"
+dependencies = [
+ "derive_more",
+ "prost",
+ "tonic",
+ "tonic-build",
+ "tracing",
+ "tracing-subscriber",
+]
+
 [[package]]
 name = "h2"
 version = "0.3.17"
@@ -1399,10 +1433,10 @@
  "http",
  "hyper",
  "log",
- "rustls",
+ "rustls 0.20.8",
  "rustls-native-certs",
  "tokio",
- "tokio-rustls",
+ "tokio-rustls 0.23.4",
 ]
 
 [[package]]
@@ -1454,6 +1488,7 @@
  "constant_time_eq",
  "derive_more",
  "ed25519-dalek",
+ "grpc_clients",
  "hex",
  "moka",
  "once_cell",
@@ -2227,6 +2262,18 @@
  "webpki",
 ]
 
+[[package]]
+name = "rustls"
+version = "0.21.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d1feddffcfcc0b33f5c6ce9a29e341e4cd59c3f78e7ee45f4a40c038b1d6cbb"
+dependencies = [
+ "log",
+ "ring",
+ "rustls-webpki",
+ "sct",
+]
+
 [[package]]
 name = "rustls-native-certs"
 version = "0.6.2"
@@ -2248,6 +2295,16 @@
  "base64",
 ]
 
+[[package]]
+name = "rustls-webpki"
+version = "0.101.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "261e9e0888cba427c3316e6322805653c9425240b6fd96cee7cb671ab70ab8d0"
+dependencies = [
+ "ring",
+ "untrusted",
+]
+
 [[package]]
 name = "rustversion"
 version = "1.0.12"
@@ -2687,11 +2744,21 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59"
 dependencies = [
- "rustls",
+ "rustls 0.20.8",
  "tokio",
  "webpki",
 ]
 
+[[package]]
+name = "tokio-rustls"
+version = "0.24.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081"
+dependencies = [
+ "rustls 0.21.6",
+ "tokio",
+]
+
 [[package]]
 name = "tokio-stream"
 version = "0.1.12"
@@ -2723,6 +2790,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "38bd8e87955eb13c1986671838177d6792cdc52af9bffced0d2c8a9a7f741ab3"
 dependencies = [
+ "async-stream",
  "async-trait",
  "axum",
  "base64",
@@ -2737,7 +2805,9 @@
  "percent-encoding",
  "pin-project",
  "prost",
+ "rustls-pemfile",
  "tokio",
+ "tokio-rustls 0.24.1",
  "tokio-stream",
  "tower",
  "tower-layer",
diff --git a/services/identity/Cargo.toml b/services/identity/Cargo.toml
--- a/services/identity/Cargo.toml
+++ b/services/identity/Cargo.toml
@@ -20,6 +20,7 @@
 constant_time_eq = "0.2.2"
 siwe = "0.3"
 comm-opaque2 = { path = "../../shared/comm-opaque2" }
+grpc_clients = { path = "../../shared/grpc_clients" }
 once_cell = "1.17"
 hex = "0.4"
 tonic-web = "0.9.1"
diff --git a/services/identity/build.rs b/services/identity/build.rs
--- a/services/identity/build.rs
+++ b/services/identity/build.rs
@@ -9,12 +9,5 @@
       ],
       &["../../shared/protos/"],
     )?;
-  tonic_build::configure()
-    .build_server(false)
-    .build_client(true)
-    .compile(
-      &["../../shared/protos/tunnelbroker.proto"],
-      &["../../shared/protos/"],
-    )?;
   Ok(())
 }
diff --git a/services/identity/src/tunnelbroker.rs b/services/identity/src/tunnelbroker.rs
--- a/services/identity/src/tunnelbroker.rs
+++ b/services/identity/src/tunnelbroker.rs
@@ -1,11 +1,11 @@
-mod proto {
-  tonic::include_proto!("tunnelbroker");
-}
 use crate::config::CONFIG;
-use proto::tunnelbroker_service_client::TunnelbrokerServiceClient;
-use proto::{Empty, MessageToDevice};
+use grpc_clients::tunnelbroker::create_tunnelbroker_client as shared_tb_client;
+use grpc_clients::tunnelbroker::protos;
+use protos::tunnelbroker_service_client::TunnelbrokerServiceClient;
+use protos::{Empty, MessageToDevice};
 use tonic::transport::Channel;
 use tonic::Response;
+use tonic::Status;
 use tracing::error;
 use tunnelbroker_messages as messages;
 
@@ -13,11 +13,11 @@
 
 pub async fn create_tunnelbroker_client(
 ) -> Result<TunnelbrokerServiceClient<Channel>, Error> {
-  TunnelbrokerServiceClient::connect(CONFIG.tunnelbroker_endpoint.to_string())
+  shared_tb_client(&CONFIG.tunnelbroker_endpoint)
     .await
     .map_err(|e| {
       error!("Unable able to connect to tunnelbroker: {:?}", e);
-      e.into()
+      Error::Status(Status::invalid_argument(format!("{}", e)))
     })
 }