54 lines
1.5 KiB
Python
54 lines
1.5 KiB
Python
"""Authentication middleware."""
|
|
from typing import Optional
|
|
from fastapi import Depends, HTTPException, status
|
|
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
|
from ..models import ClientKey
|
|
from ..services.auth import AuthService
|
|
|
|
security = HTTPBearer(auto_error=False)
|
|
|
|
|
|
async def get_current_client(
|
|
credentials: Optional[HTTPAuthorizationCredentials] = Depends(security)
|
|
) -> ClientKey:
|
|
"""Dependency to get and validate the current client.
|
|
|
|
Raises:
|
|
HTTPException: If authentication fails
|
|
|
|
Returns:
|
|
The validated ClientKey
|
|
"""
|
|
if not credentials:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
detail={"error": "Missing API key"}
|
|
)
|
|
|
|
client_key = await AuthService.validate_key(credentials.credentials)
|
|
|
|
if not client_key:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
detail={"error": "Invalid API key"}
|
|
)
|
|
|
|
if not client_key.is_active:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
detail={"error": "API key disabled"}
|
|
)
|
|
|
|
return client_key
|
|
|
|
|
|
class AuthMiddleware:
|
|
"""Authentication middleware for request processing."""
|
|
|
|
def __init__(self, exclude_paths: list[str] = None):
|
|
self.exclude_paths = exclude_paths or ["/health", "/docs", "/openapi.json"]
|
|
|
|
async def __call__(self, request, call_next):
|
|
# Middleware is handled via Depends in routes
|
|
return await call_next(request)
|