diff --git a/keyserver/addons/rust-node-addon/src/identity_client/register_user.rs b/keyserver/addons/rust-node-addon/src/identity_client/register_user.rs
--- a/keyserver/addons/rust-node-addon/src/identity_client/register_user.rs
+++ b/keyserver/addons/rust-node-addon/src/identity_client/register_user.rs
@@ -47,6 +47,7 @@
     opaque_registration_request,
     username,
     device_key_upload: Some(device_key_upload),
+    farcaster_id: None,
   };
 
   // Finish OPAQUE registration and send final registration request
diff --git a/native/native_rust_library/src/lib.rs b/native/native_rust_library/src/lib.rs
--- a/native/native_rust_library/src/lib.rs
+++ b/native/native_rust_library/src/lib.rs
@@ -626,6 +626,7 @@
       one_time_notif_prekeys: password_user_info.notif_one_time_keys,
       device_type: DEVICE_TYPE.into(),
     }),
+    farcaster_id: None,
   };
 
   let mut identity_client = get_unauthenticated_client(
@@ -820,6 +821,7 @@
       one_time_notif_prekeys: wallet_user_info.notif_one_time_keys,
       device_type: DEVICE_TYPE.into(),
     }),
+    farcaster_id: None,
   };
 
   let mut identity_client = get_unauthenticated_client(
diff --git a/native/native_rust_library/src/wallet_registration.rs b/native/native_rust_library/src/wallet_registration.rs
--- a/native/native_rust_library/src/wallet_registration.rs
+++ b/native/native_rust_library/src/wallet_registration.rs
@@ -66,6 +66,7 @@
       one_time_notif_prekeys: wallet_user_info.notif_one_time_keys,
       device_type: DEVICE_TYPE.into(),
     }),
+    farcaster_id: None,
   };
 
   let mut identity_client = get_unauthenticated_client(
diff --git a/services/commtest/src/identity/device.rs b/services/commtest/src/identity/device.rs
--- a/services/commtest/src/identity/device.rs
+++ b/services/commtest/src/identity/device.rs
@@ -70,6 +70,7 @@
       one_time_notif_prekeys: Vec::new(),
       device_type: device_type.into(),
     }),
+    farcaster_id: None,
   };
 
   let mut identity_client = get_unauthenticated_client(
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
@@ -59,6 +59,7 @@
   pub username: String,
   pub flattened_device_key_upload: FlattenedDeviceKeyUpload,
   pub user_id: Option<String>,
+  pub farcaster_id: Option<String>,
 }
 
 #[derive(Clone, Serialize, Deserialize)]
@@ -127,6 +128,7 @@
       &message,
       None,
       message.username.clone(),
+      message.farcaster_id.clone(),
     )?;
     let server_registration = comm_opaque2::server::Registration::new();
     let server_message = server_registration
@@ -181,6 +183,7 @@
       &message,
       Some(user_id),
       message.username.clone(),
+      None,
     )?;
     let server_registration = comm_opaque2::server::Registration::new();
     let server_message = server_registration
@@ -554,6 +557,7 @@
         None,
         code_version,
         login_time,
+        message.farcaster_id,
       )
       .await
       .map_err(handle_db_error)?;
@@ -635,6 +639,7 @@
         Some(user_id.clone()),
         code_version,
         login_time,
+        None,
       )
       .await
       .map_err(handle_db_error)?;
@@ -988,6 +993,7 @@
   message: &impl DeviceKeyUploadActions,
   user_id: Option<String>,
   username: String,
+  farcaster_id: Option<String>,
 ) -> Result<UserRegistrationInfo, tonic::Status> {
   Ok(UserRegistrationInfo {
     username,
@@ -995,6 +1001,7 @@
       message,
     )?,
     user_id,
+    farcaster_id,
   })
 }
 
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
@@ -53,6 +53,7 @@
 pub const USERS_TABLE_SOCIAL_PROOF_ATTRIBUTE_NAME: &str = "socialProof";
 pub const USERS_TABLE_DEVICELIST_TIMESTAMP_ATTRIBUTE_NAME: &str =
   "deviceListTimestamp";
+pub const USERS_TABLE_FARCASTER_ID_ATTRIBUTE_NAME: &str = "farcasterID";
 pub const USERS_TABLE_USERNAME_INDEX: &str = "username-index";
 pub const USERS_TABLE_WALLET_ADDRESS_INDEX: &str = "walletAddress-index";
 
diff --git a/services/identity/src/database.rs b/services/identity/src/database.rs
--- a/services/identity/src/database.rs
+++ b/services/identity/src/database.rs
@@ -47,9 +47,10 @@
   RESERVED_USERNAMES_TABLE, RESERVED_USERNAMES_TABLE_PARTITION_KEY,
   RESERVED_USERNAMES_TABLE_USER_ID_ATTRIBUTE, USERS_TABLE,
   USERS_TABLE_DEVICES_MAP_DEVICE_TYPE_ATTRIBUTE_NAME,
-  USERS_TABLE_PARTITION_KEY, USERS_TABLE_REGISTRATION_ATTRIBUTE,
-  USERS_TABLE_USERNAME_ATTRIBUTE, USERS_TABLE_USERNAME_INDEX,
-  USERS_TABLE_WALLET_ADDRESS_ATTRIBUTE, USERS_TABLE_WALLET_ADDRESS_INDEX,
+  USERS_TABLE_FARCASTER_ID_ATTRIBUTE_NAME, USERS_TABLE_PARTITION_KEY,
+  USERS_TABLE_REGISTRATION_ATTRIBUTE, USERS_TABLE_USERNAME_ATTRIBUTE,
+  USERS_TABLE_USERNAME_INDEX, USERS_TABLE_WALLET_ADDRESS_ATTRIBUTE,
+  USERS_TABLE_WALLET_ADDRESS_INDEX,
 };
 use crate::id::generate_uuid;
 use crate::nonce::NonceData;
@@ -171,6 +172,7 @@
         Some((registration_state.username, Blob::new(password_file))),
         None,
         registration_state.user_id,
+        registration_state.farcaster_id,
       )
       .await?;
 
@@ -194,6 +196,7 @@
     user_id: Option<String>,
     code_version: u64,
     access_token_creation_time: DateTime<Utc>,
+    farcaster_id: Option<String>,
   ) -> Result<String, Error> {
     let wallet_identity = EthereumIdentity {
       wallet_address,
@@ -205,6 +208,7 @@
         None,
         Some(wallet_identity),
         user_id,
+        farcaster_id,
       )
       .await?;
 
@@ -226,6 +230,7 @@
     username_and_password_file: Option<(String, Blob)>,
     wallet_identity: Option<EthereumIdentity>,
     user_id: Option<String>,
+    farcaster_id: Option<String>,
   ) -> Result<String, Error> {
     let user_id = user_id.unwrap_or_else(generate_uuid);
     let mut user = HashMap::from([(
@@ -255,6 +260,13 @@
       );
     }
 
+    if let Some(fid) = farcaster_id {
+      user.insert(
+        USERS_TABLE_FARCASTER_ID_ATTRIBUTE_NAME.to_string(),
+        AttributeValue::S(fid),
+      );
+    }
+
     self
       .client
       .put_item()
diff --git a/shared/protos/identity_unauth.proto b/shared/protos/identity_unauth.proto
--- a/shared/protos/identity_unauth.proto
+++ b/shared/protos/identity_unauth.proto
@@ -117,6 +117,7 @@
   string username = 2;
   // Information needed to open a new channel to current user's device
   DeviceKeyUpload device_key_upload = 3;
+  optional string farcaster_id = 4;
 }
 
 message ReservedRegistrationStartRequest {
@@ -191,6 +192,7 @@
   // Information specific to a user's device needed to open a new channel of
   // communication with this user
   DeviceKeyUpload device_key_upload = 3;
+  optional string farcaster_id = 4;
 }
 
 message ReservedWalletRegistrationRequest {
diff --git a/web/protobufs/identity-unauth-structs.cjs b/web/protobufs/identity-unauth-structs.cjs
--- a/web/protobufs/identity-unauth-structs.cjs
+++ b/web/protobufs/identity-unauth-structs.cjs
@@ -1399,7 +1399,8 @@
   var f, obj = {
     opaqueRegistrationRequest: msg.getOpaqueRegistrationRequest_asB64(),
     username: jspb.Message.getFieldWithDefault(msg, 2, ""),
-    deviceKeyUpload: (f = msg.getDeviceKeyUpload()) && proto.identity.unauth.DeviceKeyUpload.toObject(includeInstance, f)
+    deviceKeyUpload: (f = msg.getDeviceKeyUpload()) && proto.identity.unauth.DeviceKeyUpload.toObject(includeInstance, f),
+    farcasterId: jspb.Message.getFieldWithDefault(msg, 4, "")
   };
 
   if (includeInstance) {
@@ -1449,6 +1450,10 @@
       reader.readMessage(value,proto.identity.unauth.DeviceKeyUpload.deserializeBinaryFromReader);
       msg.setDeviceKeyUpload(value);
       break;
+    case 4:
+      var value = /** @type {string} */ (reader.readString());
+      msg.setFarcasterId(value);
+      break;
     default:
       reader.skipField();
       break;
@@ -1500,6 +1505,13 @@
       proto.identity.unauth.DeviceKeyUpload.serializeBinaryToWriter
     );
   }
+  f = /** @type {string} */ (jspb.Message.getField(message, 4));
+  if (f != null) {
+    writer.writeString(
+      4,
+      f
+    );
+  }
 };
 
 
@@ -1600,6 +1612,42 @@
 };
 
 
+/**
+ * optional string farcaster_id = 4;
+ * @return {string}
+ */
+proto.identity.unauth.RegistrationStartRequest.prototype.getFarcasterId = function() {
+  return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 4, ""));
+};
+
+
+/**
+ * @param {string} value
+ * @return {!proto.identity.unauth.RegistrationStartRequest} returns this
+ */
+proto.identity.unauth.RegistrationStartRequest.prototype.setFarcasterId = function(value) {
+  return jspb.Message.setField(this, 4, value);
+};
+
+
+/**
+ * Clears the field making it undefined.
+ * @return {!proto.identity.unauth.RegistrationStartRequest} returns this
+ */
+proto.identity.unauth.RegistrationStartRequest.prototype.clearFarcasterId = function() {
+  return jspb.Message.setField(this, 4, undefined);
+};
+
+
+/**
+ * Returns whether this field is set.
+ * @return {boolean}
+ */
+proto.identity.unauth.RegistrationStartRequest.prototype.hasFarcasterId = function() {
+  return jspb.Message.getField(this, 4) != null;
+};
+
+
 
 
 
@@ -3108,7 +3156,8 @@
   var f, obj = {
     siweMessage: jspb.Message.getFieldWithDefault(msg, 1, ""),
     siweSignature: jspb.Message.getFieldWithDefault(msg, 2, ""),
-    deviceKeyUpload: (f = msg.getDeviceKeyUpload()) && proto.identity.unauth.DeviceKeyUpload.toObject(includeInstance, f)
+    deviceKeyUpload: (f = msg.getDeviceKeyUpload()) && proto.identity.unauth.DeviceKeyUpload.toObject(includeInstance, f),
+    farcasterId: jspb.Message.getFieldWithDefault(msg, 4, "")
   };
 
   if (includeInstance) {
@@ -3158,6 +3207,10 @@
       reader.readMessage(value,proto.identity.unauth.DeviceKeyUpload.deserializeBinaryFromReader);
       msg.setDeviceKeyUpload(value);
       break;
+    case 4:
+      var value = /** @type {string} */ (reader.readString());
+      msg.setFarcasterId(value);
+      break;
     default:
       reader.skipField();
       break;
@@ -3209,6 +3262,13 @@
       proto.identity.unauth.DeviceKeyUpload.serializeBinaryToWriter
     );
   }
+  f = /** @type {string} */ (jspb.Message.getField(message, 4));
+  if (f != null) {
+    writer.writeString(
+      4,
+      f
+    );
+  }
 };
 
 
@@ -3285,6 +3345,42 @@
 };
 
 
+/**
+ * optional string farcaster_id = 4;
+ * @return {string}
+ */
+proto.identity.unauth.WalletAuthRequest.prototype.getFarcasterId = function() {
+  return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 4, ""));
+};
+
+
+/**
+ * @param {string} value
+ * @return {!proto.identity.unauth.WalletAuthRequest} returns this
+ */
+proto.identity.unauth.WalletAuthRequest.prototype.setFarcasterId = function(value) {
+  return jspb.Message.setField(this, 4, value);
+};
+
+
+/**
+ * Clears the field making it undefined.
+ * @return {!proto.identity.unauth.WalletAuthRequest} returns this
+ */
+proto.identity.unauth.WalletAuthRequest.prototype.clearFarcasterId = function() {
+  return jspb.Message.setField(this, 4, undefined);
+};
+
+
+/**
+ * Returns whether this field is set.
+ * @return {boolean}
+ */
+proto.identity.unauth.WalletAuthRequest.prototype.hasFarcasterId = function() {
+  return jspb.Message.getField(this, 4) != null;
+};
+
+
 
 
 
diff --git a/web/protobufs/identity-unauth-structs.cjs.flow b/web/protobufs/identity-unauth-structs.cjs.flow
--- a/web/protobufs/identity-unauth-structs.cjs.flow
+++ b/web/protobufs/identity-unauth-structs.cjs.flow
@@ -122,6 +122,11 @@
   hasDeviceKeyUpload(): boolean;
   clearDeviceKeyUpload(): RegistrationStartRequest;
 
+  getFarcasterId(): string;
+  setFarcasterId(value: string): RegistrationStartRequest;
+  hasFarcasterId(): boolean;
+  clearFarcasterId(): RegistrationStartRequest;
+
   serializeBinary(): Uint8Array;
   toObject(includeInstance?: boolean): RegistrationStartRequestObject;
   static toObject(includeInstance: boolean, msg: RegistrationStartRequest): RegistrationStartRequestObject;
@@ -134,6 +139,7 @@
   opaqueRegistrationRequest: Uint8Array | string,
   username: string,
   deviceKeyUpload?: DeviceKeyUploadObject,
+  farcasterId?: string,
 };
 
 declare export class ReservedRegistrationStartRequest extends Message {
@@ -326,6 +332,11 @@
   hasDeviceKeyUpload(): boolean;
   clearDeviceKeyUpload(): WalletAuthRequest;
 
+  getFarcasterId(): string;
+  setFarcasterId(value: string): WalletAuthRequest;
+  hasFarcasterId(): boolean;
+  clearFarcasterId(): WalletAuthRequest;
+
   serializeBinary(): Uint8Array;
   toObject(includeInstance?: boolean): WalletAuthRequestObject;
   static toObject(includeInstance: boolean, msg: WalletAuthRequest): WalletAuthRequestObject;
@@ -338,6 +349,7 @@
   siweMessage: string,
   siweSignature: string,
   deviceKeyUpload?: DeviceKeyUploadObject,
+  farcasterId?: string,
 };
 
 declare export class ReservedWalletRegistrationRequest extends Message {