feat: initial work on validating http signatures

This commit is contained in:
əlemi 2024-03-25 05:12:49 +01:00
parent d0816a0f6a
commit 6ea4f06d54
Signed by: alemi
GPG key ID: A4895B84D311642C
2 changed files with 38 additions and 7 deletions

View file

@ -75,8 +75,8 @@ pub async fn post(
) -> Result<JsonLD<serde_json::Value>, StatusCode> { ) -> Result<JsonLD<serde_json::Value>, StatusCode> {
match auth { match auth {
Identity::Anonymous => Err(StatusCode::UNAUTHORIZED), Identity::Anonymous => Err(StatusCode::UNAUTHORIZED),
Identity::Server(_) => Err(StatusCode::NOT_IMPLEMENTED), Identity::Remote(_) => Err(StatusCode::NOT_IMPLEMENTED),
Identity::User(uid) => if ctx.uid(id) == uid { Identity::Local(uid) => if ctx.uid(id) == uid {
match activity.base_type() { match activity.base_type() {
None => Err(StatusCode::BAD_REQUEST), None => Err(StatusCode::BAD_REQUEST),
Some(BaseType::Link(_)) => Err(StatusCode::UNPROCESSABLE_ENTITY), Some(BaseType::Link(_)) => Err(StatusCode::UNPROCESSABLE_ENTITY),

View file

@ -6,8 +6,8 @@ use crate::{model, server::Context};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Identity { pub enum Identity {
Anonymous, Anonymous,
User(String), Local(String),
Server(String), Remote(String),
} }
pub struct AuthIdentity(pub Identity); pub struct AuthIdentity(pub Identity);
@ -36,7 +36,7 @@ where
.one(ctx.db()) .one(ctx.db())
.await .await
{ {
Ok(Some(x)) => identity = Identity::User(x.actor), Ok(Some(x)) => identity = Identity::Local(x.actor),
Ok(None) => return Err(StatusCode::UNAUTHORIZED), Ok(None) => return Err(StatusCode::UNAUTHORIZED),
Err(e) => { Err(e) => {
tracing::error!("failed querying user session: {e}"); tracing::error!("failed querying user session: {e}");
@ -45,8 +45,39 @@ where
} }
} }
// TODO check and validate HTTP signature if let Some(sig) = parts
.headers
.get("Signature")
.map(|v| v.to_str().unwrap_or(""))
{
// TODO load pub key of actor and decode+verify signature
let decoded = "asd".to_string();
let mut key_id = None;
let mut headers = None;
let mut signature = None;
for frag in decoded.split(',') {
if frag.starts_with("keyId=") {
key_id = Some(frag.replace("keyId=\"", ""));
key_id.as_mut().unwrap().pop();
}
if frag.starts_with("signature=") {
signature = Some(frag.replace("signature=\"", ""));
signature.as_mut().unwrap().pop();
}
if frag.starts_with("headers=") {
let mut h = frag.replace("headers=\"", "");
h.pop();
headers = Some(h.split(' ').map(|x| x.to_string()).collect::<Vec<String>>());
}
}
if key_id.is_none() || headers.is_none() || signature.is_none() {
tracing::warn!("malformed signature");
return Err(StatusCode::BAD_REQUEST);
}
}
Ok(AuthIdentity(identity)) Ok(AuthIdentity(identity))
} }
} }