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);