Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3569455
D12090.id40602.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
D12090.id40602.diff
View Options
diff --git a/services/identity/src/client_service.rs b/services/identity/src/client_service.rs
--- a/services/identity/src/client_service.rs
+++ b/services/identity/src/client_service.rs
@@ -18,8 +18,9 @@
error_types
};
use crate::database::{
- DBDeviceTypeInt, DatabaseClient, DeviceType, KeyPayload,
+ DBDeviceTypeInt, DatabaseClient, DeviceType, KeyPayload
};
+use crate::device_list::SignedDeviceList;
use crate::error::{DeviceListError, Error as DBError};
use crate::grpc_services::authenticated::DeletePasswordUserInfo;
use crate::grpc_services::protos::unauth::{
@@ -35,7 +36,7 @@
};
use crate::grpc_services::shared::get_value;
use crate::grpc_utils::{
- SignedNonce, DeviceKeyUploadActions,
+ DeviceKeyUploadActions, RegistrationActions, SignedNonce
};
use crate::nonce::generate_nonce_data;
use crate::reserved_users::{
@@ -66,6 +67,7 @@
pub flattened_device_key_upload: FlattenedDeviceKeyUpload,
pub user_id: Option<String>,
pub farcaster_id: Option<String>,
+ pub initial_device_list: Option<SignedDeviceList>,
}
#[derive(Clone, Serialize, Deserialize)]
@@ -439,6 +441,13 @@
let code_version = get_code_version(&request);
let message = request.into_inner();
+ // WalletAuthRequest is used for both log_in_wallet_user and register_wallet_user
+ if !message.initial_device_list.is_empty() {
+ return Err(tonic::Status::invalid_argument(
+ "unexpected initial device list",
+ ));
+ }
+
let parsed_message = parse_and_verify_siwe_message(
&message.siwe_message,
&message.siwe_signature,
@@ -1129,7 +1138,7 @@
}
fn construct_user_registration_info(
- message: &impl DeviceKeyUploadActions,
+ message: &(impl DeviceKeyUploadActions + RegistrationActions),
user_id: Option<String>,
username: String,
farcaster_id: Option<String>,
@@ -1141,6 +1150,7 @@
)?,
user_id,
farcaster_id,
+ initial_device_list: message.get_and_verify_initial_device_list()?,
})
}
diff --git a/services/identity/src/device_list.rs b/services/identity/src/device_list.rs
--- a/services/identity/src/device_list.rs
+++ b/services/identity/src/device_list.rs
@@ -1,5 +1,5 @@
use chrono::{DateTime, Duration, Utc};
-use std::collections::HashSet;
+use std::{collections::HashSet, str::FromStr};
use tracing::{debug, error, warn};
use crate::{
@@ -20,7 +20,7 @@
/// Signed device list payload that is serializable to JSON.
/// For the DDB payload, see [`DeviceListUpdate`]
-#[derive(serde::Serialize, serde::Deserialize)]
+#[derive(Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SignedDeviceList {
/// JSON-stringified [`RawDeviceList`]
@@ -88,13 +88,20 @@
impl TryFrom<UpdateDeviceListRequest> for SignedDeviceList {
type Error = tonic::Status;
fn try_from(request: UpdateDeviceListRequest) -> Result<Self, Self::Error> {
- serde_json::from_str(&request.new_device_list).map_err(|err| {
+ request.new_device_list.parse().map_err(|err| {
warn!("Failed to deserialize device list update: {}", err);
tonic::Status::invalid_argument("invalid device list payload")
})
}
}
+impl FromStr for SignedDeviceList {
+ type Err = serde_json::Error;
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ serde_json::from_str(s)
+ }
+}
+
impl TryFrom<SignedDeviceList> for DeviceListUpdate {
type Error = tonic::Status;
fn try_from(signed_list: SignedDeviceList) -> Result<Self, Self::Error> {
diff --git a/services/identity/src/grpc_utils.rs b/services/identity/src/grpc_utils.rs
--- a/services/identity/src/grpc_utils.rs
+++ b/services/identity/src/grpc_utils.rs
@@ -2,11 +2,12 @@
use ed25519_dalek::{PublicKey, Signature, Verifier};
use serde::Deserialize;
use tonic::Status;
+use tracing::warn;
use crate::{
- database::DeviceRow,
- ddb_utils::DBIdentity,
- ddb_utils::Identifier as DBIdentifier,
+ database::{DeviceListUpdate, DeviceRow, KeyPayload},
+ ddb_utils::{DBIdentity, Identifier as DBIdentifier},
+ device_list::SignedDeviceList,
grpc_services::protos::{
auth::{EthereumIdentity, Identity, InboundKeyInfo, OutboundKeyInfo},
unauth::{
@@ -249,6 +250,68 @@
}
}
+/// Common functionality for registration request messages
+trait RegistrationData {
+ fn initial_device_list(&self) -> &str;
+}
+
+impl RegistrationData for RegistrationStartRequest {
+ fn initial_device_list(&self) -> &str {
+ &self.initial_device_list
+ }
+}
+impl RegistrationData for ReservedRegistrationStartRequest {
+ fn initial_device_list(&self) -> &str {
+ &self.initial_device_list
+ }
+}
+impl RegistrationData for WalletAuthRequest {
+ fn initial_device_list(&self) -> &str {
+ &self.initial_device_list
+ }
+}
+impl RegistrationData for ReservedWalletRegistrationRequest {
+ fn initial_device_list(&self) -> &str {
+ &self.initial_device_list
+ }
+}
+
+/// Similar to `[DeviceKeyUploadActions]` but only for registration requests
+pub trait RegistrationActions {
+ fn get_and_verify_initial_device_list(
+ &self,
+ ) -> Result<Option<SignedDeviceList>, tonic::Status>;
+}
+
+impl<T: RegistrationData + DeviceKeyUploadActions> RegistrationActions for T {
+ fn get_and_verify_initial_device_list(
+ &self,
+ ) -> Result<Option<SignedDeviceList>, tonic::Status> {
+ let payload = self.initial_device_list();
+ if payload.is_empty() {
+ return Ok(None);
+ }
+ let signed_list: SignedDeviceList = payload.parse().map_err(|err| {
+ warn!("Failed to deserialize initial device list: {}", err);
+ tonic::Status::invalid_argument("invalid device list payload")
+ })?;
+
+ let key_info = self
+ .payload()?
+ .parse::<KeyPayload>()
+ .map_err(|_| tonic::Status::invalid_argument("malformed payload"))?;
+ let primary_device_id = key_info.primary_identity_public_keys.ed25519;
+
+ let update_payload = DeviceListUpdate::try_from(signed_list.clone())?;
+ crate::device_list::verify_initial_device_list(
+ &update_payload,
+ &primary_device_id,
+ )?;
+
+ Ok(Some(signed_list))
+ }
+}
+
impl From<DBIdentity> for Identity {
fn from(value: DBIdentity) -> Self {
match value.identifier {
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Dec 29, 2:23 AM (8 h, 23 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2726179
Default Alt Text
D12090.id40602.diff (6 KB)
Attached To
Mode
D12090: [identity] Get and verify initial device list from registration requests
Attached
Detach File
Event Timeline
Log In to Comment