Files
bakery-ia/services/data/app/core/auth.py
2025-07-18 16:48:49 +02:00

73 lines
2.9 KiB
Python

from fastapi import HTTPException, Depends, status, Request
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
import httpx
import structlog
from typing import Dict, Any, Optional
from app.core.config import settings
logger = structlog.get_logger()
security = HTTPBearer(auto_error=False) # ✅ Don't auto-error, we'll handle manually
class AuthInfo:
"""Authentication information"""
def __init__(self, user_id: str, email: str, tenant_id: str, roles: list):
self.user_id = user_id
self.email = email
self.tenant_id = tenant_id
self.roles = roles
async def get_current_user(
request: Request,
credentials: Optional[HTTPAuthorizationCredentials] = Depends(security)
) -> AuthInfo:
"""Get current user from gateway headers or token verification"""
# ✅ OPTION 1: Check for gateway headers (preferred when using gateway)
user_id = request.headers.get("X-User-ID")
email = request.headers.get("X-User-Email")
tenant_id = request.headers.get("X-Tenant-ID")
roles_header = request.headers.get("X-User-Roles", "")
if user_id and email and tenant_id:
# Gateway already authenticated the user
roles = roles_header.split(",") if roles_header else ["user"]
logger.info("Authenticated via gateway headers", user_id=user_id, email=email)
return AuthInfo(user_id, email, tenant_id, roles)
# ✅ OPTION 2: Direct token verification (when not using gateway)
if not credentials:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Authentication required (no token or gateway headers)"
)
try:
async with httpx.AsyncClient(timeout=5.0) as client:
response = await client.post(
f"{settings.AUTH_SERVICE_URL}/api/v1/auth/verify",
headers={"Authorization": f"Bearer {credentials.credentials}"}
)
if response.status_code == 200:
user_data = response.json()
logger.info("Authenticated via direct token", user_id=user_data.get("user_id"))
return AuthInfo(
user_id=user_data["user_id"],
email=user_data["email"],
tenant_id=user_data["tenant_id"],
roles=user_data.get("roles", ["user"])
)
else:
logger.warning("Token verification failed", status_code=response.status_code)
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid authentication credentials"
)
except httpx.RequestError as e:
logger.error("Auth service unavailable", error=str(e))
raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
detail="Authentication service unavailable"
)