next_web_dev/security/
request_auth_middleware.rs

1use axum::{
2    extract::{Request, State},
3    http::header,
4    middleware::Next,
5    response::Response,
6    // Extension,
7};
8use next_web_common::response::api_response::ApiResponse;
9// use tracing::info;
10
11use super::{authorization_service::AuthorizationService, login_type::LoginType};
12use crate::{
13    manager::user_authorization_manager::UserAuthorizationManager, util::token_util::TokenUtil,
14};
15
16async fn request_auth_middleware<T: AuthorizationService<Vec<String>> + Clone>(
17    State(user_auth_manager): State<UserAuthorizationManager<T>>,
18    mut req: Request,
19    next: Next,
20) -> Result<Response, ApiResponse<String>> {
21    let login_type = LoginType::default();
22    // do something with `state` and `request`...
23    let token = req
24        .headers()
25        .get(header::AUTHORIZATION)
26        .and_then(|header| header.to_str().ok())
27        .ok_or(ApiResponse::fail(
28            "Authorization header not found".into(),
29        ))
30        .map(|token| token.replace("Bearer ", ""))?;
31
32    // local (check if the token is valid)
33    let user_info = TokenUtil::decode(&token).map_err(|e| ApiResponse::fail(e.to_string()))?;
34
35    // service (check if the token is valid)
36    if !user_auth_manager.verify_token(&token, &login_type).await {
37        return Err(ApiResponse::fail("Invalid token".into()));
38    }
39
40    if let Some(auth_group) = user_auth_manager.get_permission(req.method(), req.uri().path()) {
41        // check if the user is authorized to access the resource
42        if !user_auth_manager
43            .pre_authorize(user_info.user_id(), auth_group, &login_type)
44            .await
45        {
46            return Err(ApiResponse::fail("Unauthorized access".into()));
47        }
48    }
49    // set the user info in the request
50    req.extensions_mut().insert(user_info);
51
52    // check if the user is authorized to access the resource
53    Ok(next.run(req).await)
54}