Skip to main content

nextcloud_auth/bearer/
bearer_auth.rs

1use std::fmt;
2
3use nextcloud_sdk_core::{AuthProvider, Headers};
4
5use super::BearerToken;
6
7/// Applies an OAuth2 access token as an `Authorization: Bearer` header.
8#[derive(Clone)]
9pub struct BearerAuth {
10    token: BearerToken,
11}
12
13impl BearerAuth {
14    /// Builds a provider from a token string.
15    pub fn new(token: impl Into<String>) -> Self {
16        Self {
17            token: BearerToken::new(token),
18        }
19    }
20
21    /// Builds a provider from an already-wrapped token.
22    pub const fn from_token(token: BearerToken) -> Self {
23        Self { token }
24    }
25
26    /// The token this provider applies.
27    pub const fn token(&self) -> &BearerToken {
28        &self.token
29    }
30
31    /// The header value sent to the server.
32    pub fn header_value(&self) -> String {
33        format!("Bearer {}", self.token.expose())
34    }
35}
36
37impl AuthProvider for BearerAuth {
38    fn authenticate(&self, headers: &mut Headers) {
39        headers.set("Authorization", self.header_value());
40    }
41}
42
43impl fmt::Debug for BearerAuth {
44    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45        f.debug_struct("BearerAuth")
46            .field("token", &self.token)
47            .finish()
48    }
49}
50
51#[cfg(test)]
52mod tests {
53    use nextcloud_sdk_core::{AuthProvider, Header, Headers};
54
55    use super::BearerAuth;
56
57    fn bearer() -> BearerAuth {
58        BearerAuth::new("access-token")
59    }
60
61    #[test]
62    fn header_value_prefixes_the_token_with_bearer() {
63        assert_eq!(bearer().header_value(), "Bearer access-token");
64    }
65
66    #[test]
67    fn authenticate_sets_the_authorization_header() {
68        let mut headers = Headers::new();
69        bearer().authenticate(&mut headers);
70        assert_eq!(headers.get("Authorization"), Some("Bearer access-token"));
71    }
72
73    #[test]
74    fn authenticate_replaces_an_existing_authorization_header() {
75        let mut headers = Headers::new().with(Header::new("Authorization", "Basic c3RhbGU="));
76        bearer().authenticate(&mut headers);
77        assert_eq!(headers.len(), 1);
78        assert_eq!(headers.get("Authorization"), Some("Bearer access-token"));
79    }
80
81    #[test]
82    fn debug_redacts_the_token() {
83        let rendered = format!("{:?}", bearer());
84        assert!(!rendered.contains("access-token"));
85        assert!(rendered.contains("<redacted>"));
86    }
87}