Skip to main content

pacenotes_server/auth/
bearer_header.rs

1/// The raw token from `Authorization: Bearer <token>`, if well-formed.
2/// It is a credential: never log it or put it in an error.
3pub fn bearer_from_headers(headers: &axum::http::HeaderMap) -> Option<String> {
4    let value = headers.get(pacenotes_shared::AUTH_HEADER)?.to_str().ok()?;
5    let token = value.strip_prefix(pacenotes_shared::BEARER_PREFIX)?.trim();
6    if token.is_empty() {
7        return None;
8    }
9    Some(token.to_string())
10}
11
12#[cfg(test)]
13mod tests {
14    fn headers(authorization: &str) -> axum::http::HeaderMap {
15        let mut headers = axum::http::HeaderMap::new();
16        headers.insert(
17            axum::http::header::AUTHORIZATION,
18            axum::http::HeaderValue::from_str(authorization).unwrap(),
19        );
20        headers
21    }
22
23    #[test]
24    fn bearer_header_parsing() {
25        for (authorization, expected) in [
26            ("Bearer pcn_abc", Some("pcn_abc")),
27            ("Bearer  pcn_abc  ", Some("pcn_abc")),
28            ("pcn_abc", None),
29            ("Basic pcn_abc", None),
30            ("Bearer   ", None),
31        ] {
32            assert_eq!(
33                super::bearer_from_headers(&headers(authorization)).as_deref(),
34                expected,
35                "{authorization:?}"
36            );
37        }
38        assert!(super::bearer_from_headers(&axum::http::HeaderMap::new()).is_none());
39    }
40}