Skip to main content

agp_config/auth/
bearer.rs

1// Copyright AGNTCY Contributors (https://github.com/agntcy)
2// SPDX-License-Identifier: Apache-2.0
3
4use serde::Deserialize;
5use tower_http::auth::{AddAuthorizationLayer, require_authorization::Bearer};
6use tower_http::validate_request::ValidateRequestHeaderLayer;
7
8use super::{AuthError, ClientAuthenticator, ServerAuthenticator};
9use crate::opaque::OpaqueString;
10
11#[derive(Debug, Deserialize, Clone, PartialEq)]
12pub struct Config {
13    token: OpaqueString,
14}
15
16impl Default for Config {
17    fn default() -> Self {
18        Config {
19            token: OpaqueString::new("token"),
20        }
21    }
22}
23
24impl Config {
25    /// Create a new Config
26    pub fn new(token: &str) -> Self {
27        Config {
28            token: OpaqueString::new(token),
29        }
30    }
31
32    /// Get the token
33    pub fn token(&self) -> &OpaqueString {
34        &self.token
35    }
36}
37
38impl ClientAuthenticator for Config {
39    // Associated types
40    type ClientLayer = AddAuthorizationLayer;
41
42    fn get_client_layer(&self) -> Result<Self::ClientLayer, AuthError> {
43        match self.token().as_ref() {
44            "" => Err(AuthError::ConfigError("token is empty".to_string())),
45            _ => Ok(AddAuthorizationLayer::bearer(self.token())),
46        }
47    }
48}
49
50impl<Response> ServerAuthenticator<Response> for Config
51where
52    Response: Default,
53{
54    // Associated types
55    type ServerLayer = ValidateRequestHeaderLayer<Bearer<Response>>;
56
57    fn get_server_layer(&self) -> Result<Self::ServerLayer, AuthError> {
58        Ok(ValidateRequestHeaderLayer::bearer(self.token()))
59    }
60}
61
62// tests
63#[cfg(test)]
64mod tests {
65    use tower::ServiceBuilder;
66    use tower_reqwest::HttpClientLayer;
67
68    use super::*;
69
70    #[test]
71    fn test_config() {
72        let token = OpaqueString::new("token");
73        let config = Config::new(&token);
74
75        assert_eq!(config.token(), &token);
76    }
77
78    #[tokio::test]
79    async fn test_authenticator() {
80        let token = OpaqueString::new("token");
81        let config = Config::new(&token);
82
83        let client_layer = config.get_client_layer().unwrap();
84        let server_layer: ValidateRequestHeaderLayer<Bearer<String>> =
85            config.get_server_layer().unwrap();
86
87        // Check that we can use the layers when building a service
88        let _ = ServiceBuilder::new().layer(server_layer);
89
90        let _ = ServiceBuilder::new()
91            .layer(HttpClientLayer)
92            .layer(client_layer);
93    }
94}