diff --git a/server/crates/arbiter-client/src/lib.rs b/server/crates/arbiter-client/src/lib.rs
index 2c7ec5b..cd65220 100644
--- a/server/crates/arbiter-client/src/lib.rs
+++ b/server/crates/arbiter-client/src/lib.rs
@@ -367,7 +367,9 @@ async fn receive_auth_confirmation(
.await
.map_err(|_| ConnectError::UnexpectedAuthResponse)?;
- let payload = response.payload.ok_or(ConnectError::UnexpectedAuthResponse)?;
+ let payload = response
+ .payload
+ .ok_or(ConnectError::UnexpectedAuthResponse)?;
match payload {
ClientResponsePayload::AuthOk(_) => Ok(()),
ClientResponsePayload::ClientConnectError(err) => Err(map_connect_error(err.code)),
diff --git a/server/crates/arbiter-server/src/actors/client/auth.rs b/server/crates/arbiter-server/src/actors/client/auth.rs
index 55acb4c..18386d8 100644
--- a/server/crates/arbiter-server/src/actors/client/auth.rs
+++ b/server/crates/arbiter-server/src/actors/client/auth.rs
@@ -1,8 +1,8 @@
use arbiter_proto::{
format_challenge,
proto::client::{
- AuthChallenge, AuthChallengeSolution, ClientConnectError, ClientRequest, ClientResponse,
- client_connect_error::Code as ConnectErrorCode,
+ AuthChallenge, AuthChallengeSolution, AuthOk, ClientConnectError, ClientRequest,
+ ClientResponse, client_connect_error::Code as ConnectErrorCode,
client_request::Payload as ClientRequestPayload,
client_response::Payload as ClientResponsePayload,
},
@@ -26,6 +26,25 @@ use crate::{
use super::session::ClientSession;
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct ClientId(i32);
+
+impl ClientId {
+ pub fn new(raw: i32) -> Self {
+ Self(raw)
+ }
+
+ pub fn as_i32(self) -> i32 {
+ self.0
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+struct ClientNonceState {
+ client_id: ClientId,
+ nonce: i32,
+}
+
#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq)]
pub enum Error {
#[error("Unexpected message payload")]
@@ -63,7 +82,7 @@ pub enum ApproveError {
async fn get_nonce(
db: &db::DatabasePool,
pubkey: &VerifyingKey,
-) -> Result