""" Authentication middleware for API Gateway """ import aiohttp from fastapi import HTTPException, Request from typing import Optional, Dict, Any import logging logger = logging.getLogger(__name__) class AuthMiddleware: """Authentication middleware for validating tokens""" def __init__(self, token_service_url: str = "http://localhost:8001"): self.token_service_url = token_service_url async def verify_token(self, request: Request) -> Optional[Dict[str, Any]]: """ Verify authentication token from request headers Returns token payload if valid, raises HTTPException if invalid """ # Extract token from Authorization header auth_header = request.headers.get("Authorization") if not auth_header: raise HTTPException(status_code=401, detail="Authorization header required") if not auth_header.startswith("Bearer "): raise HTTPException(status_code=401, detail="Bearer token required") token = auth_header[7:] # Remove "Bearer " prefix try: # Validate token with token service async with aiohttp.ClientSession() as session: async with session.post( f"{self.token_service_url}/tokens/validate", json={"token": token}, timeout=aiohttp.ClientTimeout(total=5) ) as response: if response.status != 200: raise HTTPException(status_code=401, detail="Token validation failed") token_data = await response.json() if not token_data.get("valid"): error_msg = token_data.get("error", "Invalid token") raise HTTPException(status_code=401, detail=error_msg) # Token is valid, return decoded payload return token_data.get("decoded") except aiohttp.ClientError as e: logger.error(f"Token service connection error: {e}") raise HTTPException(status_code=503, detail="Authentication service unavailable") except HTTPException: raise except Exception as e: logger.error(f"Token verification error: {e}") raise HTTPException(status_code=500, detail="Authentication error") async def check_permissions(self, token_payload: Dict[str, Any], required_resources: list) -> bool: """ Check if token has required permissions for specific resources """ if not token_payload: return False # Get list of resources the token has access to token_resources = token_payload.get("list_of_resources", []) # Check if token has access to all required resources for resource in required_resources: if resource not in token_resources: return False return True def extract_user_info(self, token_payload: Dict[str, Any]) -> Dict[str, Any]: """Extract user information from token payload""" return { "name": token_payload.get("name"), "resources": token_payload.get("list_of_resources", []), "data_aggregation": token_payload.get("data_aggregation", False), "time_aggregation": token_payload.get("time_aggregation", False), "embargo": token_payload.get("embargo", 0), "expires_at": token_payload.get("exp") }