hoprd_api/middleware/
preconditions.rs1use std::str::FromStr;
2
3use axum::{
4 extract::{OriginalUri, Request, State},
5 http::{
6 HeaderMap,
7 header::{AUTHORIZATION, HeaderName},
8 status::StatusCode,
9 },
10 middleware::Next,
11 response::IntoResponse,
12};
13
14use crate::{ApiErrorStatus, Auth, InternalState};
15
16pub(crate) async fn authenticate(
17 State(state): State<InternalState>,
18 _uri: OriginalUri,
19 headers: HeaderMap,
20 request: Request,
21 next: Next,
22) -> impl IntoResponse {
23 let auth = state.auth.clone();
24
25 let x_auth_header = HeaderName::from_str("x-auth-token").expect("Invalid header name: x-auth-token");
26
27 let is_authorized = match auth.as_ref() {
28 Auth::Token(expected_token) => {
29 let auth_headers = headers
30 .iter()
31 .filter_map(|(n, v)| {
32 (AUTHORIZATION.eq(n) || x_auth_header.eq(n))
33 .then_some((n, v.to_str().expect("Invalid header value")))
34 })
35 .collect::<Vec<_>>();
36
37 !auth_headers.is_empty()
39 && (auth_headers.contains(&(&AUTHORIZATION, &format!("Bearer {expected_token}")))
40 || auth_headers.contains(&(&x_auth_header, expected_token)))
41 }
42 Auth::None => true,
43 };
44
45 if !is_authorized {
46 return (StatusCode::UNAUTHORIZED, ApiErrorStatus::Unauthorized).into_response();
47 }
48
49 next.run(request).await
51}