feat: implement basic auth in middleware
parent
993e58babf
commit
22e01d10dc
|
@ -1,7 +1,10 @@
|
||||||
use axum::{
|
use axum::{
|
||||||
extract::{Path, State},
|
extract::{Path, Request, State},
|
||||||
|
http::StatusCode,
|
||||||
|
middleware::Next,
|
||||||
|
response::{IntoResponse, Response},
|
||||||
routing::post,
|
routing::post,
|
||||||
Router,
|
RequestExt, Router,
|
||||||
};
|
};
|
||||||
use axum_extra::{
|
use axum_extra::{
|
||||||
extract::{
|
extract::{
|
||||||
|
@ -69,7 +72,7 @@ async fn post_logout(
|
||||||
|
|
||||||
tokio::task::spawn_blocking(move || {
|
tokio::task::spawn_blocking(move || {
|
||||||
if let Some(session) = Session::by_id(&ctx.pool, session_id)? {
|
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
|
// The requested user to logout should be the same as the one linked to the session
|
||||||
// ID
|
// ID
|
||||||
|
@ -90,3 +93,74 @@ async fn post_logout(
|
||||||
Ok(jar)
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue