objectstore_server/extractors/
service.rs1use axum::extract::FromRequestParts;
2use axum::http::{header, request::Parts};
3
4use crate::auth::{AuthAwareService, AuthContext};
5use crate::endpoints::common::ApiError;
6use crate::state::ServiceState;
7
8const BEARER_PREFIX: &str = "Bearer ";
9
10impl FromRequestParts<ServiceState> for AuthAwareService {
11 type Rejection = ApiError;
12
13 async fn from_request_parts(
14 parts: &mut Parts,
15 state: &ServiceState,
16 ) -> Result<Self, Self::Rejection> {
17 let encoded_token = parts
18 .headers
19 .get(header::AUTHORIZATION)
20 .and_then(|v| v.to_str().ok())
21 .and_then(strip_bearer);
22
23 let enforce = state.config.auth.enforce;
24 let auth_result = AuthContext::from_encoded_jwt(encoded_token, &state.key_directory)
26 .inspect_err(|err| err.log(None, None, enforce));
27
28 let auth_context = match enforce {
32 true => Some(auth_result?),
33 false => auth_result.ok(),
34 };
35
36 AuthAwareService::new(
37 state.service.clone(),
38 auth_context,
39 state.config.auth.enforce,
40 )
41 }
42}
43
44fn strip_bearer(header_value: &str) -> Option<&str> {
45 let (prefix, tail) = header_value.split_at_checked(BEARER_PREFIX.len())?;
46 if prefix.eq_ignore_ascii_case(BEARER_PREFIX) {
47 Some(tail)
48 } else {
49 None
50 }
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56
57 #[test]
58 fn test_strip_bearer() {
59 assert_eq!(strip_bearer("Bearer tokenvalue"), Some("tokenvalue"));
61 assert_eq!(strip_bearer("bearer tokenvalue"), Some("tokenvalue"));
62 assert_eq!(strip_bearer("BEARER tokenvalue"), Some("tokenvalue"));
63
64 assert_eq!(strip_bearer("Token tokenvalue"), None);
66 assert_eq!(strip_bearer("Bearer"), None);
67
68 assert_eq!(strip_bearer("Bearer⚠️tokenvalue"), None);
70 }
71}