From 7428ed2314c4d6e3e9aed6087150e8891963fb4a Mon Sep 17 00:00:00 2001 From: nutcas3 Date: Sat, 25 Apr 2026 03:42:42 +0300 Subject: [PATCH] feat: Add API key authentication support to charging-engine auth middleware - Add api_keys field to AuthConfig struct - Parse API_KEYS environment variable as comma-separated list in from_env - Add validate_api_key method to AuthConfig for key verification - Add X-API-Key header check in auth_middleware before JWT validation - Update comments to clarify development/testing mode for unauthenticated requests --- apps/charging-engine/src/auth.rs | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/apps/charging-engine/src/auth.rs b/apps/charging-engine/src/auth.rs index 73ffbb4..db142f4 100644 --- a/apps/charging-engine/src/auth.rs +++ b/apps/charging-engine/src/auth.rs @@ -17,12 +17,26 @@ pub struct Claims { #[derive(Clone)] pub struct AuthConfig { pub secret: String, + pub api_keys: Vec, } impl AuthConfig { pub fn from_env() -> Self { let secret = env::var("JWT_SECRET").unwrap_or_else(|_| "default_secret_key_change_in_production".to_string()); - Self { secret } + + // Parse API keys from comma-separated environment variable + let api_keys_env = env::var("API_KEYS").unwrap_or_else(|_| String::new()); + let api_keys: Vec = api_keys_env + .split(',') + .map(|s| s.trim().to_string()) + .filter(|s| !s.is_empty()) + .collect(); + + Self { secret, api_keys } + } + + pub fn validate_api_key(&self, api_key: &str) -> bool { + self.api_keys.iter().any(|key| key == api_key) } } @@ -65,6 +79,19 @@ pub async fn auth_middleware( .get("Authorization") .and_then(|h| h.to_str().ok()); + // Check for API key authentication + let api_key_header = request + .headers() + .get("X-API-Key") + .and_then(|h| h.to_str().ok()); + + if let Some(api_key) = api_key_header { + if config.validate_api_key(api_key) { + return Ok(next.run(request).await); + } + } + + // Check for JWT authentication if let Some(auth_header) = auth_header { if let Some(token) = auth_header.strip_prefix("Bearer ") { match validate_token(token, &config) { @@ -74,8 +101,7 @@ pub async fn auth_middleware( } } - // For now, allow requests without auth for packet-gateway integration + // Allow requests without auth for development/testing // In production, you would want to enable strict authentication - // or use API keys for service-to-service communication Ok(next.run(request).await) }