actix_web_security/authentication/
middleware.rs1use std::cell::RefCell;
4use std::future::{self, Future, Ready};
5use std::pin::Pin;
6use std::rc::Rc;
7use std::sync::Arc;
8use std::task::{Context, Poll};
9
10use actix_web::dev::{Service, ServiceRequest, ServiceResponse, Transform};
11use actix_web::Error;
12
13use crate::authentication::endpoint_matcher::EndpointMatcher;
14use crate::authentication::error::error_type::AuthenticationError;
15use crate::authentication::scheme::header_extractor::AuthorizationHeaderExtractor;
16use crate::authentication::ProviderManager;
17use crate::user_details::attachment::UserDetailsRequestAttachmentHelper;
18
19pub struct HttpAuthenticationMiddleware<T, U>
24where
25 T: AuthorizationHeaderExtractor + Clone,
26 U: EndpointMatcher + Clone,
27{
28 authorization_extractor: Box<T>,
29 provider_manager: ProviderManager,
30 endpoint_matcher: Box<U>,
31}
32
33impl<T: AuthorizationHeaderExtractor + Clone, U: EndpointMatcher + Clone>
34 HttpAuthenticationMiddleware<T, U>
35{
36 pub fn new(
40 provider_manager: ProviderManager,
41 authorization_extractor: Box<T>,
42 endpoint_matcher: Box<U>,
43 ) -> HttpAuthenticationMiddleware<T, U> {
44 HttpAuthenticationMiddleware {
45 authorization_extractor,
46 provider_manager,
47 endpoint_matcher,
48 }
49 }
50}
51
52impl<S, B, T, U> Transform<S> for HttpAuthenticationMiddleware<T, U>
53where
54 T: AuthorizationHeaderExtractor + Clone + 'static,
55 U: EndpointMatcher + Clone,
56 S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error> + 'static,
57{
58 type Request = ServiceRequest;
59 type Response = ServiceResponse<B>;
60 type Error = Error;
61 type Transform = HttpAuthenticationService<S, T, U>;
62 type InitError = ();
63 type Future = Ready<Result<Self::Transform, Self::InitError>>;
64
65 fn new_transform(&self, service: S) -> Self::Future {
66 let service = Rc::new(RefCell::new(service));
67 let provider_manager = Arc::new(self.provider_manager.clone());
68 let authorization_extractor = Arc::new(self.authorization_extractor.clone());
69 let endpoint_matcher = Arc::new(self.endpoint_matcher.clone());
70 future::ready(Ok(HttpAuthenticationService {
71 service,
72 provider_manager,
73 authorization_extractor,
74 endpoint_matcher,
75 }))
76 }
77}
78
79pub struct HttpAuthenticationService<
81 S,
82 T: AuthorizationHeaderExtractor + Clone,
83 U: EndpointMatcher + Clone,
84> {
85 service: Rc<RefCell<S>>,
86 provider_manager: Arc<ProviderManager>,
87 authorization_extractor: Arc<Box<T>>,
88 endpoint_matcher: Arc<Box<U>>,
89}
90
91impl<S, B, T, U> Service for HttpAuthenticationService<S, T, U>
92where
93 U: EndpointMatcher + Clone,
94 T: AuthorizationHeaderExtractor + Clone + 'static,
95 S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error> + 'static,
96{
97 type Request = ServiceRequest;
98 type Response = ServiceResponse<B>;
99 type Error = Error;
100 type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Error>>>>;
101
102 fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
103 self.service.poll_ready(cx)
104 }
105
106 fn call(&mut self, req: Self::Request) -> Self::Future {
107 let service = Rc::clone(&self.service);
108 let handle_request = self.endpoint_matcher.do_match(&req);
109
110 if handle_request {
111 let authorization_extractor = Arc::clone(&self.authorization_extractor);
112 let provider_manager = Arc::clone(&self.provider_manager);
113 Box::pin(async move {
114 let error: Option<AuthenticationError>;
115
116 let extracted_token = authorization_extractor.extract_token(&req.headers()).await;
117 match extracted_token {
118 Ok(token) => {
119 let authentication_result = provider_manager.authenticate(&token).await;
120 match authentication_result {
121 Ok(result) => {
122 req.attach(result);
123 error = None;
124 }
125 Err(e) => error = Some(e),
126 };
127 }
128 Err(e) => error = Some(e),
129 };
130
131 match error {
132 Some(e) => Err(e.into()),
133 None => {
134 let fut = service.borrow_mut().call(req);
135 let res = fut.await?;
136
137 Ok(res)
138 }
139 }
140 })
141 } else {
142 Box::pin(async move {
143 let fut = service.borrow_mut().call(req);
144 let res = fut.await?;
145
146 Ok(res)
147 })
148 }
149 }
150}