| """ |
| Auth Middleware — JWT Validation |
| """ |
| import os |
| import logging |
| from typing import Optional |
| from datetime import datetime, timedelta, timezone |
|
|
| from fastapi import Request, HTTPException, Depends |
| from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials |
| from jose import JWTError, jwt |
| from bson import ObjectId |
|
|
| from src.db import mongo |
|
|
| logger = logging.getLogger("llm_firewall.auth_middleware") |
|
|
| security = HTTPBearer() |
|
|
| SECRET_KEY = os.getenv("JWT_SECRET_KEY", "fallback_secret_key_please_change") |
| ALGORITHM = os.getenv("JWT_ALGORITHM", "HS256") |
| ACCESS_TOKEN_EXPIRE_MINUTES = int(os.getenv("ACCESS_TOKEN_EXPIRE_MINUTES", "43200")) |
|
|
|
|
| def create_access_token(data: dict, expires_delta: Optional[timedelta] = None): |
| to_encode = data.copy() |
| if expires_delta: |
| expire = datetime.now(timezone.utc) + expires_delta |
| else: |
| expire = datetime.now(timezone.utc) + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) |
| to_encode.update({"exp": expire}) |
| encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) |
| return encoded_jwt |
|
|
|
|
| async def validate_user_token(credentials: HTTPAuthorizationCredentials = Depends(security)) -> dict: |
| """ |
| Validate the JWT access token and return the user document. |
| Raises HTTPException on failure. |
| """ |
| token = credentials.credentials |
| try: |
| payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) |
| user_id_str: str = payload.get("sub") |
| if user_id_str is None: |
| raise HTTPException(status_code=401, detail="Invalid token payload") |
| |
| try: |
| user_id = ObjectId(user_id_str) |
| except Exception: |
| raise HTTPException(status_code=401, detail="Invalid user ID format in token") |
| |
| except JWTError: |
| raise HTTPException(status_code=401, detail="Could not validate credentials") |
| |
| users_collection = mongo.get_users_collection() |
| user = await users_collection.find_one({"_id": user_id}) |
| if user is None: |
| raise HTTPException(status_code=401, detail="User not found") |
| |
| return user |
|
|