use crate::auth::jwt::{JWT, default_jwt};
use crate::conf;
use crate::error::ApiError;
use axum::body::Body;
use axum::http::{Request, Response, header};
use std::pin::Pin;
use std::sync::LazyLock;
use tower_http::auth::{AsyncAuthorizeRequest, AsyncRequireAuthorizationLayer};
static AUTH_LAYER: LazyLock<AsyncRequireAuthorizationLayer<JWTAuth>> =
LazyLock::new(|| AsyncRequireAuthorizationLayer::new(JWTAuth::new(default_jwt())));
#[derive(Debug, Clone)]
pub struct JWTAuth {
jwt: &'static JWT,
}
impl JWTAuth {
pub fn new(jwt: &'static JWT) -> Self {
Self { jwt }
}
}
impl AsyncAuthorizeRequest<Body> for JWTAuth {
type RequestBody = Body;
type ResponseBody = Body;
type Future = Pin<
Box<
dyn Future<Output = Result<Request<Self::RequestBody>, Response<Self::ResponseBody>>>
+ Send,
>,
>;
fn authorize(&mut self, mut request: Request<Body>) -> Self::Future {
let jwt = self.jwt;
Box::pin(async move {
let path = request.uri().path();
if conf::get().auth().ignored(path)? {
return Ok(request);
}
let token = request
.headers()
.get(header::AUTHORIZATION)
.map(|value| -> Result<_, ApiError> {
let token = value
.to_str()
.map_err(|_| {
ApiError::Unauthenticated(String::from("Authorization请求头无效"))
})?
.strip_prefix("Bearer ")
.ok_or_else(|| {
ApiError::Unauthenticated(String::from("Authorization请求头格式无效"))
})?;
Ok(token)
})
.transpose()?
.ok_or_else(|| {
ApiError::Unauthenticated(String::from("Authorization请求头缺失"))
})?;
let principal = jwt.decode(token).map_err(|err| ApiError::Internal(err))?;
request.extensions_mut().insert(principal);
Ok(request)
})
}
}
pub fn get_auth_layer() -> &'static AsyncRequireAuthorizationLayer<JWTAuth> {
&AUTH_LAYER
}