use std::sync::Arc;
use axum::{
extract::Request,
http::StatusCode,
middleware::Next,
response::{IntoResponse, Response},
};
use super::verifier::JwtVerifier;
pub async fn jwt_auth_middleware(
axum::extract::State(verifier): axum::extract::State<Arc<JwtVerifier>>,
req: Request,
next: Next,
) -> Response {
let path = req.uri().path().to_string();
let token = match req
.headers()
.get("authorization")
.and_then(|v| v.to_str().ok())
.and_then(|v| v.strip_prefix("Bearer "))
{
Some(t) => t.to_string(),
None => {
return (
StatusCode::UNAUTHORIZED,
"Missing or malformed Authorization header (expected: Bearer <token>)",
)
.into_response();
}
};
let claims = match verifier.verify(&token) {
Ok(c) => c,
Err(e) => {
return (StatusCode::UNAUTHORIZED, e.to_string()).into_response();
}
};
let required = verifier.required_scopes_for_path(&path);
if !required.is_empty() {
let user_scopes = verifier.scopes_from_claims(&claims);
for req_scope in required {
if !user_scopes.contains(req_scope) {
return (
StatusCode::FORBIDDEN,
format!("Insufficient scope: missing {}", req_scope.as_str()),
)
.into_response();
}
}
}
next.run(req).await
}