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
+23 -39
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()
.typed_get::<Authorization<Bearer>>() {
Some(header) => header,
None => return Ok(common_response(
StatusCode::UNAUTHORIZED,
"Invalid or missing authorization token",
)),
};
// Try synchronous email extraction first (for internal JWT tokens) let token = auth_header.token();
let email = match extract_email(headers) {
Some(email) => email,
None => {
// If sync extraction fails, try async (for Google tokens)
match extract_email_async(headers).await {
Some(email) => email,
None => {
return Ok(common_response(
StatusCode::UNAUTHORIZED,
"Invalid or expired token",
));
}
}
}
};
let repository = UsersRepository::new(&state); let claims = match decode_access_token(token) {
let user: Option<UsersDetailQueryDto> = Ok(token_data) => token_data.claims,
match repository.query_user_by_email(email).await { Err(_) => return Ok(common_response(
Ok(user) => Some(user), StatusCode::UNAUTHORIZED,
Err(err) => { "Invalid or expired token",
return Ok(common_response( )),
StatusCode::INTERNAL_SERVER_ERROR, };
&err.to_string(),
)); req.extensions_mut().insert(claims);
}
};
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)
} }