feat: Add axum-extra dependency and refactor auth middleware for improved token handling

This commit is contained in:
MythEclipse
2025-08-14 23:16:41 +07:00
parent 10dc869eaf
commit 01e20baa45
3 changed files with 27 additions and 41 deletions
Generated
+1
View File
@@ -2314,6 +2314,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"axum", "axum",
"axum-extra",
"axum-test", "axum-test",
"chrono", "chrono",
"futures", "futures",
+1
View File
@@ -9,6 +9,7 @@ imphnen-libs.workspace = true
imphnen-utils.workspace = true imphnen-utils.workspace = true
imphnen-entities.workspace = true imphnen-entities.workspace = true
axum.workspace = true axum.workspace = true
axum-extra.workspace = true
serde.workspace = true serde.workspace = true
serde_json.workspace = true serde_json.workspace = true
utoipa.workspace = true utoipa.workspace = true
+25 -41
View File
@@ -2,52 +2,36 @@ use axum::{
Extension, extract::Request, http::StatusCode, middleware::Next, Extension, extract::Request, http::StatusCode, middleware::Next,
response::Response, response::Response,
}; };
use imphnen_iam::{UsersDetailQueryDto, UsersRepository}; use imphnen_libs::{AppState, jsonwebtoken::decode_access_token};
use imphnen_libs::AppState; use imphnen_utils::common_response;
use imphnen_utils::{common_response, extract_email, extract_email_async}; use axum_extra::headers::{authorization::Bearer, Authorization, HeaderMapExt};
use std::convert::Infallible; use std::convert::Infallible;
pub async fn auth_middleware( pub async fn auth_middleware(
Extension(state): Extension<AppState>, Extension(_state): Extension<AppState>, // state is currently unused in this middleware
mut req: Request, mut req: Request,
next: Next, next: Next,
) -> Result<Response, Infallible> { ) -> Result<Response, Infallible> {
let headers = req.headers(); let auth_header = match req
.headers()
// Try synchronous email extraction first (for internal JWT tokens) .typed_get::<Authorization<Bearer>>() {
let email = match extract_email(headers) { Some(header) => header,
Some(email) => email, None => return Ok(common_response(
None => { StatusCode::UNAUTHORIZED,
// If sync extraction fails, try async (for Google tokens) "Invalid or missing authorization token",
match extract_email_async(headers).await { )),
Some(email) => email, };
None => {
return Ok(common_response( let token = auth_header.token();
StatusCode::UNAUTHORIZED,
"Invalid or expired token", let claims = match decode_access_token(token) {
)); Ok(token_data) => token_data.claims,
} Err(_) => return Ok(common_response(
} StatusCode::UNAUTHORIZED,
} "Invalid or expired token",
}; )),
};
let repository = UsersRepository::new(&state);
let user: Option<UsersDetailQueryDto> = req.extensions_mut().insert(claims);
match repository.query_user_by_email(email).await {
Ok(user) => Some(user),
Err(err) => {
return Ok(common_response(
StatusCode::INTERNAL_SERVER_ERROR,
&err.to_string(),
));
}
};
if user.is_none() {
return Ok(common_response(
StatusCode::UNAUTHORIZED,
"Unauthorized user",
));
}
req.extensions_mut().insert(user.unwrap());
Ok(next.run(req).await) Ok(next.run(req).await)
} }