clean up passkey login

This commit is contained in:
mbecker20
2025-09-26 15:49:14 -07:00
parent 7a2a54bec1
commit 2bc8a754be
2 changed files with 144 additions and 128 deletions
+64 -56
View File
@@ -93,7 +93,7 @@ impl PeripheryConnectionArgs<'_> {
/// to implement passkey support for backward compatibility
async fn handle_login(
handler: &mut super::WebsocketHandler<'_, TungsteniteWebsocket>,
// deprecated.
// for legacy auth
passkey: &str,
) -> anyhow::Result<()> {
// Get the required auth type
@@ -107,61 +107,7 @@ async fn handle_login(
// Noise auth
&[0] => handler.login::<ClientLoginFlow>().await,
// Passkey auth
&[1] => {
let res = async {
let mut passkey = if passkey.is_empty() {
core_config()
.passkey
.as_deref()
.context("Periphery requires passkey auth")?
.as_bytes()
.to_vec()
} else {
passkey.as_bytes().to_vec()
};
passkey.push(MessageState::Successful.as_byte());
handler
.socket
.send(passkey.into())
.await
.context("Failed to send passkey")?;
// Receive login state message and return based on value
let state_msg = handler.socket.recv_bytes().await.context(
"Failed to receive authentication state message",
)?;
let state = state_msg.last().context(
"Authentication state message did not contain state byte",
)?;
match MessageState::from_byte(*state) {
MessageState::Successful => anyhow::Ok(()),
_ => Err(deserialize_error_bytes(
&state_msg[..(state_msg.len() - 1)],
)),
}
}
.await;
if let Err(e) = res {
let mut bytes = serialize_error_bytes(&e);
bytes.push(MessageState::Failed.as_byte());
if let Err(e) = handler
.socket
.send(bytes.into())
.await
.context("Failed to send login failed to client")
{
// Log additional error
warn!("{e:#}");
}
// Close socket
let _ = handler.socket.close(None).await;
// Return the original error
Err(e)
} else {
Ok(())
}
}
&[1] => handle_passkey_login(handler, passkey).await,
other => {
return Err(anyhow!(
"Receieved invalid login type pattern: {other:?}"
@@ -170,6 +116,68 @@ async fn handle_login(
}
}
async fn handle_passkey_login(
handler: &mut super::WebsocketHandler<'_, TungsteniteWebsocket>,
// for legacy auth
passkey: &str,
) -> anyhow::Result<()> {
let res = async {
let mut passkey = if passkey.is_empty() {
core_config()
.passkey
.as_deref()
.context("Periphery requires passkey auth")?
.as_bytes()
.to_vec()
} else {
passkey.as_bytes().to_vec()
};
passkey.push(MessageState::Successful.as_byte());
handler
.socket
.send(passkey.into())
.await
.context("Failed to send passkey")?;
// Receive login state message and return based on value
let state_msg = handler
.socket
.recv_bytes()
.await
.context("Failed to receive authentication state message")?;
let state = state_msg.last().context(
"Authentication state message did not contain state byte",
)?;
match MessageState::from_byte(*state) {
MessageState::Successful => anyhow::Ok(()),
_ => Err(deserialize_error_bytes(
&state_msg[..(state_msg.len() - 1)],
)),
}
}
.await;
if let Err(e) = res {
let mut bytes = serialize_error_bytes(&e);
bytes.push(MessageState::Failed.as_byte());
if let Err(e) = handler
.socket
.send(bytes.into())
.await
.context("Failed to send login failed to client")
{
// Log additional error
warn!("{e:#}");
}
// Close socket
let _ = handler.socket.close(None).await;
// Return the original error
Err(e)
} else {
Ok(())
}
}
async fn connect_websocket(
url: &str,
) -> anyhow::Result<(TungsteniteWebsocket, HeaderValue)> {
+80 -72
View File
@@ -123,94 +123,102 @@ async fn handle_login(
match (&config.core_public_key, &config.passkeys) {
(Some(_), _) | (_, None) => {
// Send login type [0] (Noise auth)
handler
.socket
// Noise handshake auth: [0]
.send(Bytes::from_owner([0]))
.await
.context("Failed to send login type indicator")?;
handler.login::<ServerLoginFlow>().await
}
(None, Some(passkeys)) => {
warn!(
"Authenticating using Passkeys. Set 'core_public_key' (PERIPHERY_CORE_PUBLIC_KEY) instead to enhance security."
);
let res = async {
// Send login type
handler
.socket
// Passkey auth: [1]
.send(Bytes::from_owner([1]))
.await
.context("Failed to send login type indicator")?;
handle_passkey_login(handler, passkeys).await
}
}
}
// Receieve passkey
let bytes = handler
.socket
.recv_bytes()
.await
.context("Failed to receive passkey from Core")?;
let passkey = match MessageState::from_byte(
*bytes.last().context("passkey message is empty")?,
) {
MessageState::Successful => &bytes[..(bytes.len() - 1)],
_ => {
return Err(deserialize_error_bytes(
&bytes[..(bytes.len() - 1)],
));
}
};
async fn handle_passkey_login(
handler: &mut WebsocketHandler<'_, AxumWebsocket>,
passkeys: &[String],
) -> anyhow::Result<()> {
warn!(
"Authenticating using Passkeys. Set 'core_public_key' (PERIPHERY_CORE_PUBLIC_KEY) instead to enhance security."
);
let res = async {
// Send login type
handler
.socket
// Passkey auth: [1]
.send(Bytes::from_owner([1]))
.await
.context("Failed to send login type indicator")?;
if passkeys.iter().any(|expected_passkey| {
expected_passkey.as_bytes() == passkey
}) {
handler
.socket
.send(MessageState::Successful.into())
.await
.context("Failed to send login type indicator")?;
Ok(())
} else {
let e = anyhow!("Invalid passkey");
let mut bytes = serialize_error_bytes(&e);
bytes.push(MessageState::Failed.as_byte());
if let Err(e) = handler
.socket
.send(bytes.into())
.await
.context("Failed to send login failed")
{
// Log additional error
warn!("{e:#}");
// Close socket
let _ = handler.socket.close(None).await;
}
// Return the original error
Err(e)
}
// Receieve passkey
let bytes = handler
.socket
.recv_bytes()
.await
.context("Failed to receive passkey from Core")?;
let passkey = match MessageState::from_byte(
*bytes.last().context("passkey message is empty")?,
) {
MessageState::Successful => &bytes[..(bytes.len() - 1)],
_ => {
return Err(deserialize_error_bytes(
&bytes[..(bytes.len() - 1)],
));
}
.await;
if let Err(e) = res {
let mut bytes = serialize_error_bytes(&e);
bytes.push(MessageState::Failed.as_byte());
if let Err(e) = handler
.socket
.send(bytes.into())
.await
.context("Failed to send login failed to client")
{
// Log additional error
warn!("{e:#}");
}
};
if passkeys
.iter()
.any(|expected_passkey| expected_passkey.as_bytes() == passkey)
{
handler
.socket
.send(MessageState::Successful.into())
.await
.context("Failed to send login type indicator")?;
Ok(())
} else {
let e = anyhow!("Invalid passkey");
let mut bytes = serialize_error_bytes(&e);
bytes.push(MessageState::Failed.as_byte());
if let Err(e) = handler
.socket
.send(bytes.into())
.await
.context("Failed to send login failed")
{
// Log additional error
warn!("{e:#}");
// Close socket
let _ = handler.socket.close(None).await;
// Return the original error
Err(e)
} else {
Ok(())
}
// Return the original error
Err(e)
}
}
.await;
if let Err(e) = res {
let mut bytes = serialize_error_bytes(&e);
bytes.push(MessageState::Failed.as_byte());
if let Err(e) = handler
.socket
.send(bytes.into())
.await
.context("Failed to send login failed to client")
{
// Log additional error
warn!("{e:#}");
}
// Close socket
let _ = handler.socket.close(None).await;
// Return the original error
Err(e)
} else {
Ok(())
}
}
async fn guard_request_by_ip(