""" API Authentication Module ========================= Implements API key-based authentication for the FastAPI backend. """ import os import hashlib from typing import Optional from fastapi import Header, HTTPException, status class AuthManager: """Manages API key authentication and user identification.""" def __init__(self): """Initialize auth manager with API keys from environment.""" api_keys_str = os.environ.get("API_KEYS", "") self.valid_api_keys = set( key.strip() for key in api_keys_str.split(",") if key.strip() ) if not self.valid_api_keys: print("⚠️ WARNING: No API keys configured! Set API_KEYS environment variable.") else: print(f"✅ Auth Manager initialized with {len(self.valid_api_keys)} API key(s)") def derive_user_id(self, api_key: str) -> str: """ Derive a stable user ID from API key using SHA256. Args: api_key: The API key Returns: 12-character user ID derived from key hash """ hash_bytes = hashlib.sha256(api_key.encode()).digest() return hash_bytes.hex()[:12] def validate_api_key(self, api_key: Optional[str]) -> str: """ Validate API key and return user ID. Args: api_key: API key from request header Returns: user_id: Derived user identifier Raises: HTTPException: If API key is invalid or missing """ if not api_key: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Missing X-API-KEY header" ) if api_key not in self.valid_api_keys: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid API key" ) return self.derive_user_id(api_key) # Global auth manager instance auth_manager = AuthManager() async def get_current_user(x_api_key: Optional[str] = Header(None, alias="X-API-KEY")) -> str: """ FastAPI dependency for extracting authenticated user ID. Args: x_api_key: API key from X-API-KEY header Returns: user_id: Authenticated user identifier Raises: HTTPException: If authentication fails """ return auth_manager.validate_api_key(x_api_key)