Skip to main content

github_mcp/auth/strategies/
api_key.rs

1// GitHub v3 REST API MCP server — generated by mcpify. Do not hand-edit.
2
3use async_trait::async_trait;
4
5use super::super::auth_manager::header_location_for;
6use super::super::auth_strategy::{AuthConfig, AuthStrategy, Credentials};
7use super::super::errors::AuthError;
8use crate::core::config_schema::AuthMethod;
9
10#[derive(Debug, Default)]
11pub struct ApiKeyStrategy;
12
13#[async_trait]
14impl AuthStrategy for ApiKeyStrategy {
15    async fn authenticate(&self, config: &AuthConfig) -> anyhow::Result<Credentials> {
16        let api_key = config
17            .get("api_key")
18            .ok_or_else(|| AuthError::MissingCredentials("api_key".to_string()))?;
19
20        let mut credentials = Credentials::new();
21        credentials.insert("api_key".to_string(), api_key.clone());
22        // Carry the scheme's real configured header name (e.g.
23        // `X-Octopus-ApiKey`) through so `AuthManager::apply_auth_headers`
24        // uses it instead of falling back to the generic `X-Api-Key`
25        // literal — same header name the HTTP-transport extractor already
26        // uses via `header_location_for`.
27        let (_, header_name) = header_location_for(AuthMethod::ApiKey);
28        credentials.insert("request_header_name".to_string(), header_name.to_string());
29        Ok(credentials)
30    }
31
32    fn validate_credentials(&self, credentials: &Credentials) -> bool {
33        credentials
34            .get("api_key")
35            .is_some_and(|key| !key.is_empty())
36    }
37}
38
39#[cfg(test)]
40mod tests {
41    use super::*;
42
43    #[tokio::test]
44    async fn carries_the_configured_api_key_through() {
45        let strategy = ApiKeyStrategy;
46        let config = AuthConfig::from([("api_key".to_string(), "abc123".to_string())]);
47        let credentials = strategy.authenticate(&config).await.unwrap();
48        assert_eq!(credentials.get("api_key").unwrap(), "abc123");
49    }
50
51    #[tokio::test]
52    async fn rejects_a_config_missing_the_api_key() {
53        let strategy = ApiKeyStrategy;
54        assert!(strategy.authenticate(&AuthConfig::new()).await.is_err());
55    }
56
57    #[test]
58    fn rejects_an_empty_api_key_as_invalid() {
59        let strategy = ApiKeyStrategy;
60        let credentials = Credentials::from([("api_key".to_string(), String::new())]);
61        assert!(!strategy.validate_credentials(&credentials));
62    }
63}