Files
bakery-ia/services/data/app/core/auth.py

73 lines
2.9 KiB
Python
Raw Normal View History

2025-07-18 16:48:49 +02:00
from fastapi import HTTPException, Depends, status, Request
2025-07-18 11:51:43 +02:00
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
import httpx
import structlog
2025-07-18 16:48:49 +02:00
from typing import Dict, Any, Optional
2025-07-18 11:51:43 +02:00
from app.core.config import settings
logger = structlog.get_logger()
2025-07-18 16:48:49 +02:00
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
2025-07-18 11:51:43 +02:00
2025-07-18 16:48:49 +02:00
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)"
)
2025-07-18 11:51:43 +02:00
try:
2025-07-18 16:48:49 +02:00
async with httpx.AsyncClient(timeout=5.0) as client:
2025-07-18 11:51:43 +02:00
response = await client.post(
f"{settings.AUTH_SERVICE_URL}/api/v1/auth/verify",
headers={"Authorization": f"Bearer {credentials.credentials}"}
)
if response.status_code == 200:
2025-07-18 16:48:49 +02:00
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"])
)
2025-07-18 11:51:43 +02:00
else:
2025-07-18 16:48:49 +02:00
logger.warning("Token verification failed", status_code=response.status_code)
2025-07-18 11:51:43 +02:00
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid authentication credentials"
)
2025-07-18 16:48:49 +02:00
except httpx.RequestError as e:
logger.error("Auth service unavailable", error=str(e))
2025-07-18 11:51:43 +02:00
raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
detail="Authentication service unavailable"
)