1use crate::router::{Handler, HandlerObj, ResponseFuture};
16use crate::web::response;
17
18use futures::future::ok;
19use hyper::header::{HeaderValue, AUTHORIZATION, WWW_AUTHENTICATE};
20use hyper::{Body, Request, Response, StatusCode};
21use ring::constant_time::verify_slices_are_equal;
22
23lazy_static! {
24 pub static ref EPIC_BASIC_REALM: HeaderValue =
25 HeaderValue::from_str("Basic realm=EpicAPI").unwrap();
26 pub static ref EPIC_FOREIGN_BASIC_REALM: HeaderValue =
27 HeaderValue::from_str("Basic realm=EpicForeignAPI").unwrap();
28}
29
30pub struct BasicAuthMiddleware {
32 api_basic_auth: String,
33 basic_realm: &'static HeaderValue,
34 ignore_uri: Option<String>,
35}
36
37impl BasicAuthMiddleware {
38 pub fn new(
39 api_basic_auth: String,
40 basic_realm: &'static HeaderValue,
41 ignore_uri: Option<String>,
42 ) -> BasicAuthMiddleware {
43 BasicAuthMiddleware {
44 api_basic_auth,
45 basic_realm,
46 ignore_uri,
47 }
48 }
49}
50
51impl Handler for BasicAuthMiddleware {
52 fn call(
53 &self,
54 req: Request<Body>,
55 mut handlers: Box<dyn Iterator<Item = HandlerObj>>,
56 ) -> ResponseFuture {
57 let next_handler = match handlers.next() {
58 Some(h) => h,
59 None => return response(StatusCode::INTERNAL_SERVER_ERROR, "no handler found"),
60 };
61 if req.method().as_str() == "OPTIONS" {
62 return next_handler.call(req, handlers);
63 }
64 if let Some(u) = self.ignore_uri.as_ref() {
65 if req.uri().path() == u {
66 return next_handler.call(req, handlers);
67 }
68 }
69 if req.headers().contains_key(AUTHORIZATION)
70 && verify_slices_are_equal(
71 req.headers()[AUTHORIZATION].as_bytes(),
72 &self.api_basic_auth.as_bytes(),
73 )
74 .is_ok()
75 {
76 next_handler.call(req, handlers)
77 } else {
78 unauthorized_response(&self.basic_realm)
80 }
81 }
82}
83
84pub struct BasicAuthURIMiddleware {
86 api_basic_auth: String,
87 basic_realm: &'static HeaderValue,
88 target_uri: String,
89}
90
91impl BasicAuthURIMiddleware {
92 pub fn new(
93 api_basic_auth: String,
94 basic_realm: &'static HeaderValue,
95 target_uri: String,
96 ) -> BasicAuthURIMiddleware {
97 BasicAuthURIMiddleware {
98 api_basic_auth,
99 basic_realm,
100 target_uri,
101 }
102 }
103}
104
105impl Handler for BasicAuthURIMiddleware {
106 fn call(
107 &self,
108 req: Request<Body>,
109 mut handlers: Box<dyn Iterator<Item = HandlerObj>>,
110 ) -> ResponseFuture {
111 let next_handler = match handlers.next() {
112 Some(h) => h,
113 None => return response(StatusCode::INTERNAL_SERVER_ERROR, "no handler found"),
114 };
115 if req.method().as_str() == "OPTIONS" {
116 return next_handler.call(req, handlers);
117 }
118 if req.uri().path() == self.target_uri {
119 if req.headers().contains_key(AUTHORIZATION)
120 && verify_slices_are_equal(
121 req.headers()[AUTHORIZATION].as_bytes(),
122 &self.api_basic_auth.as_bytes(),
123 )
124 .is_ok()
125 {
126 next_handler.call(req, handlers)
127 } else {
128 unauthorized_response(&self.basic_realm)
130 }
131 } else {
132 next_handler.call(req, handlers)
133 }
134 }
135}
136
137fn unauthorized_response(basic_realm: &HeaderValue) -> ResponseFuture {
138 let response = Response::builder()
139 .status(StatusCode::UNAUTHORIZED)
140 .header(WWW_AUTHENTICATE, basic_realm)
141 .body(Body::empty())
142 .unwrap();
143 Box::pin(ok(response))
144}