ferrox_security/
auth_middleware.rs1use axum::{
2 extract::State,
3 http::{Request, StatusCode, header},
4 middleware::Next,
5 response::Response,
6};
7use std::sync::Arc;
8use crate::{PasetoAuth, AuthPayload};
9
10pub async fn require_auth<B>(
13 State(auth_engine): State<Arc<PasetoAuth>>,
14 mut req: Request<B>,
15 next: Next,
16) -> Result<Response, StatusCode> {
17 let auth_header = req.headers().get(header::AUTHORIZATION)
18 .and_then(|value| value.to_str().ok())
19 .filter(|value| value.starts_with("Bearer "))
20 .map(|value| &value[7..]);
21
22 let token = match auth_header {
23 Some(token) => token,
24 None => return Err(StatusCode::UNAUTHORIZED),
25 };
26
27 match auth_engine.validate_token(token) {
28 Ok(payload) => {
29 req.extensions_mut().insert(payload.clone());
31
32 if let Ok(user_id_val) = header::HeaderValue::from_str(&payload.user_id) {
36 req.headers_mut().insert("x-ferrox-user-id", user_id_val);
37 }
38 if let Ok(role_val) = header::HeaderValue::from_str(&payload.role) {
39 req.headers_mut().insert("x-ferrox-user-role", role_val);
40 }
41
42 Ok(next.run(req).await)
43 }
44 Err(_) => Err(StatusCode::UNAUTHORIZED),
45 }
46}
47
48pub async fn require_role<B>(
51 req: Request<B>,
52 next: Next,
53 required_role: &str,
54) -> Result<Response, StatusCode> {
55 let auth_payload = req.extensions().get::<AuthPayload>();
57
58 match auth_payload {
59 Some(payload) if payload.role == required_role => {
60 Ok(next.run(req).await)
61 }
62 _ => Err(StatusCode::FORBIDDEN), }
64}