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                        // Token is valid, proceed with request
52                        inner.call(req).await
53                    }
54                    Err(_) => {
55                        // Invalid token
56                        Err(CoreError::BadRequest("Invalid token".to_string()))
57                    }
58                }
59            } else {
60                // No token provided
61                Err(CoreError::BadRequest("Missing authorization header".to_string()))
62            }
63        })
64    }
65}
66
67/// Layer for Auth middleware
68pub struct AuthLayer {
69    secret: String,
70}
71
72impl AuthLayer {
73    pub fn new(secret: String) -> Self {
74        Self { secret }
75    }
76}
77
78impl<S> Layer<S> for AuthLayer {
79    type Service = AuthMiddleware<S>;
80
81    fn layer(&self, inner: S) -> Self::Service {
82        AuthMiddleware::new(inner, self.secret.clone())
83    }
84}