objectstore_server/extractors/
service.rs

1use 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 inner = state.service.clone();
18        if !state.config.auth.enforce {
19            return Ok(AuthAwareService::new(inner, None));
20        }
21
22        let encoded_token = parts
23            .headers
24            .get(header::AUTHORIZATION)
25            .and_then(|v| v.to_str().ok())
26            .and_then(strip_bearer);
27
28        let context = AuthContext::from_encoded_jwt(encoded_token, &state.key_directory)
29            .inspect_err(|err| tracing::debug!("Authorization rejected: `{:?}`", err))?;
30
31        Ok(AuthAwareService::new(state.service.clone(), Some(context)))
32    }
33}
34
35fn strip_bearer(header_value: &str) -> Option<&str> {
36    let (prefix, tail) = header_value.split_at_checked(BEARER_PREFIX.len())?;
37    if prefix.eq_ignore_ascii_case(BEARER_PREFIX) {
38        Some(tail)
39    } else {
40        None
41    }
42}
43
44#[cfg(test)]
45mod tests {
46    use super::*;
47
48    #[test]
49    fn test_strip_bearer() {
50        // Prefix matches
51        assert_eq!(strip_bearer("Bearer tokenvalue"), Some("tokenvalue"));
52        assert_eq!(strip_bearer("bearer tokenvalue"), Some("tokenvalue"));
53        assert_eq!(strip_bearer("BEARER tokenvalue"), Some("tokenvalue"));
54
55        // Prefix doesn't match
56        assert_eq!(strip_bearer("Token tokenvalue"), None);
57        assert_eq!(strip_bearer("Bearer"), None);
58
59        // No character boundary at end of expected prefix
60        assert_eq!(strip_bearer("Bearer⚠️tokenvalue"), None);
61    }
62}