Skip to main content

oxidite_auth/
middleware.rs

1use oxidite_core::{OxiditeRequest, OxiditeResponse, Error as CoreError};
2use tower::{Service, Layer};
3use std::task::{Context, Poll};
4use std::future::Future;
5use std::pin::Pin;
6use crate::verify_token;
7
8/// Auth middleware that validates JWT tokens
9#[derive(Clone)]
10pub struct AuthMiddleware<S> {
11    inner: S,
12    secret: String,
13}
14
15impl<S> AuthMiddleware<S> {
16    pub fn new(inner: S, secret: String) -> Self {
17        Self { inner, secret }
18    }
19}
20
21impl<S> Service<OxiditeRequest> for AuthMiddleware<S>
22where
23    S: Service<OxiditeRequest, Response = OxiditeResponse, Error = CoreError> + Clone + Send + 'static,
24    S::Future: Send + 'static,
25{
26    type Response = S::Response;
27    type Error = S::Error;
28    type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
29
30    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
31        self.inner.poll_ready(cx)
32    }
33
34    fn call(&mut self, req: OxiditeRequest) -> Self::Future {
35        // Extract Authorization header before moving req
36        let token = req
37            .headers()
38            .get("authorization")
39            .and_then(|h| h.to_str().ok())
40            .and_then(|h| h.strip_prefix("Bearer "))
41            .map(|s| s.to_string());
42
43        let secret = self.secret.clone();
44        let mut inner = self.inner.clone();
45
46        Box::pin(async move {
47            // Verify token
48            if let Some(token_str) = token {
49                match verify_token(&token_str, &secret) {
50                    Ok(claims) => {
51                        let mut req = req;
52                        req.extensions_mut().insert(claims.clone());
53                        if let Ok(user_id) = claims.sub.parse::<i64>() {
54                            req.extensions_mut().insert(user_id);
55                        }
56                        // Token is valid, proceed with request
57                        inner.call(req).await
58                    }
59                    Err(_) => {
60                        // Invalid token
61                        Err(CoreError::Unauthorized("Invalid token".to_string()))
62                    }
63                }
64            } else {
65                // No token provided
66                Err(CoreError::Unauthorized("Missing authorization header".to_string()))
67            }
68        })
69    }
70}
71
72/// Layer for Auth middleware
73pub struct AuthLayer {
74    secret: String,
75}
76
77impl AuthLayer {
78    pub fn new(secret: String) -> Self {
79        Self { secret }
80    }
81}
82
83impl<S> Layer<S> for AuthLayer {
84    type Service = AuthMiddleware<S>;
85
86    fn layer(&self, inner: S) -> Self::Service {
87        AuthMiddleware::new(inner, self.secret.clone())
88    }
89}