feat: implement basic auth in middleware

episode-actions
Jef Roosens 2025-02-23 21:02:42 +01:00
parent 993e58babf
commit 22e01d10dc
No known key found for this signature in database
GPG Key ID: 21FD3D77D56BAF49
1 changed files with 77 additions and 3 deletions

View File

@ -1,7 +1,10 @@
use axum::{
extract::{Path, State},
extract::{Path, Request, State},
http::StatusCode,
middleware::Next,
response::{IntoResponse, Response},
routing::post,
Router,
RequestExt, Router,
};
use axum_extra::{
extract::{
@ -69,7 +72,7 @@ async fn post_logout(
tokio::task::spawn_blocking(move || {
if let Some(session) = Session::by_id(&ctx.pool, session_id)? {
let user = session.user(&ctx.pool)?;
let user = session.user(&ctx.pool)?.ok_or(AppError::NotFound)?;
// The requested user to logout should be the same as the one linked to the session
// ID
@ -90,3 +93,74 @@ async fn post_logout(
Ok(jar)
}
}
/// This middleware accepts
pub async fn auth_middleware(State(ctx): State<Context>, mut req: Request, next: Next) -> Response {
// SAFETY: this extractor's error type is Infallible
let jar: CookieJar = req.extract_parts().await.unwrap();
tracing::debug!("{:?}", jar);
let mut auth_user = None;
let mut new_session_id = None;
if let Some(session_id) = jar
.get(SESSION_ID_COOKIE)
.and_then(|c| c.value().parse::<i64>().ok())
{
match tokio::task::spawn_blocking(move || Session::user_from_id(&ctx.pool, session_id))
.await
.unwrap()
.map_err(AppError::Db)
{
Ok(user) => {
auth_user = user;
}
Err(err) => {
return err.into_response();
}
};
} else if let Ok(auth) = req
.extract_parts::<TypedHeader<Authorization<Basic>>>()
.await
{
match tokio::task::spawn_blocking(move || {
let user = User::by_username(&ctx.pool, auth.username())?.ok_or(AppError::NotFound)?;
if user.verify_password(auth.password()) {
Ok((Session::new_for_user(&ctx.pool, user.id)?, user))
} else {
Err(AppError::Unauthorized)
}
})
.await
.unwrap()
{
Ok((session, user)) => {
auth_user = Some(user);
new_session_id = Some(session.id);
}
Err(err) => {
return err.into_response();
}
}
}
if let Some(user) = auth_user {
req.extensions_mut().insert(user);
let res = next.run(req).await;
if let Some(session_id) = new_session_id {
(
jar.add(
Cookie::build((SESSION_ID_COOKIE, session_id.to_string()))
.expires(Expiration::Session),
),
res,
)
.into_response()
} else {
res
}
} else {
StatusCode::UNAUTHORIZED.into_response()
}
}