use axum::{ extract::FromRequestParts, http::{request::Parts, StatusCode}, }; use axum::async_trait; pub struct RequireAuth(pub crate::jwt::Claims); #[async_trait] impl FromRequestParts for RequireAuth where S: Send + Sync, { type Rejection = (StatusCode, &'static str); async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result { let auth_header = parts .headers .get("Authorization") .and_then(|value| value.to_str().ok()) .filter(|value| value.starts_with("Bearer ")); let token = match auth_header { Some(header) => header.trim_start_matches("Bearer "), None => return Err((StatusCode::UNAUTHORIZED, "Missing Bearer token")), }; let jwt_secret = std::env::var("JWT_SECRET").expect("JWT_SECRET must be set"); match crate::jwt::verify_access_token(token, &jwt_secret) { Ok(claims) => Ok(RequireAuth(claims)), Err(_) => Err((StatusCode::UNAUTHORIZED, "Invalid or expired token")), } } }