From 384d5147ed35799f7c2d8228258cd2488a913477 Mon Sep 17 00:00:00 2001 From: alemi Date: Mon, 25 Mar 2024 01:58:30 +0100 Subject: [PATCH] feat: initial auth extractor --- src/auth.rs | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 1 + 2 files changed, 53 insertions(+) create mode 100644 src/auth.rs diff --git a/src/auth.rs b/src/auth.rs new file mode 100644 index 0000000..2d40582 --- /dev/null +++ b/src/auth.rs @@ -0,0 +1,52 @@ +use axum::{extract::{FromRef, FromRequestParts}, http::{header::{self, HeaderValue, USER_AGENT}, request::Parts, StatusCode}}; +use sea_orm::{ColumnTrait, Condition, EntityTrait, QueryFilter}; + +use crate::{model, server::Context}; + +#[derive(Debug, Clone)] +pub enum Identity { + Anonymous, + User(String), + Server(String), +} + +pub struct AuthIdentity(pub Identity); + +#[axum::async_trait] +impl FromRequestParts for AuthIdentity +where + Context: FromRef, + S: Send + Sync, +{ + type Rejection = StatusCode; + + async fn from_request_parts(parts: &mut Parts, state: &S) -> Result { + let ctx = Context::from_ref(state); + let mut identity = Identity::Anonymous; + + let auth_header = parts + .headers + .get(header::AUTHORIZATION) + .map(|v| v.to_str().unwrap_or("")) + .unwrap_or(""); + + if auth_header.starts_with("Bearer ") { + match model::session::Entity::find_by_id(auth_header.replace("Bearer ", "")) + .filter(Condition::all().add(model::session::Column::Expires.gt(chrono::Utc::now()))) + .one(ctx.db()) + .await + { + Ok(Some(x)) => identity = Identity::User(x.actor), + Ok(None) => return Err(StatusCode::UNAUTHORIZED), + Err(e) => { + tracing::error!("failed querying user session: {e}"); + return Err(StatusCode::INTERNAL_SERVER_ERROR) + }, + } + } + + // TODO check and validate HTTP signature + + Ok(AuthIdentity(identity)) + } +} diff --git a/src/main.rs b/src/main.rs index b27ec40..e86cf31 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,6 +5,7 @@ pub mod activitypub; pub mod server; pub mod router; pub mod errors; +pub mod auth; use clap::{Parser, Subcommand}; use sea_orm::{ConnectOptions, Database, EntityTrait, IntoActiveModel};