Files
YANPM/apps/api/src/middlewares/require_auth.rs
2025-12-20 16:40:41 +08:00

71 lines
2.0 KiB
Rust

use std::sync::Arc;
use axum::{
extract::State,
http::{Request, StatusCode},
middleware::Next,
response::Response,
};
use axum_extra::extract::cookie::CookieJar;
use tracing::debug;
use uuid::Uuid;
use crate::{
errors::service_error::ServiceError, helpers::constants::JWT_COOKIE_NAME,
middlewares::request_info::RequestInfo, routes::AppState,
};
pub async fn require_auth(
cookies: CookieJar,
State(state): State<Arc<AppState>>,
req: Request<axum::body::Body>,
next: Next,
) -> Result<Response, StatusCode> {
// get jwt from cookies
let auth_service = &state.service.auth_state.authentication;
let token = if let Some(cookie) = cookies.get(JWT_COOKIE_NAME) {
cookie.value().to_string()
} else {
debug!("No JWT cookie found. cookies: {:?}", cookies);
return handle_unauthenticated().await;
};
// validate jwt
let is_valid = auth_service.is_valid_jwt(&token, None).await;
let user_id = match is_valid {
Ok(Some(claims)) => claims
.sub
.parse::<Uuid>()
.map_err(|_| StatusCode::UNAUTHORIZED)?,
Ok(None) => return handle_unauthenticated().await,
Err(err) => {
tracing::error!("Error validating JWT: {}", err);
return Err(StatusCode::INTERNAL_SERVER_ERROR);
}
};
// ensure user exists
if let Err(err) = state.service.user.get_user_by_id(user_id, None).await {
match err {
ServiceError::NotFound(_) => return handle_unauthenticated().await,
_ => {
tracing::error!("Error fetching user by ID: {}", err);
return Err(StatusCode::INTERNAL_SERVER_ERROR);
}
}
}
let mut req = req;
let user = req
.extensions_mut()
.get_or_insert_with(|| RequestInfo { user_id: None });
user.user_id = Some(user_id);
Ok(next.run(req).await)
}
async fn handle_unauthenticated() -> Result<Response, StatusCode> {
// TODO: log unauthenticated access attempts
Err(StatusCode::UNAUTHORIZED)
}